YOLO v4 深層学習を使用したオブジェクトの検出
この例では、You Only Look Once version 4 (YOLO v4) 深層学習ネットワークを使用して、イメージ内のオブジェクトを検出する方法を説明します。この例では、次の作業を行います。
YOLO v4 オブジェクト検出ネットワークの学習、検証、テスト用のデータセットを構成。また、ネットワーク効率を向上させるため、学習データセットのデータ拡張を実行。
YOLO v4 オブジェクト検出ネットワークの学習で使用するため、学習データからアンカー ボックスを計算。
関数
yolov4ObjectDetectorを使用して YOLO v4 オブジェクト検出器を作成し、関数trainYOLOv4ObjectDetectorを使用して検出器の学習を実行。
この例では、イメージに含まれる車両を検出するための事前学習済みの YOLO v4 オブジェクト検出器についても説明します。この事前学習済みのネットワークは、バックボーン ネットワークとして tiny-yolov4-coco を使用し、車両データセットで学習を行っています。YOLO v4 オブジェクト検出ネットワークの詳細については、YOLO v4 入門を参照してください。
データセットの読み込み
この例では、295 個のイメージを含んだ小さな車両データセットを使用します。これらのイメージの多くは、Caltech の Cars 1999 データセットおよび Cars 2001 データセットからのものです (Caltech Computational Vision の Web サイトで入手可能)。Pietro Perona 氏によって作成されたもので、許可を得て使用しています。各イメージには、1 個または 2 個のラベル付けされた車両インスタンスが含まれています。小さなデータセットは YOLO v4 の学習手順を調べるうえで役立ちますが、実際にロバストな検出器に学習させるにはラベル付けされたイメージがより多く必要になります。
車両のイメージを解凍し、車両のグラウンド トゥルース データを読み込みます。
unzip vehicleDatasetImages.zip data = load("vehicleDatasetGroundTruth.mat"); vehicleDataset = data.vehicleDataset;
車両データは 2 列の table に保存されています。1 列目にはイメージ ファイルのパスが含まれ、2 列目には境界ボックスが含まれています。
データ セットの最初の数行を表示します。
vehicleDataset(1:4,:)
ans=4×2 table
'vehicleImages/image_00001.jpg' [220,136,35,28]
'vehicleImages/image_00002.jpg' [175,126,61,45]
'vehicleImages/image_00003.jpg' [108,120,45,33]
'vehicleImages/image_00004.jpg' [124,112,38,36]
ローカルの車両データ フォルダーへの絶対パスを追加します。
vehicleDataset.imageFilename = fullfile(pwd,vehicleDataset.imageFilename);
データセットは学習、検証、テスト用のセットに分割します。データの 60% を学習用に、10% を検証用に、残りを学習済みの検出器のテスト用に選択します。
rng("default");
shuffledIndices = randperm(height(vehicleDataset));
idx = floor(0.6 * length(shuffledIndices) );
trainingIdx = 1:idx;
trainingDataTbl = vehicleDataset(shuffledIndices(trainingIdx),:);
validationIdx = idx+1 : idx + 1 + floor(0.1 * length(shuffledIndices) );
validationDataTbl = vehicleDataset(shuffledIndices(validationIdx),:);
testIdx = validationIdx(end)+1 : length(shuffledIndices);
testDataTbl = vehicleDataset(shuffledIndices(testIdx),:);imageDatastore と boxLabelDatastore を使用し、学習中および評価中にイメージとラベル データを読み込むためのデータストアを作成します。
imdsTrain = imageDatastore(trainingDataTbl{:,"imageFilename"});
bldsTrain = boxLabelDatastore(trainingDataTbl(:,"vehicle"));
imdsValidation = imageDatastore(validationDataTbl{:,"imageFilename"});
bldsValidation = boxLabelDatastore(validationDataTbl(:,"vehicle"));
imdsTest = imageDatastore(testDataTbl{:,"imageFilename"});
bldsTest = boxLabelDatastore(testDataTbl(:,"vehicle"));イメージ データストアとボックス ラベル データストアを組み合わせます。
trainingData = combine(imdsTrain,bldsTrain); validationData = combine(imdsValidation,bldsValidation); testData = combine(imdsTest,bldsTest);
データ セットに以下のいずれかが含まれる場合、validateInputData を使用して、無効なイメージ、境界ボックス、またはラベルを検出します。
無効なイメージ形式または NaN 値を含むサンプル
ゼロ/NaN 値/Inf 値を含むか、空である境界ボックス
欠損ラベルまたは非カテゴリカル ラベル
境界ボックスの値は、有限の正の整数でなければならず、かつ NaN であってはなりません。境界ボックスの高さと幅の値は、正でなければならず、イメージ境界の内側に収まっていなければなりません。
validateInputData(trainingData); validateInputData(validationData); validateInputData(testData);
学習イメージとボックス ラベルのうちの 1 つを表示します。
data = read(trainingData);
I = data{1};
bbox = data{2};
annotatedImage = insertShape(I,"Rectangle",bbox);
annotatedImage = imresize(annotatedImage,2);
figure
imshow(annotatedImage)
reset(trainingData);
YOLO v4 オブジェクト検出器ネットワークの作成
学習に使用するネットワーク入力サイズを指定します。
inputSize = [416 416 3];
検出するオブジェクト クラスの名前を指定します。
className = "vehicle";関数estimateAnchorBoxesを使用して、学習データ内のオブジェクトのサイズに基づいてアンカー ボックスを推定します。学習前のイメージのサイズ変更を考慮するには、アンカー ボックスを推定する学習データのサイズを変更します。関数 transform を使用して学習データの前処理を行い、アンカー ボックスの数を定義してアンカー ボックスを推定します。補助関数 preprocessData を使用して、ネットワークの入力サイズに合わせて学習データのサイズを変更します。
rng("default")
trainingDataForEstimation = transform(trainingData,@(data)preprocessData(data,inputSize));
numAnchors = 6;
[anchors,meanIoU] = estimateAnchorBoxes(trainingDataForEstimation,numAnchors);すべての検出ヘッドで使用するアンカー ボックスとして、引数 anchorBoxes を指定します。アンカー ボックスは [Mx 1] の cell 配列として指定します。ここで、M は検出ヘッドの数を表します。各検出ヘッドは、anchors 引数に格納される [Nx 2] の行列で構成されます。ここで、N は使用するアンカーの数です。特徴マップのサイズに基づいて、各検出ヘッドの anchorBoxes を指定します。スケールが小さい場合は大きいアンカーを使用し、スケールが大きい場合は小さいアンカーを使用します。これを行うには、アンカーを面積ごとに降順に並べ替え、最初の 3 つを最初の検出ヘッドに割り当て、最後の 3 つを 2 番目の検出ヘッドに割り当てます。
area = anchors(:, 1).*anchors(:,2);
[~,idx] = sort(area,"descend");
anchors = anchors(idx,:);
anchorBoxes = {anchors(1:3,:)
anchors(4:6,:)};アンカー ボックスの選択の詳細については、学習データからのアンカー ボックスの推定 (Computer Vision Toolbox™) およびアンカー ボックスによるオブジェクトの検出を参照してください。
関数 yolov4ObjectDetector を使用して、YOLO v4 オブジェクト検出器を作成します。COCO データセットで学習させた事前学習済みの YOLO v4 検出ネットワークの名前を指定します。クラス名および推定されるアンカー ボックスを指定します。
detector = yolov4ObjectDetector("tiny-yolov4-coco",className,anchorBoxes,InputSize=inputSize);データ拡張の実行
学習精度を上げるため、データ拡張を実行します。関数 transform を使用して、カスタムのデータ拡張を学習データに適用します。補助関数 augmentData によって、入力データに以下の拡張が適用されます。
HSV 空間でのカラー ジッターの付加
水平方向のランダムな反転
10% のランダムなスケーリング
データ拡張は、テスト データと検証データには適用されないことに注意してください。理想的には、テスト データと検証データは元のデータを代表するもので、バイアスのない評価を行うために変更なしで使用されなければなりません。
augmentedTrainingData = transform(trainingData,@augmentData);
拡張された学習データのサンプルを読み取って表示します。
augmentedData = cell(4,1); for k = 1:4 data = read(augmentedTrainingData); augmentedData{k} = insertShape(data{1},"rectangle",data{2}); reset(augmentedTrainingData); end figure montage(augmentedData,BorderSize=10)

学習オプションの指定
trainingOptions を使用してネットワーク学習オプションを指定します。Adam ソルバーを使用して、一定の学習率 0.001 でオブジェクト検出器を 80 エポック学習させます。検証損失が最小となる学習済み検出器を得るには、OutputNetwork を "best-validation-loss" に設定します。ValidationData を検証データに設定し、ValidationFrequency を 1000 に設定します。ValidationFrequency を減らすとデータをより頻繁に検証できますが、学習時間が長くなります。ExecutionEnvironment を使用して、ネットワークの学習に使用するハードウェア リソースを決定します。ExecutionEnvironment の既定値は "auto" で、利用可能な場合は GPU が選択され、そうでない場合は CPU が選択されます。学習プロセス中に部分的に学習させた検出器を保存できるように、CheckpointPath を一時的な場所に設定します。停電やシステム障害などで学習が中断された場合に、保存したチェックポイントから学習を再開できます。
options = trainingOptions("adam", ... GradientDecayFactor=0.9, ... SquaredGradientDecayFactor=0.999, ... InitialLearnRate=0.001, ... LearnRateSchedule="none", ... MiniBatchSize=4, ... L2Regularization=0.0005, ... MaxEpochs=80, ... DispatchInBackground=true, ... ResetInputNormalization=true, ... Shuffle="every-epoch", ... VerboseFrequency=20, ... ValidationFrequency=1000, ... CheckpointPath=tempdir, ... ValidationData=validationData, ... OutputNetwork="best-validation-loss");
YOLO v4 オブジェクト検出器の学習
関数 trainYOLOv4ObjectDetector を使用して YOLO v4 オブジェクト検出器に学習させます。この例は、24 GB メモリ搭載の NVIDIA™ RTX A5000 で実行されます。この設定を使用してこのネットワークに学習させるのに約 33 分かかりました。学習時間は使用するハードウェアによって異なります。ネットワークに学習させる代わりに、Computer Vision Toolbox™ に用意されている事前学習済みの YOLO v4 オブジェクト検出器を使用することもできます。
補助関数 downloadPretrainedYOLOv4Detector を使用して、事前学習済みの検出器をダウンロードします。拡張した学習データで検出器に学習させるには、doTraining の値を true に設定します。
doTraining = false; if doTraining % Train the YOLO v4 detector. [detector,info] = trainYOLOv4ObjectDetector(augmentedTrainingData,detector,options); else % Load pretrained detector for the example. detector = downloadPretrainedYOLOv4Detector(); end
テスト イメージに対して検出器を実行します。
I = imread("highway.png");
[bboxes,scores,labels] = detect(detector,I);結果を表示します。
I = insertObjectAnnotation(I,"rectangle",bboxes,scores);
figure
imshow(I)
テスト セットを使用した検出器の評価
オブジェクト検出器アナライザー アプリを使用して、検出器の性能をグラウンド トゥルースと比較して可視化し、評価します。アプリは、テスト セットに対して検出器を実行し、平均適合率などのメトリクスを計算し、適合率-再現率曲線をプロットし、テスト セット内の各イメージに対する検出結果を表示します。グラウンド トゥルース データと正解の検出器予測および不正解の検出器予測を並べて可視化し、検出器による誤りが最も多いイメージをすばやく見つけ出して、パフォーマンスをより深く理解できます。たとえば、検出器が特定のシナリオで誤動作する場合、その特定のシナリオを含む追加データを使用して検出器に再学習させる必要があることを示している可能性があります。
objectDetectorAnalyzer(detector,testData)

[適合率-再現率曲線] タブを選択して、車両クラスの適合率-再現率曲線を表示します。曲線は、評価のためのオーバーラップしきい値が 0.5 の場合、検出器がテスト セットで良好なパフォーマンスを発揮することを示していますが、オーバーラップしきい値が 0.7 および 0.8 に増加するとパフォーマンスが低下します。曲線上の円マーカーは、検出器の操作点を示しています。適合率-再現率曲線上の操作点とは、検出器が達成する適合率と再現率のバランスを決定する、特定の検出スコアしきい値設定のことです。スコアしきい値スライダーを調整して、用途に最適な操作点を決定できます。

追加の検出メトリクスを確認するには、その他のタブをクリックします。
データセットおよびクラスの概要: データセット全体のパフォーマンスを、すべてのクラスにわたって要約します。
混同行列: クラスごとに、検出されたオブジェクトの数と検出されなかったオブジェクトの数を表示します。
面積別の検出: オブジェクト サイズごとに正しい検出結果と正しくない検出結果を可視化することで、オブジェクト サイズが原因で発生するエラーを特定できます。
評価メトリクスのカスタム可視化については、evaluateObjectDetection を参照してください。オブジェクト検出メトリクスの詳細については、<TODO Sasha トピックページへのリンクを入力> を参照してください。
サポート関数
データ拡張を実行するための補助関数。
function data = augmentData(A) % Apply random horizontal flipping, and random X/Y scaling. Boxes that get % scaled outside the bounds are clipped if the overlap is above 0.25. Also, % jitter image color. data = cell(size(A)); for ii = 1:size(A,1) I = A{ii,1}; bboxes = A{ii,2}; labels = A{ii,3}; sz = size(I); if numel(sz) == 3 && sz(3) == 3 I = jitterColorHSV(I,... contrast=0.0,... Hue=0.1,... Saturation=0.2,... Brightness=0.2); end % Randomly flip image. tform = randomAffine2d(XReflection=true,Scale=[1 1.1]); rout = affineOutputView(sz,tform,BoundsStyle="centerOutput"); I = imwarp(I,tform,OutputView=rout); % Apply same transform to boxes. [bboxes,indices] = bboxwarp(bboxes,tform,rout,OverlapThreshold=0.25); labels = labels(indices); % Return original data only when all boxes are removed by warping. if isempty(indices) data(ii,:) = A(ii,:); else data(ii,:) = {I,bboxes,labels}; end end end function data = preprocessData(data,targetSize) % Resize the images and scale the pixels to between 0 and 1. Also scale the % corresponding bounding boxes. for ii = 1:size(data,1) I = data{ii,1}; imgSize = size(I); bboxes = data{ii,2}; I = im2single(imresize(I,targetSize(1:2))); scale = targetSize(1:2)./imgSize(1:2); bboxes = bboxresize(bboxes,scale); data(ii,1:2) = {I,bboxes}; end end
事前学習済みの YOLO v4 オブジェクト検出器をダウンロードするための補助関数。
function detector = downloadPretrainedYOLOv4Detector() % Download a pretrained yolov4 detector. if ~exist("yolov4TinyVehicleExample_24a.mat", "file") if ~exist("yolov4TinyVehicleExample_24a.zip", "file") disp("Downloading pretrained detector..."); pretrainedURL = "https://ssd.mathworks.com/supportfiles/vision/data/yolov4TinyVehicleExample_24a.zip"; websave("yolov4TinyVehicleExample_24a.zip", pretrainedURL); end unzip("yolov4TinyVehicleExample_24a.zip"); end pretrained = load("yolov4TinyVehicleExample_24a.mat"); detector = pretrained.detector; end
参照
[1] Alexey Bochkovskiy, Chien-Yao Wang, and Hong-Yuan Mark Liao. “YOLOv4: Optimal Speed and Accuracy of Object Detection.” 2020, arXiv:2004.10934. https://arxiv.org/abs/2004.10934.
参考
アプリ
関数
yolov4ObjectDetector|trainYOLOv4ObjectDetector|yoloxObjectDetector|detect|evaluateObjectDetection|trainingOptions(Deep Learning Toolbox) |transform
トピック
- Object Detection in Large Satellite Imagery Using Deep Learning
- Detect Small Objects Using Tiled Training of YOLOX Network
- YOLOX ネットワークを使用したプリント基板の欠陥の検出
- YOLO v2 深層学習を使用したマルチクラス オブジェクト検出
- YOLO v4 入門
- オブジェクト検出器の選択
- 深層学習を使用したオブジェクト検出入門
- アンカー ボックスによるオブジェクトの検出
- MATLAB による深層学習 (Deep Learning Toolbox)
- 事前学習済みの深層ニューラル ネットワーク (Deep Learning Toolbox)