В этом примере показано, как импортировать предварительно обученный ONNX™ (Открытый Exchange Нейронной сети) сеть обнаружения объектов v2 [1] вы только смотрите однажды (YOLO) и использовать его, чтобы обнаружить объекты. После того, как вы импортируете сеть, можно развернуть ее во встроенные платформы с помощью GPU Coder™ или переобучить ее на пользовательских данных с помощью передачи обучения с trainYOLOv2ObjectDetector
.
Загрузите файлы, связанные с предварительно обученной Крошечной сетью 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)...
Разархивируйте и untar загруженный файл, чтобы извлечь Крошечную сеть YOLO v2. Загрузите 'model.onnx'
модель, которая является сетью ONNX YOLO v2, предварительно обученной на наборе данных ПАСКАЛЯ ВОКА. Сеть может обнаружить объекты от 20 различных классов [4].
pretrainedNetTar = gunzip(pretrainedNetZip); onnxfiles = untar(pretrainedNetTar{1}); pretrainedNet = onnxfiles{1,2};
Используйте 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 предопределенные поля привязки, чтобы предсказать объектное местоположение. Поля привязки, используемые в импортированной сети, заданы в Крошечном файле [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, преобразовывают слой к последнему слою свертки.
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
Соберите график слоев с помощью 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]
Используйте импортированный детектор, чтобы обнаружить объекты в тестовом изображении. Отобразите результаты.
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.