このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。
事前学習済みの ONNX YOLO v2 オブジェクト検出器のインポート
この例では、事前学習済みの ONNX™(Open Neural Network Exchange) You Only Look Once (YOLO) v2 [1] オブジェクト検出ネットワークをインポートし、このネットワークを使用してオブジェクトを検出する方法を説明します。ネットワークをインポートした後、GPU Coder™ を使用してこのネットワークを組み込みプラットフォームに展開したり、trainYOLOv2ObjectDetector
による転移学習を使用してカスタム データでこのネットワークに再学習させたりすることができます。
ONNX YOLO v2 ネットワークのダウンロード
事前学習済みの Tiny YOLO v2 ネットワークに関連するファイルをダウンロードします。
pretrainedURL = 'https://ssd.mathworks.com/supportfiles/vision/deeplearning/models/yolov2/tiny_yolov2.tar'; pretrainedNetTar = 'yolov2Tiny.tar'; if ~exist(pretrainedNetTar,'file') disp('Downloading pretrained network (58 MB)...'); websave(pretrainedNetTar,pretrainedURL); end
Downloading pretrained network (58 MB)...
YOLO v2 ネットワークの解凍
ダウンロードしたファイルを解凍し、Tiny YOLO v2 ネットワークを展開します。tiny_yolov2
フォルダーから 'Model.onnx'
モデルを読み込みます。これは、PASCAL VOC データ セットで事前学習させた ONNX YOLO v2 ネットワークです。このネットワークは、20 種類のクラスに属するオブジェクトを検出できます [4]。
onnxfiles = untar(pretrainedNetTar);
pretrainedNet = 'tiny_yolov2/Model.onnx';
ONNX YOLO v2 層のインポート
関数 importONNXLayers
を使用して、ダウンロードしたネットワークをインポートします。
lgraph = importONNXLayers(pretrainedNet,'ImportWeights',true);
Warning: Imported layers have no output layer because ONNX files do not specify the network's output layer type. The layers will not be trainable until an output layer is added. Either add an output layer to the imported layers, or specify the output layer type using 'OutputLayerType' in the call to importONNXLayers.
この例では、インポートした層に出力層を追加するため、この警告は無視して構いません。YOLO v2 の変換層と出力層の追加の節で、インポートした層に YOLO v2 出力層と YOLO v2 変換層を追加する方法が説明されています。
この例のネットワークには、サポートされていない層は含まれていません。インポートしたいネットワークにサポートされていない層が含まれている場合、関数はそれらをプレースホルダー層としてインポートすることに注意してください。インポートしたネットワークを使用する前に、これらの層を置き換えなければなりません。プレースホルダー層の置き換えの詳細については、findPlaceholderLayers
(Deep Learning Toolbox) を参照してください。
YOLO v2 アンカー ボックスの定義
YOLO v2 は、事前定義されたアンカー ボックスを使用してオブジェクトの位置を予測します。インポートしたネットワークで使用されているアンカー ボックスは、Tiny YOLO v2 ネットワーク コンフィギュレーション ファイルで定義されています [5]。ONNX のアンカーは、最終畳み込み層の出力サイズ (13 x 13) に基づき定義されています。yolov2ObjectDetector
でアンカーを使用するには、ネットワークの入力サイズ (416 x 416) に合わせてアンカー ボックスのサイズを変更します。yolov2ObjectDetector
のアンカー ボックスは、[高さ, 幅] の形式で指定しなければなりません。
onnxAnchors = [1.08,1.19; 3.42,4.41; 6.63,11.38; 9.42,5.11; 16.62,10.52]; inputSize = lgraph.Layers(1,1).InputSize(1:2); lastActivationSize = [13,13]; upScaleFactor = inputSize./lastActivationSize; anchorBoxesTmp = upScaleFactor.* onnxAnchors; anchorBoxes = [anchorBoxesTmp(:,2),anchorBoxesTmp(:,1)];
検出層の重みの並べ替え
効率よく処理を行うには、インポートしたネットワークに含まれる最終畳み込み層の重みとバイアスを並べ替えて、yolov2ObjectDetector
が必要とする配置の活性化を取得しなければなりません。yolov2ObjectDetector
には、最終畳み込み層の特徴マップに含まれる 125 個のチャネルを次の配置で入力する必要があります。
チャネル 1 から 5 - アンカー 5 個の IoU の値
チャネル 6 から 10 - アンカー 5 個の X の値
チャネル 11 から 15 - アンカー 5 個の Y の値
チャネル 16 から 20 - アンカー 5 個の幅の値
チャネル 21 から 25 - アンカー 5 個の高さの値
チャネル 26 から 30 - アンカー 5 個のクラス 1 の確率値
チャネル 31 から 35 - アンカー 5 個のクラス 2 の確率値
チャネル 121 から 125 - アンカー 5 個のクラス 20 の確率値
ただし、サイズが 13 x 13 の最終畳み込み層では、活性化の配置が異なります。特徴マップ内の 25 個のチャネルは、それぞれ次のように対応しています。
チャネル 1 - X の値
チャネル 2 - Y の値
チャネル 3 - 幅の値
チャネル 4 - 高さの値
チャネル 5 - IoU の値
チャネル 6 - クラス 1 の確率値
チャネル 7 - クラス 2 の確率値
チャネル 25 - クラス 20 の確率値
この例の最後にリストされている補助関数 rearrangeONNXWeights
を使用して、インポートしたネットワークに含まれる最終畳み込み層の重みとバイアスを並べ替え、yolov2ObjectDetector
が必要とする形式の活性化を取得します。
weights = lgraph.Layers(end,1).Weights; bias = lgraph.Layers(end,1).Bias; layerName = lgraph.Layers(end,1).Name; numAnchorBoxes = size(onnxAnchors,1); [modWeights,modBias] = rearrangeONNXWeights(weights,bias,numAnchorBoxes);
並べ替えた重みとバイアスを使用して、インポートしたネットワークに含まれる最終畳み込み層の重みとバイアスを新しい畳み込み層の重みとバイアスに置き換えます。
filterSize = size(modWeights,[1 2]); numFilters = size(modWeights,4); modConvolution8 = convolution2dLayer(filterSize,numFilters,... 'Name',layerName,'Bias',modBias,'Weights',modWeights); lgraph = replaceLayer(lgraph,'convolution8',modConvolution8);
YOLO v2 の変換層と出力層の追加
YOLO v2 検出ネットワークは、YOLO v2 の変換層と出力層を必要とします。これら 2 つの層を作成し、それらを直列に積み重ね、最終畳み込み層に YOLO v2 変換層を接続します。
classNames = tinyYOLOv2Classes; layersToAdd = [ yolov2TransformLayer(numAnchorBoxes,'Name','yolov2Transform'); yolov2OutputLayer(anchorBoxes,'Classes',classNames,'Name','yolov2Output'); ]; lgraph = addLayers(lgraph, layersToAdd); lgraph = connectLayers(lgraph,layerName,'yolov2Transform');
インポートしたネットワークに含まれる ElementwiseAffineLayer
は、yolov2ObjectDetector
によって実行される前処理手順を複製します。そのため、インポートされたネットワークから ElementwiseAffineLayer
を削除します。
yoloScaleLayerIdx = find(... arrayfun( @(x)isa(x,'nnet.onnx.layer.ElementwiseAffineLayer'), ... lgraph.Layers)); if ~isempty(yoloScaleLayerIdx) for i = 1:size(yoloScaleLayerIdx,1) layerNames {i} = lgraph.Layers(yoloScaleLayerIdx(i,1),1).Name; end lgraph = removeLayers(lgraph,layerNames); lgraph = connectLayers(lgraph,'Input_image','convolution'); end
YOLO v2 オブジェクト検出器の作成
関数 assembleNetwork
を使用して層グラフを組み立て、関数 yolov2ObjectDetector
を使用して YOLO v2 オブジェクト検出器を作成します。
net = assembleNetwork(lgraph)
net = DAGNetwork with properties: Layers: [34×1 nnet.cnn.layer.Layer] Connections: [33×2 table] InputNames: {'Input_image'} OutputNames: {'yolov2Output'}
yolov2Detector = yolov2ObjectDetector(net)
yolov2Detector = yolov2ObjectDetector with properties: ModelName: 'importedNetwork' Network: [1×1 DAGNetwork] TrainingImageSize: [416 416] AnchorBoxes: [5×2 double] ClassNames: [aeroplane bicycle bird boat bottle bus car cat chair cow diningtable dog horse motorbike person pottedplant sheep sofa train tvmonitor]
インポートした YOLO v2 検出器を使用したオブジェクトの検出
インポートした検出器を使用して、テスト イメージ内のオブジェクトを検出します。結果を表示します。
I = imread('highway.png'); % Convert image to BGR format. Ibgr = cat(3,I(:,:,3),I(:,:,2),I(:,:,1)); [bboxes, scores, labels] = detect(yolov2Detector, Ibgr); detectedImg = insertObjectAnnotation(I, 'rectangle', bboxes, scores); figure imshow(detectedImg);
サポート関数
function [modWeights,modBias] = rearrangeONNXWeights(weights,bias,numAnchorBoxes) %rearrangeONNXWeights rearranges the weights and biases of an imported YOLO %v2 network as required by yolov2ObjectDetector. numAnchorBoxes is a scalar %value containing the number of anchors that are used to reorder the weights and %biases. This function performs the following operations: % * Extract the weights and biases related to IoU, boxes, and classes. % * Reorder the extracted weights and biases as expected by yolov2ObjectDetector. % * Combine and reshape them back to the original dimensions. weightsSize = size(weights); biasSize = size(bias); sizeOfPredictions = biasSize(3)/numAnchorBoxes; % Reshape the weights with regard to the size of the predictions and anchors. reshapedWeights = reshape(weights,prod(weightsSize(1:3)),sizeOfPredictions,numAnchorBoxes); % Extract the weights related to IoU, boxes, and classes. weightsIou = reshapedWeights(:,5,:); weightsBoxes = reshapedWeights(:,1:4,:); weightsClasses = reshapedWeights(:,6:end,:); % Combine the weights of the extracted parameters as required by % yolov2ObjectDetector. reorderedWeights = cat(2,weightsIou,weightsBoxes,weightsClasses); permutedWeights = permute(reorderedWeights,[1 3 2]); % Reshape the new weights to the original size. modWeights = reshape(permutedWeights,weightsSize); % Reshape the biases with regared to the size of the predictions and anchors. reshapedBias = reshape(bias,sizeOfPredictions,numAnchorBoxes); % Extract the biases related to IoU, boxes, and classes. biasIou = reshapedBias(5,:); biasBoxes = reshapedBias(1:4,:); biasClasses = reshapedBias(6:end,:); % Combine the biases of the extracted parameters as required by yolov2ObjectDetector. reorderedBias = cat(1,biasIou,biasBoxes,biasClasses); permutedBias = permute(reorderedBias,[2 1]); % Reshape the new biases to the original size. modBias = reshape(permutedBias,biasSize); end function classes = tinyYOLOv2Classes() % Return the class names corresponding to the pretrained ONNX tiny YOLO v2 % network. % % The tiny YOLO v2 network is pretrained on the Pascal VOC data set, % which contains images from 20 different classes [4]. classes = [ ... " aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car",... "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike",... "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]; end
参考文献
[1] Redmon, Joseph, and Ali Farhadi. "YOLO9000: Better, Faster, Stronger." In 2017 IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 6517–25. Honolulu, HI: IEEE, 2017. https://doi.org/10.1109/CVPR.2017.690.
[2] "Tiny YOLO v2 Model." https://github.com/onnx/models/tree/master/vision/object_detection_segmentation/tiny-yolov2
[3] "Tiny YOLO v2 Model License."
https://github.com/onnx/onnx/blob/master/LICENSE.
[4] Everingham, Mark, Luc Van Gool, Christopher K. I. Williams, John Winn, and Andrew Zisserman. "The Pascal Visual Object Classes (VOC) Challenge." International Journal of Computer Vision 88, no. 2 (June 2010): 303–38. https://doi.org/10.1007/s11263-009-0275-4.
[5] "yolov2-tiny-voc.cfg" https://github.com/pjreddie/darknet/blob/master/cfg/yolov2-tiny-voc.cfg.