Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

YOLO v2 深層学習を使用したマルチクラス オブジェクト検出

この例では、カスタム データ セットに対してマルチクラス オブジェクト検出を実行する方法を示します。

概要

深層学習は、YOLO v2、YOLO v4、YOLOX、SSD、Faster R-CNN などのロバストなマルチクラス オブジェクト検出器の学習に使用できる強力な機械学習手法です。この例では、関数trainYOLOv2ObjectDetectorを使用して、YOLO v2 マルチクラス オブジェクト検出器に学習させます。学習済みのオブジェクト検出器は、複数の屋内オブジェクトの検出や識別を行うことができます。YOLOX、YOLO v4、SSD、および Faster R-CNN などの他のマルチクラス オブジェクト検出器の学習の詳細については、深層学習を使用したオブジェクト検出入門およびオブジェクト検出器の選択を参照してください。

この例では、最初に、事前学習済みの YOLO v2 オブジェクト検出器を使用してイメージ内の複数のオブジェクトを検出する方法を示します。次に、オプションでデータ セットをダウンロードし、転移学習を使用してカスタム データ セットで YOLO v2 に学習させることができます。

事前学習済みのオブジェクト検出器の読み込み

事前学習済みの YOLO v2 オブジェクト検出器をダウンロードして読み込みます。

pretrainedURL = "https://www.mathworks.com/supportfiles/vision/data/yolov2IndoorObjectDetector23b.zip";
pretrainedFolder = fullfile(tempdir,"pretrainedNetwork");
pretrainedNetworkZip = fullfile(pretrainedFolder, "yolov2IndoorObjectDetector23b.zip"); 

if ~exist(pretrainedNetworkZip,"file")
    mkdir(pretrainedFolder);
    disp("Downloading pretrained network (6 MB)...");
    websave(pretrainedNetworkZip, pretrainedURL);
end

unzip(pretrainedNetworkZip, pretrainedFolder)

pretrainedNetwork = fullfile(pretrainedFolder, "yolov2IndoorObjectDetector.mat");
pretrained = load(pretrainedNetwork);
detector = pretrained.detector;

複数の屋内オブジェクトの検出

ターゲット クラスのオブジェクトを含むテスト イメージを読み取り、オブジェクト検出器を実行し、検出結果の注釈が付けられたイメージを表示します。

I = imread('indoorTest.jpg');
[bbox,score,label]  = detect(detector, I);

annotatedImage = insertObjectAnnotation(I,"rectangle",bbox,label,LineWidth=4,FontSize=24);
figure
imshow(annotatedImage)

学習用データの読み込み

この例では、Bishwo Adhikari [1] によって作成された屋内オブジェクト検出データ セットを使用します。データ セットは、fire extinguisher (消火器)、chair (椅子)、clock (時計)、trash bin (ゴミ箱)、screen (画面)、および printer (プリンター) の 7 つのクラスを含む屋内シーンから収集された 2213 個のラベル付きイメージで構成されています。各イメージには、これらのクラスのラベル付きインスタンスが 1 つ以上含まれています。データ セットが既にダウンロードされているかどうかを確認し、ダウンロードされていない場合は、websave を使用してダウンロードします。

dsURL = "https://zenodo.org/record/2654485/files/Indoor%20Object%20Detection%20Dataset.zip?download=1"; 
outputFolder = fullfile(tempdir,"indoorObjectDetection"); 
imagesZip = fullfile(outputFolder,"indoor.zip");

if ~exist(imagesZip,"file")   
    mkdir(outputFolder)       
    disp("Downloading 401 MB Indoor Objects Data Set images..."); 
    websave(imagesZip, dsURL);
    unzip(imagesZip, fullfile(outputFolder));  
end

データを読み込むための imageDatastore を作成します。

datapath = fullfile(outputFolder, "Indoor Object Detection Data Set");
imds = imageDatastore(datapath, IncludeSubfolders=true, FileExtensions=".jpg");

注釈とデータ セットの分割は annotationsIndoor.mat で提供されています。学習セット、検証セット、およびテスト セットに対応する注釈とインデックスを読み込みます。6 個のイメージにはラベルが関連付けられていないため、分割に含まれるのは 2213 個のイメージではなく合計 2207 個のイメージです。ラベルを含むイメージのインデックスを変数 cleanIdx に保存します。

data = load("annotationsIndoor.mat");
bbStore = data.BBstore;
trainingIdx = data.trainingIdx;
validationIdx = data.validationIdx;
testIdx = data.testIdx;
cleanIdx = data.idxs;

% Remove the 6 images with no labels.
imds = subset(imds,cleanIdx);
bbStore = subset(bbStore,cleanIdx);

学習データの解析

データをより深く理解するために、オブジェクト クラスのラベルとサイズの分布を解析します。この解析は、学習データを準備する方法や、この特定のデータ セット用にオブジェクト検出器を構成する方法を決定するのに役立つため、非常に重要です。

クラス分布の解析

関数 countEachLabel を使用して、データ セット内の境界ボックス クラス ラベルの分布を測定します。

tbl = countEachLabel(bbStore)
tbl=7×3 table
         Label          Count    ImageCount
    ________________    _____    __________

    exit                 545        504    
    fireextinguisher    1684        818    
    chair               1662        850    
    clock                280        277    
    trashbin             228        170    
    screen               115         94    
    printer               81         81    

カウントをクラスごとに可視化します。

bar(tbl.Label,tbl.Count)
ylabel("Frequency")

このデータ セット内のクラスは不均衡です。学習では上位クラスを優先してバイアスがかけられるため、正しく処理されていない場合は、こうした不均衡が学習プロセスに悪影響を及ぼす可能性があります。不均衡に対処するには、データを追加する、過小評価されているクラスをオーバーサンプリングする、損失関数を変更する、データ拡張を適用するなどの補完的な手法を 1 つ以上使用します。これらの各アプローチでは、最適な解決策を決定するために経験的な解析が必要です。後のセクションで、データ拡張の適用を行います。

オブジェクト サイズの解析およびオブジェクト検出器の選択

データ セット内のすべての境界ボックスとラベルを読み取り、境界ボックスの対角線の長さを計算します。

data = readall(bbStore);
bboxes = vertcat(data{:,1});
labels = vertcat(data{:,2});
diagonalLength = hypot(bboxes(:,3),bboxes(:,4));

オブジェクトのサイズをクラスごとにグループ化します。

G = findgroups(labels);
groupedDiagonalLength = splitapply(@(x){x},diagonalLength,G);

各クラスのオブジェクトの長さの分布を可視化します。

figure
classes = tbl.Label;
numClasses = numel(classes);
for i = 1:numClasses
    len = groupedDiagonalLength{i};
    x = repelem(i,numel(len),1);
    plot(x,len,"o");
    hold on
end
hold off
ylabel("Object extent (pixels)")

xticks(1:numClasses)
xticklabels(classes)

この可視化により、どのタイプのオブジェクト検出器を構成するかを決定するのに役立つ重要なデータ セット属性が示されます。

  1. 各クラス内のオブジェクト サイズのばらつき

  2. クラス間のオブジェクト サイズのばらつき

このデータ セットでは、クラス間のサイズの範囲にかなりのオーバーラップがあります。さらに、各クラス内でのサイズのばらつきはそれほど大きくありません。これは、単一のマルチクラス検出器に学習させて、さまざまなサイズのオブジェクトを処理できることを意味します。サイズ範囲がオーバーラップしていない場合、または各オブジェクト サイズの範囲の開きが 10 倍以上ある場合は、異なるサイズ範囲に対して複数の検出器に学習させる方がより実用的です。

サイズのばらつきに基づいて、どのオブジェクト検出器に学習させるかを決定できます。各クラス内のサイズのばらつきが小さい場合は、YOLO v2 などの単一スケールのオブジェクト検出器を使用します。各クラス内で大きなばらつきがある場合は、YOLO v4 や SSD などのマルチスケールのオブジェクト検出器を選択します。このデータ セットのオブジェクト サイズは同じ桁にとどまっているため、まずは YOLO v2 を使用します。高度なマルチスケール検出器はより高いパフォーマンスが得られる可能性がありますが、YOLO v2 と比較して学習により多くの時間とリソースを消費する可能性があります。単純なソリューションでパフォーマンス要件を満たせない場合、より高度な検出器を使用します。

サイズ分布情報を使用して学習イメージのサイズを選択します。通常、サイズは学習時にバッチ処理ができるよう固定されています。GPU メモリなどの学習環境のリソース制約に基づき、学習イメージのサイズによって、バッチ サイズをどの程度の大きさにするかが決まります。特に GPU を使用する場合は、より大きなデータ バッチを処理することでスループットが向上し、学習時間が短縮されます。ただし、元のデータのサイズが非常に小さいサイズに変更されている場合、学習イメージのサイズがオブジェクトの解像度に影響を与える可能性があります。

次のセクションでは、このデータ セットのサイズ解析情報を使用して YOLO v2 オブジェクト検出器を構成します。

YOLO v2 オブジェクト検出器アーキテクチャの定義

次の手順を使用して、YOLO v2 オブジェクト検出器を構成します。

  1. 転移学習用に事前学習済みの検出器を選択します。

  2. 学習イメージのサイズを選択します。

  3. オブジェクトの位置とクラスの予測に使用するネットワークの特徴を選択します。

  4. オブジェクト検出器の学習に使用する前処理済みデータからアンカー ボックスを推定します。

転移学習用に事前学習済みの Tiny YOLO v2 検出器を選択します。Tiny YOLO v2 は、大規模オブジェクト検出データ セットである COCO [2] で学習済みの軽量ネットワークです。事前学習済みのオブジェクト検出器から転移学習することで、ネットワークに最初から学習させる場合と比べて、学習にかかる時間が短縮されます。もう 1 つの事前学習済み検出器は、より大規模な Darknet-19 YOLO v2 事前学習済み検出器です。大規模なネットワークを実験する前に、より単純なネットワークから始めてパフォーマンスのベースラインを確立することを検討してください。Tiny または Darknet-19 YOLO v2 の事前学習済み検出器を使用するには、Computer Vision Toolbox™ Model for YOLO v2 Object Detection が必要です。

pretrainedDetector = yolov2ObjectDetector("tiny-yolov2-coco");

次に、YOLO v2 の学習イメージのサイズを選択します。学習イメージのサイズを選択するときは、次のサイズ パラメーターを考慮します。

  1. オブジェクト サイズの分布およびイメージのサイズ変更がオブジェクト サイズに与える影響。

  2. 選択したサイズでデータをバッチ処理するために必要な計算リソース。

  3. ネットワークに必要な最小入力サイズ。

事前学習済みの Tiny YOLO v2 ネットワークの入力サイズを決定します。

pretrainedDetector.Network.Layers(1).InputSize

屋内オブジェクト検出データ セット内のイメージのサイズは [720 1024 3] です。前のセクションで行ったオブジェクト解析に基づくと、最小のオブジェクトは約 20x20 ピクセルです。

この例を実行する際の精度と計算コストのバランスを維持するため、サイズを [720 720 3] に指定します。このサイズにすることで、イメージのサイズを小さくしても、このデータ セット内のオブジェクトの空間解像度に大きな影響が及ばなくなります。この例を独自のデータ セットに適用する場合は、データに基づいて学習イメージのサイズを変更しなければなりません。最適な入力サイズを決定するには、経験的な解析が必要です。

inputSize = [720 720 3];

transform を使用して、イメージと境界ボックスのサイズを変更する前処理関数を適用します。さらに、境界ボックスをサニタイズして有効な形状に変換します。

preprocessedData = transform(ds,@(data)resizeImageAndLabel(data, inputSize));

前処理したイメージとボックス ラベルの 1 つを表示して、サイズ変更したイメージ内のオブジェクトの特徴がまだ視認できることを確認します。

data = preview(preprocessedData);
I = data{1};
bbox = data{2};
label = data{3};
imshow(I)
showShape("rectangle", bbox, Label=label)

YOLO v2 は、1 つのネットワーク層から抽出された特徴を使用してイメージ内のオブジェクトの位置とクラスを予測する、単一スケールの検出器です。特徴抽出層は、深層学習ベースのオブジェクト検出器の重要なハイパーパラメーターです。特徴抽出層を選択するときは、データ セット内のオブジェクト サイズの範囲に適した空間解像度で特徴を出力する層を選択します。

オブジェクト検出に使用されるほとんどのネットワークでは、データがネットワークを流れる際、特徴量が 2 のべき乗で空間的にダウンサンプリングされます。たとえば、ネットワークには、特定の入力サイズから開始して空間的に 4 分の 1、8 分の 1、16 分の 1、32 分の 1 にダウンサンプリングされた特徴マップを生成する層が含まれます。データ セット内のオブジェクトのサイズが小さい場合 (たとえば、10x10 ピクセル未満)、16 分の 1 および 32 分の 1 にダウンサンプリングされた特徴マップの空間解像度は、オブジェクト位置を正確に推定するのに十分でない可能性があります。逆に、オブジェクトが大きい場合、4 分の 1 または 8 分の 1 にダウンサンプリングされた特徴マップは、大きなオブジェクトのグローバル コンテキストを十分に符号化できない可能性があります。

このデータ セットでは、"layer_relu_5" という名前の層を選択します。この層の出力特徴マップは 16 分の 1 にダウンサンプリングされます。このダウンサンプリングの量は、空間分解能と抽出される特徴の強度との適切なトレードオフです (ネットワークでさらに抽出された特徴により、より強力なイメージの特徴が符号化されますが、空間分解能は低下します)。

featureLayer = "leaky_relu_5";

analyzeNetwork を使用して、Tiny YOLO v2 ネットワークを可視化し、16 分の 1 にダウンサンプリングされた特徴を出力する層の名前を決定できます。

次に、estimateAnchorBoxes を使用して、学習データからアンカー ボックスを推定します。選択した学習イメージのサイズに基づく推定値を取得するには、前処理済みデータからアンカー ボックスを推定しなければなりません。学習データからのアンカー ボックスの推定に記載されている手順を使用して、このデータ セットに適したアンカー ボックスの数を決定します。この手順に基づくと、5 つのアンカー ボックスを使用することが、計算コストと精度の間で適切なトレードオフになることがわかります。他のハイパーパラメーターと同様に、アンカー ボックスの数は経験的な解析を使用して最適化する必要があります。

numAnchors = 5;
aboxes = estimateAnchorBoxes(preprocessedData, numAnchors);

最後に、選択した学習イメージ サイズと推定したアンカー ボックスを使用して、転移学習用に 7 つのクラスで YOLO v2 を構成します。

numClasses = 7;
pretrainedNet = pretrainedDetector.Network;
lgraph = yolov2Layers(inputSize, numClasses, aboxes, pretrainedNet, featureLayer);

Deep Learning Toolbox™ の analyzeNetwork または DeepNetworkDesigner を使用して、ネットワークを可視化できます。

学習データの準備

再現性を得るために、rng を使用して乱数発生器をシード 0 で初期化し、関数 shuffle を使用してデータ セットをシャッフルします。

rng(0);
preprocessedData = shuffle(preprocessedData);

関数 subset を使用して、データ セットを学習、テスト、検証の各サブセットに分割します。

dsTrain = subset(preprocessedData,trainingIdx);
dsVal = subset(preprocessedData,validationIdx);
dsTest = subset(preprocessedData,testIdx);

データ拡張

データ拡張を使用して、学習の際に元のデータをランダムに変換することでネットワークの精度を向上させます。データ拡張では、ラベル付き学習サンプルの数を増やさずに、学習データをさらに多様化させます。transform を使用して、次の手順で学習データを拡張します。

  • イメージおよび関連するボックス ラベルを水平方向にランダムに反転。

  • イメージおよび関連するボックス ラベルをランダムにスケーリング。

  • イメージの色にジッターを付加。

augmentedTrainingData = transform(dsTrain, @augmentData);

学習イメージとボックス ラベルのうちの 1 つを表示します。

data = read(augmentedTrainingData);
I = data{1};
bbox = data{2};
label = data{3};
imshow(I)
showShape("rectangle", bbox, Label=label)

YOLO v2 オブジェクト検出器の学習

trainingOptions を使用してネットワーク学習オプションを指定します。

opts = trainingOptions("rmsprop",...
        InitialLearnRate=0.001,...
        MiniBatchSize=8,...
        MaxEpochs=10,...
        LearnRateSchedule="piecewise",...
        LearnRateDropPeriod=5,...
        VerboseFrequency=30, ...
        L2Regularization=0.001,...
        ValidationData=dsVal, ...
        ValidationFrequency=50, ...
        OutputNetwork="best-validation-loss");

これらの学習オプションは、実験マネージャーを使用して選択されました。実験マネージャーを使用したハイパーパラメーター調整の詳細については、Train Object Detectors in Experiment Managerを参照してください。

doTrainingtrue に設定した場合、関数trainYOLOv2ObjectDetectorを使用して YOLO v2 オブジェクト検出器に学習させます。

doTraining = false;
if doTraining
    [detector, info] = trainYOLOv2ObjectDetector(augmentedTrainingData,lgraph, opts);
end

この例は、24 GB メモリ搭載の NVIDIA™ GeForce RTX 3090 Ti GPU で検証済みです。この GPU を使用してこのネットワークに学習させるのに約 45 分かかりました。学習所要時間は使用するハードウェアによって異なります。GPU のメモリがこれより少ない場合、メモリ不足が発生する可能性があります。これが発生した場合は、関数 trainingOptions を使用して MiniBatchSize を減らします。

オブジェクト検出器の評価

テスト イメージで学習させたオブジェクト検出器を評価し、パフォーマンスを測定します。Computer Vision Toolbox™ には、平均適合率や対数平均ミス率などの一般的なメトリクスを測定するためのオブジェクト検出器評価関数 (evaluateObjectDetection) が用意されています。この例では、平均適合率 (AP) メトリクスを使用してパフォーマンスを評価します。平均適合率は、検出器が正しい分類を実行できること (適合率) と検出器がすべての関連オブジェクトを検出できること (再現率) を示す単一の数値です。

テスト データ セットに対して検出器を実行します。できるだけ多くのオブジェクトを検出するには、検出しきい値を低い値に設定します。これは、検出器の適合率を、再現率の値の全範囲にわたって評価するのに役立ちます。

detectionThreshold = 0.01;
results = detect(detector,dsTest, MiniBatchSize=8, Threshold=detectionThreshold);

evaluateObjectDetection を使用して、テスト セットの結果に関するオブジェクト検出メトリクスを計算します。この関数は、1 つ以上の Intersection Over Union (IoU) しきい値で検出器を評価します。IoU しきい値は、予測境界ボックスが真陽性としてカウントされるために必要な、予測境界ボックスとグラウンド トゥルース境界ボックスの間のオーバーラップ量を定義します。

iouThresholds = [0.5 0.75 0.9];
metrics = evaluateObjectDetection(results, dsTest, iouThresholds);

クラス メトリクス全体をリストし、平均適合率の平均 (mAP) を検査して、検出器のパフォーマンスがどの程度優れているかを確認します。

metrics.ClassMetrics 
ans=7×5 table
                        NumObjects      mAP           AP            Precision             Recall     
                        __________    _______    ____________    ________________    ________________

    chair                  168        0.60842    {3×1 double}    {3×13754 double}    {3×13754 double}
    clock                   23          0.551    {3×1 double}    {3×2744  double}    {3×2744  double}
    exit                    52        0.55121    {3×1 double}    {3×3149  double}    {3×3149  double}
    fireextinguisher       165         0.5417    {3×1 double}    {3×4787  double}    {3×4787  double}
    printer                  7        0.14627    {3×1 double}    {3×4588  double}    {3×4588  double}
    screen                   4        0.08631    {3×1 double}    {3×10175 double}    {3×10175 double}
    trashbin                17        0.26921    {3×1 double}    {3×7881  double}    {3×7881  double}

すべての IoU しきい値の平均適合率の値を棒グラフで可視化します。

figure
classAP = metrics.ClassMetrics{:,"AP"}';
classAP = [classAP{:}];
bar(classAP')
xticklabels(metrics.ClassNames)
ylabel("AP")
legend(string(iouThresholds) + " IoU")

プロットは、他のクラスに比べてサンプル数が少ない 3 つのクラス (printer、screen、および trash bin) では検出器のパフォーマンスが低かったことを示しています。高い IoU しきい値では、検出器のパフォーマンスも低下しています。これらの結果に基づいて、パフォーマンスを向上させる次のステップは、クラス分布の解析セクションで特定されたクラスの不均衡の問題に対処することです。クラスの不均衡に対処するには、その少数のクラスが含まれるイメージを追加するか、そのようなクラスが含まれるイメージを複製してデータ拡張を使用します。そのような拡張には追加の実験が必要であり、この例の範囲を超えています。

オブジェクトのサイズが検出器のパフォーマンスに与える影響

関数metricsByAreaを使用して、オブジェクト サイズが検出器のパフォーマンスに及ぼす影響を調査します。この関数は、指定した範囲のオブジェクト サイズに対して検出器メトリクスを計算します。用途に応じて、サイズ範囲の事前定義セットに基づいてオブジェクト サイズの範囲を定義することも、この例のように推定されたアンカー ボックスを使用することもできます。このアンカー ボックス推定メソッドでは、オブジェクトのサイズを自動的にクラスタリングし、データ中心のサイズ範囲セットを提供します。

検出器からアンカー ボックスを抽出し、それぞれの面積を計算し、面積を並べ替えます。

areas = prod(detector.AnchorBoxes,2);
areas = sort(areas);

計算した面積を使用して、面積の範囲の限界値を定義します。最後の範囲の上限は最大面積の 3 倍のサイズに設定しており、このデータ セット内のオブジェクトには十分です。

lowerLimit = [0;areas];
upperLimit = [areas; 3*areas(end)];
areaRanges = [lowerLimit upperLimit]

関数 metricsByArea を使用して、"chair" クラス用に定義したサイズ範囲全体にわたってオブジェクト検出メトリクスを評価します。

classes = string(detector.ClassNames);
areaMetrics = metricsByArea(metrics,areaRanges,ClassName=classes(3))
areaMetrics=6×6 table
           AreaRange            NumObjects      mAP           AP            Precision           Recall     
    ________________________    __________    _______    ____________    _______________    _______________

             0          2774         0              0    {3×1 double}    {3×152  double}    {3×152  double}
          2774          9177        19        0.51195    {3×1 double}    {3×578  double}    {3×578  double}
          9177         15916        11        0.21218    {3×1 double}    {3×2404 double}    {3×2404 double}
         15916         47799        43        0.72803    {3×1 double}    {3×6028 double}    {3×6028 double}
         47799    1.2472e+05        74        0.62831    {3×1 double}    {3×4174 double}    {3×4174 double}
    1.2472e+05    3.7415e+05        21        0.60897    {3×1 double}    {3×423  double}    {3×423  double}

NumObjects 列に、テスト データ セット内の面積範囲内にあるオブジェクトの数が表示されます。検出器は "chair" クラス全体で良好なパフォーマンスを示しているものの、他のサイズ範囲と比較して検出器の平均適合率が低いサイズ範囲があります。検出器がうまく機能していない範囲には、サンプルが 11 個しかありません。このサイズ範囲でのパフォーマンスを向上させるには、このサイズのサンプルをさらに追加するか、データ拡張を使用して一連のサイズ範囲全体にわたるさらに多くのサンプルを作成します。

検出器のパフォーマンスをさらに向上させる方法についてより深い洞察を得るために、他のクラスに対してこの手順を繰り返すことができます。

適合率メトリクスと再現率メトリクスの計算

最後に、適合率/再現率 (PR) 曲線と検出信頼度スコアを並べてプロットします。適合率/再現率曲線は、各クラスのさまざまな再現率レベルにおける検出器の適合率を示します。PR 曲線の隣に検出器スコアをプロットすることで、用途に適した適合率と再現率を達成する検出しきい値を選択できます。

クラスを選択し、そのクラスの適合率と再現率のメトリクスを抽出して、適合率/再現率曲線をプロットします。

class = classes(3);

% Extract precision and recall values.
precision = metrics.ClassMetrics{class,"Precision"};
recall = metrics.ClassMetrics{class,"Recall"};

% Plot precision/recall curves.
figure
tiledlayout(1,2)
nexttile
plot(recall{:}',precision{:}')
ylim([0 1])
xlim([0 1])
grid on
xlabel("Recall")
ylabel("Precision")
title(class + " Precision/Recall ")
legend(string(iouThresholds) + " IoU",Location="south")

テスト セットの検出結果からすべてのラベルとスコアを抽出し、選択したクラスに対応するスコアを並べ替えます。この方法では、適合率/再現率の値を計算する際に使用される順序と一致するようにスコアを並べ替え、適合率/再現率を可視化し、結果を並べてスコア表示できるようにします。

allLabels = vertcat(results{:,3}{:});
allScores = vertcat(results{:,2}{:});

classScores = allScores(allLabels == class);
classScores = [1;sort(classScores,'descend')];

"chair" クラスの適合率/再現率曲線の隣にスコアを可視化します。

nexttile
plot(recall{1,:}',classScores)
ylim([0 1])
xlim([0 1])
ylabel("Score")
xlabel("Recall")
grid on
title(class + " Detection Scores")

この Figure が示すように、検出しきい値によって適合率と再現率をトレードオフできます。用途に最適な適合率/再現率特性が得られるしきい値を選択します。たとえば、IoU しきい値が 0.5 の場合、検出しきい値を 0.4 に設定すると、"chair" クラスでは再現率レベル 0.9 で適合率 0.9 を達成できます。適合率/再現率の特性はクラスごとに異なる可能性があるため、最終的な検出しきい値を選択する前に、すべてのクラスの適合率/再現率曲線を解析します。

展開

検出器の学習と評価が完了したら、オプションで、GPU Coder™ を使用してコードを生成し、yolov2ObjectDetector を展開できます。詳細については、YOLO v2 を使用したオブジェクト検出のコードの生成 (GPU Coder)の例を参照してください。

まとめ

この例では、マルチクラス オブジェクト検出器の学習および評価を行う方法を示します。この例を独自のデータに適用する場合は、データ セット内のオブジェクト クラスとサイズ分布を注意深く評価してください。データによっては、最適な結果を得るために、異なるハイパーパラメーターを使用したり、YOLO v4 や YOLOX などの別のオブジェクト検出器を使用したりする必要があります。

サポート関数

function B = 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.
B = cell(size(A));

I = A{1};
sz = size(I);
if numel(sz)==3 && sz(3) == 3
    I = jitterColorHSV(I,...
        Contrast=0.2,...
        Hue=0,...
        Saturation=0.1,...
        Brightness=0.2);
end

% Randomly flip and scale image.
tform = randomAffine2d(XReflection=true, Scale=[1 1.1]);  
rout = affineOutputView(sz, tform, BoundsStyle="CenterOutput");    
B{1} = imwarp(I, tform, OutputView=rout);

% Sanitize boxes, if needed. This helper function is attached as a
% supporting file. Open the example in MATLAB to open this function.
A{2} = helperSanitizeBoxes(A{2});
    
% Apply same transform to boxes.
[B{2},indices] = bboxwarp(A{2}, tform, rout, OverlapThreshold=0.25);    
B{3} = A{3}(indices);
    
% Return original data only when all boxes are removed by warping.
if isempty(indices)
    B = A;
end
end
function data = resizeImageAndLabel(data,targetSize)
% Resize the images and scale the corresponding bounding boxes.

    scale = (targetSize(1:2))./size(data{1},[1 2]);
    data{1} = imresize(data{1},targetSize(1:2));
    data{2} = bboxresize(data{2},scale);

    data{2} = floor(data{2});
    imageSize = targetSize(1:2);
    boxes = data{2};
    % Set boxes with negative values to have value 1.
    boxes(boxes<=0) = 1;
    
    % Validate if bounding box in within image boundary.
    boxes(:,3) = min(boxes(:,3),imageSize(2) - boxes(:,1)-1);
    boxes(:,4) = min(boxes(:,4),imageSize(1) - boxes(:,2)-1);
    
    data{2} = boxes; 

end

参考文献

[1] Adhikari, Bishwo; Peltomaki, Jukka; Huttunen, Heikki. (2019).Indoor Object Detection Dataset [Data set]. 7th European Workshop on Visual Information Processing 2018 (EUVIP), Tampere, Finland.

[2] Lin, Tsung-Yi, Michael Maire, Serge Belongie, Lubomir Bourdev, Ross Girshick, James Hays, Pietro Perona, Deva Ramanan, C. Lawrence Zitnick, and Piotr Dollár. “Microsoft COCO: Common Objects in Context,” May 1, 2014. https://arxiv.org/abs/1405.0312v3.

参考

| | |