exponenta event banner

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

В этом примере показано, как импортировать предварительно подготовленный ONNX™ (Open Neural Network Exchange), который можно просматривать только один раз (YOLO) v2 [1], и использовать его для обнаружения объектов. После импорта сети ее можно развернуть на встраиваемых платформах с помощью графического процессора 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. Загрузить 'Model.onnx' модель из tiny_yolov2 папка, которая является сетью ONNX YOLO v2, предварительно подготовленной в наборе данных PASCAL VOC. Сеть может обнаруживать объекты из 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.

Определение полей привязки YOLO v2

В YOLO v2 для прогнозирования местоположения объекта используются предопределенные поля привязки. Поля привязки, используемые в импортированной сети, определяются в файле конфигурации сети Tiny YOLO v2 [5]. Якоря 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 = 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('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] Редмон, Джозеф и Али Фархади. «YOLO9000: лучше, быстрее, сильнее». В 2017 году Конференция 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] Эверингем, Марк, Люк Ван Гул, Кристофер К. И. Уильямс, Джон Уинн и Эндрю Зиссерман. «Вызов классов визуальных объектов Паскаля (VOC)». Международный журнал компьютерного зрения 88, № 2 (июнь 2010 года): 303-38. https://doi.org/10.1007/s11263-009-0275-4.

[5] «yolov2-крошечный-voc.cfg» https://github.com/pjreddie/darknet/blob/master/cfg/yolov2-tiny-voc.cfg.

См. также

Функции

Объекты

Связанные темы