Импортируйте Предварительно обученный детектор объектов ONNX YOLO v2

В этом примере показано, как импортировать предварительно обученный ONNX™ (Открытый Exchange Нейронной сети) сеть обнаружения объектов v2 [1] вы только смотрите однажды (YOLO) и использовать его, чтобы обнаружить объекты. После того, как вы импортируете сеть, можно развернуть ее во встроенные платформы с помощью GPU Coder™ или переобучить ее на пользовательских данных с помощью передачи обучения с trainYOLOv2ObjectDetector.

Загрузите Сеть ONNX YOLO v2

Загрузите файлы, связанные с предварительно обученной Крошечной сетью YOLO v2 [2], [3].

pretrainedURL = 'https://onnxzoo.blob.core.windows.net/models/opset_8/tiny_yolov2/tiny_yolov2.tar.gz';
pretrainedNetZip = 'yolov2Tmp.tar.gz';
if ~exist(pretrainedNetZip,'file')
    disp('Downloading pretrained network (58 MB)...');
    websave(pretrainedNetZip,pretrainedURL);
end
Downloading pretrained network (58 MB)...

Извлеките Сеть YOLO v2

Разархивируйте и untar загруженный файл, чтобы извлечь Крошечную сеть YOLO v2. Загрузите 'model.onnx' модель, которая является сетью ONNX YOLO v2, предварительно обученной на наборе данных ПАСКАЛЯ ВОКА. Сеть может обнаружить объекты от 20 различных классов [4].

pretrainedNetTar = gunzip(pretrainedNetZip);
onnxfiles = untar(pretrainedNetTar{1});
pretrainedNet = onnxfiles{1,2};

Импортируйте слои 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 Transform и Output показывает, как добавить YOLO v2 выходной слой наряду со слоем YOLO v2 Transform к импортированным слоям.

Сеть в этом примере не содержит неподдерживаемых слоев. Обратите внимание на то, что, если сеть, которую вы хотите импортировать, не поддержала слои, функция импортирует их как слои заполнителя. Прежде чем можно будет использовать импортированную сеть, необходимо заменить эти слои. Для получения дополнительной информации о замене слоев заполнителя смотрите findPlaceholderLayers (Deep Learning Toolbox).

Задайте Поля Привязки к YOLO v2

Использование YOLO v2 предопределенные поля привязки, чтобы предсказать объектное местоположение. Поля привязки, используемые в импортированной сети, заданы в Крошечном файле [5] YOLO v2 конфигурации сети. Привязки ONNX заданы относительно выходного размера итогового слоя свертки, который является 13 13. Использовать привязки с yolov2ObjectDetector, измените размер полей привязки к сетевому входному размеру, который является 416 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 = round(upScaleFactor.* onnxAnchors);
anchorBoxes = [anchorBoxesTmp(:,2),anchorBoxesTmp(:,1)];

Переупорядочьте веса слоя обнаружения

Для эффективной обработки необходимо переупорядочить веса и смещения последнего слоя свертки в импортированной сети, чтобы получить активации в расположении что yolov2ObjectDetector требует. yolov2ObjectDetector ожидает 125 каналов карты функции последнего слоя свертки в следующем расположении:

  • Каналы 1 - 5 - значения IoU для пяти привязок

  • Каналы 6 - 10 - X значений для пяти привязок

  • Каналы 11 - 15 - Y значения для пяти привязок

  • Каналы 16 - 20 - значения Ширины для пяти привязок

  • Каналы 21 - 25 - значения Высоты для пяти привязок

  • Каналы 26 - 30 - значения вероятности Класса 1 для пяти привязок

  • Каналы 31 - 35 - значения вероятности Класса 2 для пяти привязок

  • Каналы 121 - 125 - значения вероятности Класса 20 для пяти привязок

Однако в последнем слое свертки, который имеет размер 13 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 преобразовал и YOLO v2 выходные слои. Создайте оба из этих слоев, сложите их последовательно и присоедините 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 функционируйте и создайте детектор объектов YOLO v2 с помощью yolov2ObjectDetector функция.

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('car1.jpg');
% Convert image to BGR format.
I = cat(3,I(:,:,3),I(:,:,2),I(:,:,1));
[bboxes, scores, labels] = detect(yolov2Detector, I);
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, Джозеф и Али Фархади. “YOLO9000: Лучше, Быстрее, Более сильный”. На 2 017 Конференциях по IEEE по Компьютерному зрению и Распознаванию образов (CVPR), 6517–25. Гонолулу, HI: IEEE, 2017. https://doi.org/10.1109/CVPR.2017.690.

[2] "Крошечная Модель YOLO v2". https://github.com/onnx/models/tree/master/vision/object_detection_segmentation/tiny-yolov2

[3] "Крошечная Лицензия Модели YOLO v2". https://github.com/onnx/onnx/blob/master/LICENSE.

[4] Everingham, Марк, Люк Ван Гул, Кристофер К. Ай. Уильямс, Джон Винн и Эндрю Зиссермен. “Проблема Классов визуального объекта (VOC) Паскаля”. Международный журнал Компьютерного зрения 88, № 2 (июнь 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.