exponenta event banner

Обнаружение транспортного средства с помощью YOLO v2, развернутого в FPGA

В этом примере показано, как обучить и развернуть детектор объектов YOLO v2.

Глубокое обучение - это мощный метод машинного обучения, который можно использовать для обучения надежных детекторов объектов. Существует несколько методов обнаружения объектов, включая более быстрый R-CNN, и вы смотрите только один раз (YOLO) v2. В этом примере выполняется подготовка детектора транспортного средства YOLO v2 с использованием trainYOLOv2ObjectDetector функция.

Загрузить набор данных

В этом примере используется небольшой набор данных транспортного средства, содержащий 295 изображений. Многие из этих изображений получены из наборов данных Caltech Cars 1999 и 2001, доступных на веб-сайте Caltech Computational Vision, созданном Пьетро Пероной и используемом с разрешения. Каждое изображение содержит один или два помеченных экземпляра транспортного средства. Небольшой набор данных полезен для изучения процедуры обучения YOLO v2, но на практике для обучения надежного детектора требуется больше маркированных изображений. Распакуйте изображения транспортного средства и загрузите данные об истинности грунта транспортного средства.

unzip vehicleDatasetImages.zip
data = load('vehicleDatasetGroundTruth.mat');
vehicleDataset = data.vehicleDataset;

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

% Add the fullpath to the local vehicle data folder.
vehicleDataset.imageFilename = fullfile(pwd,vehicleDataset.imageFilename);

Разбейте набор данных на обучающие и тестовые наборы. Выберите 60% данных для обучения, а остальные - для тестирования обученного детектора.

rng(0);
shuffledIndices = randperm(height(vehicleDataset));
idx = floor(0.6 * length(shuffledIndices) );
trainingDataTbl = vehicleDataset(shuffledIndices(1:idx),:);
testDataTbl = vehicleDataset(shuffledIndices(idx+1:end),:);

Использовать imageDatastore и boxLabelDataStore создание хранилищ данных для загрузки данных изображения и метки во время обучения и оценки.

imdsTrain = imageDatastore(trainingDataTbl{:,'imageFilename'});
bldsTrain = boxLabelDatastore(trainingDataTbl(:,'vehicle'));

imdsTest = imageDatastore(testDataTbl{:,'imageFilename'});
bldsTest = boxLabelDatastore(testDataTbl(:,'vehicle'));

Объединение хранилищ данных меток изображений и полей.

trainingData = combine(imdsTrain,bldsTrain);
testData = combine(imdsTest,bldsTest);

Создание сети обнаружения объектов YOLO v2

Сеть обнаружения объектов YOLO v2 состоит из двух подсетей. Сеть извлечения элементов, за которой следует сеть обнаружения. Сеть извлечения функций обычно представляет собой предварительно обученный CNN (для получения более подробной информации см. Предварительно обученные глубокие нейронные сети). В этом примере для извлечения элементов используется AlexNet. Вы также можете использовать другие предварительно обученные сети, такие как StartNet v2 или ResNet-18 также могут использоваться в зависимости от требований приложений. Подсеть обнаружения является небольшим CNN по сравнению с сетью извлечения признаков и состоит из нескольких сверточных слоев и слоев, специфичных для YOLO v2.

Используйте yolov2Layers для автоматического создания сети обнаружения объектов YOLO v2 с предварительно подготовленной сетью извлечения функций AlexNet. yolov2Layers требуется указать несколько входов для параметризации сети YOLO v2:

  • Размер сетевого входа

  • Якорные ящики

  • Сеть извлечения элементов

Сначала укажите размер сетевого входа и количество классов. При выборе размера сетевого ввода учитывайте минимальный размер, требуемый самой сетью, размер обучающих изображений и вычислительные затраты, понесенные при обработке данных выбранного размера. Если это возможно, выберите размер сетевого ввода, близкий к размеру обучающего изображения и превышающий размер ввода, требуемый для сети. Чтобы уменьшить вычислительные затраты на выполнение примера, укажите размер сетевого входа [224 224 3], который является минимальным размером, необходимым для запуска сети.

inputSize = [224 224 3];

Определите количество обнаруживаемых классов объектов.

numClasses = width(vehicleDataset)-1;

Обратите внимание, что учебные изображения, используемые в этом примере, больше 224 на 224 и различаются по размеру, поэтому перед началом обучения необходимо изменить размер изображений на этапе предварительной обработки.

Далее используйте estimateAnchorBoxes оценить ящики привязки на основе размера объектов в данных обучения. Чтобы учесть изменение размеров изображений перед обучением, измените размер обучающих данных для оценки полей привязки. Использовать transform для предварительной обработки данных обучения, затем определите количество анкерных ящиков и оцените их. Изменение размера обучающих данных в соответствии с размером входного изображения сети с помощью функции поддержки yolo_preprocessData.

trainingDataForEstimation = transform(trainingData,@(data)yolo_preprocessData(data,inputSize));
numAnchors = 7;
[anchorBoxes, meanIoU] = estimateAnchorBoxes(trainingDataForEstimation, numAnchors)
anchorBoxes = 7×2

   145   126
    91    86
   161   132
    41    34
    67    64
   136   111
    33    23

meanIoU = 0.8651

Дополнительные сведения о выборе анкерных ящиков см. в разделах Оценка анкерных ящиков по учебным данным (панель инструментов компьютерного зрения) (Toolbox™ компьютерного зрения) и Анкерные ящики для обнаружения объектов (панель инструментов компьютерного зрения).

Теперь используйте alexnet для загрузки предварительно подготовленной модели AlexNet.

featureExtractionNetwork = alexnet
featureExtractionNetwork = 
  SeriesNetwork with properties:

         Layers: [25×1 nnet.cnn.layer.Layer]
     InputNames: {'data'}
    OutputNames: {'output'}

Выбрать 'relu5' в качестве слоя извлечения элементов для замены слоев после 'relu5' с подсетью обнаружения. Этот слой извлечения элементов выводит карты элементов, которые понижаются в 16 раз. Эта величина понижающей дискретизации является хорошим компромиссом между пространственным разрешением и прочностью выделенных признаков, поскольку признаки, извлеченные далее вниз по сети, кодируют более сильные признаки изображения за счет пространственного разрешения. Выбор оптимального слоя извлечения элементов требует эмпирического анализа.

featureLayer = 'relu5';

Создайте сеть обнаружения объектов YOLO v2..

lgraph = yolov2Layers(inputSize,numClasses,anchorBoxes,featureExtractionNetwork,featureLayer);

Можно визуализировать сеть с помощью analyzeNetwork или Deep Network Designer из Deep Learning Toolbox™.

Если требуется дополнительный контроль над сетевой архитектурой YOLO v2, используйте Deep Network Designer для разработки сети обнаружения YOLO v2 вручную. Дополнительные сведения см. в разделе Проектирование сети обнаружения YOLO v2 (панель инструментов компьютерного зрения).

Увеличение объема данных

Увеличение данных используется для повышения точности сети путем случайного преобразования исходных данных во время обучения. С помощью увеличения данных можно добавить большее разнообразие к обучающим данным без фактического увеличения количества маркированных обучающих образцов.

Использовать transform для увеличения обучающих данных путем случайного разворота изображения и связанных меток полей по горизонтали. Обратите внимание, что увеличение данных не применяется к данным тестирования и проверки. В идеале, данные тестирования и проверки должны быть репрезентативными для исходных данных и оставлены неизмененными для объективной оценки.

augmentedTrainingData = transform(trainingData,@yolo_augmentData);

Предпроцессные данные обучения и детектор объектов канала YOLO v2

Предварительная обработка дополненных данных обучения и данных проверки для подготовки к обучению.

preprocessedTrainingData = transform(augmentedTrainingData,@(data)yolo_preprocessData(data,inputSize));

Использовать trainingOptions для указания параметров сетевого обучения. Набор 'ValidationData' к предварительно обработанным данным проверки. Набор 'CheckpointPath' во временное место. Это позволяет экономить частично обученные детекторы в процессе обучения. Если обучение прервано, например, из-за отключения питания или сбоя системы, вы можете возобновить обучение с сохраненной контрольной точки.

options = trainingOptions('sgdm', ...
        'MiniBatchSize', 16, ....
        'InitialLearnRate',1e-3, ...
        'MaxEpochs',20,...
        'CheckpointPath', tempdir, ...
        'Shuffle','never');

Использовать trainYOLOv2ObjectDetector функция для обучения детектора объекта YOLO v2.

[detector,info] = trainYOLOv2ObjectDetector(preprocessedTrainingData,lgraph,options);
*************************************************************************
Training a YOLO v2 Object Detector for the following object classes:

* vehicle

Training on single CPU.
Initializing input data normalization.
|========================================================================================|
|  Epoch  |  Iteration  |  Time Elapsed  |  Mini-batch  |  Mini-batch  |  Base Learning  |
|         |             |   (hh:mm:ss)   |     RMSE     |     Loss     |      Rate       |
|========================================================================================|
|       1 |           1 |       00:00:02 |         7.23 |         52.3 |          0.0010 |
|       5 |          50 |       00:00:43 |         0.99 |          1.0 |          0.0010 |
|      10 |         100 |       00:01:24 |         0.77 |          0.6 |          0.0010 |
|      14 |         150 |       00:02:03 |         0.64 |          0.4 |          0.0010 |
|      19 |         200 |       00:02:41 |         0.57 |          0.3 |          0.0010 |
|      20 |         220 |       00:02:55 |         0.58 |          0.3 |          0.0010 |
|========================================================================================|
Detector training complete.
*************************************************************************

В качестве быстрого теста запустите детектор на одном тестовом изображении. Убедитесь, что размер изображения совпадает с размером учебных изображений.

I = imread(testDataTbl.imageFilename{2});
I = imresize(I,inputSize(1:2));
[bboxes,scores] = detect(detector,I);

Просмотрите результаты.

I_new = insertObjectAnnotation(I,'rectangle',bboxes,scores);
figure
imshow(I_new)

Загрузить предварительно обученную сеть

Загрузите предварительно обученную сеть.

snet=detector.Network;
I_pre=yolo_pre_proc(I);

Использовать analyzeNetwork для получения информации о сетевых уровнях:

analyzeNetwork(snet)

Создание целевого объекта

Создайте целевой объект для целевого устройства с именем поставщика и интерфейсом для подключения целевого устройства к хост-компьютеру. Опции интерфейса - JTAG (по умолчанию) и Ethernet. Варианты поставщиков - Intel или Xilinx. Для программирования устройства используйте установленный пакет Xilinx Vivado Design Suite по Ethernet-соединению.

hTarget = dlhdl.Target('Xilinx', 'Interface', 'Ethernet');

Создание объекта рабочего процесса

Создание объекта dlhdl.Workflow класс. При создании объекта укажите сеть и имя битового потока. Укажите сохраненную сеть серии Pre-Trained, trainedNetNoCar, как сеть. Убедитесь, что имя битового потока соответствует типу данных и целевой плате FPGA. В этом примере целевой платой FPGA является ZCU102 плата Zynq UltraScale + MPSoC. Битовый поток использует один тип данных.

hW=dlhdl.Workflow('Network', snet, 'Bitstream', 'zcu102_single','Target',hTarget)
hW = 
  Workflow with properties:

            Network: [1×1 DAGNetwork]
          Bitstream: 'zcu102_single'
    ProcessorConfig: []
             Target: [1×1 dlhdl.Target]

Скомпилировать детектор объектов YOLO v2

Для компиляции snet series network, запустите функцию компиляции dlhdl.Workflow объект.

dn = hW.compile
### Compiling network for Deep Learning FPGA prototyping ...
### Targeting FPGA bitstream zcu102_single ...
### The network includes the following layers:

     1   'data'                Image Input                   224×224×3 images with 'zerocenter' normalization                                  (SW Layer)
     2   'conv1'               Convolution                   96 11×11×3 convolutions with stride [4  4] and padding [0  0  0  0]               (HW Layer)
     3   'relu1'               ReLU                          ReLU                                                                              (HW Layer)
     4   'norm1'               Cross Channel Normalization   cross channel normalization with 5 channels per element                           (HW Layer)
     5   'pool1'               Max Pooling                   3×3 max pooling with stride [2  2] and padding [0  0  0  0]                       (HW Layer)
     6   'conv2'               Grouped Convolution           2 groups of 128 5×5×48 convolutions with stride [1  1] and padding [2  2  2  2]   (HW Layer)
     7   'relu2'               ReLU                          ReLU                                                                              (HW Layer)
     8   'norm2'               Cross Channel Normalization   cross channel normalization with 5 channels per element                           (HW Layer)
     9   'pool2'               Max Pooling                   3×3 max pooling with stride [2  2] and padding [0  0  0  0]                       (HW Layer)
    10   'conv3'               Convolution                   384 3×3×256 convolutions with stride [1  1] and padding [1  1  1  1]              (HW Layer)
    11   'relu3'               ReLU                          ReLU                                                                              (HW Layer)
    12   'conv4'               Grouped Convolution           2 groups of 192 3×3×192 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    13   'relu4'               ReLU                          ReLU                                                                              (HW Layer)
    14   'conv5'               Grouped Convolution           2 groups of 128 3×3×192 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    15   'relu5'               ReLU                          ReLU                                                                              (HW Layer)
    16   'yolov2Conv1'         Convolution                   256 3×3×256 convolutions with stride [1  1] and padding 'same'                    (HW Layer)
    17   'yolov2Batch1'        Batch Normalization           Batch normalization with 256 channels                                             (HW Layer)
    18   'yolov2Relu1'         ReLU                          ReLU                                                                              (HW Layer)
    19   'yolov2Conv2'         Convolution                   256 3×3×256 convolutions with stride [1  1] and padding 'same'                    (HW Layer)
    20   'yolov2Batch2'        Batch Normalization           Batch normalization with 256 channels                                             (HW Layer)
    21   'yolov2Relu2'         ReLU                          ReLU                                                                              (HW Layer)
    22   'yolov2ClassConv'     Convolution                   42 1×1×256 convolutions with stride [1  1] and padding [0  0  0  0]               (HW Layer)
    23   'yolov2Transform'     YOLO v2 Transform Layer.      YOLO v2 Transform Layer with 7 anchors.                                           (SW Layer)
    24   'yolov2OutputLayer'   YOLO v2 Output                YOLO v2 Output with 7 anchors.                                                    (SW Layer)

### Optimizing series network: Fused 'nnet.cnn.layer.BatchNormalizationLayer' into 'nnet.cnn.layer.Convolution2DLayer'
2 Memory Regions created.

Skipping: data
Compiling leg: conv1>>yolov2ClassConv ...
Compiling leg: conv1>>yolov2ClassConv ... complete.
Skipping: yolov2Transform
Skipping: yolov2OutputLayer
Creating Schedule...
......
Creating Schedule...complete.
Creating Status Table...
.....
Creating Status Table...complete.
Emitting Schedule...
.....
Emitting Schedule...complete.
Emitting Status Table...
.......
Emitting Status Table...complete.

### Allocating external memory buffers:

          offset_name          offset_address    allocated_space 
    _______________________    ______________    ________________

    "InputDataOffset"           "0x00000000"     "24.0 MB"       
    "OutputResultOffset"        "0x01800000"     "4.0 MB"        
    "SchedulerDataOffset"       "0x01c00000"     "0.0 MB"        
    "SystemBufferOffset"        "0x01c00000"     "28.0 MB"       
    "InstructionDataOffset"     "0x03800000"     "4.0 MB"        
    "ConvWeightDataOffset"      "0x03c00000"     "16.0 MB"       
    "EndOffset"                 "0x04c00000"     "Total: 76.0 MB"

### Network compilation complete.
dn = struct with fields:
             weights: [1×1 struct]
        instructions: [1×1 struct]
           registers: [1×1 struct]
    syncInstructions: [1×1 struct]

Программирование битового потока на FPGA и загрузка веса сети

Для развертывания сети на оборудовании Zynq ® UltraScale+™ MPSoC ZCU102 запустите функцию развертывания dlhdl.Workflow объект. Эта функция использует выходные данные функции компиляции для программирования платы FPGA с помощью файла программирования. Функция также загружает веса сети и смещения. Функция развертывания проверяет наличие инструмента Xilinx Vivado и поддерживаемой версии инструмента. Затем он начинает программировать устройство FPGA с помощью битового потока, отображает сообщения о ходе выполнения и время, необходимое для развертывания сети.

hW.deploy
### FPGA bitstream programming has been skipped as the same bitstream is already loaded on the target FPGA.
### Loading weights to Conv Processor.
### Conv Weights loaded. Current time is 20-Dec-2020 15:26:28

Загрузить примерное изображение и выполнить прогнозирование

Выполните функцию прогнозирования на dlhdl.Workflow и отобразите результат:

[prediction, speed] = hW.predict(I_pre,'Profile','on');
### Finished writing input activations.
### Running single input activations.


              Deep Learning Processor Profiler Performance Results

                   LastFrameLatency(cycles)   LastFrameLatency(seconds)       FramesNum      Total Latency     Frames/s
                         -------------             -------------              ---------        ---------       ---------
Network                    8615567                  0.03916                       1            8615567             25.5
    conv1                  1357049                  0.00617 
    norm1                   569406                  0.00259 
    pool1                   205869                  0.00094 
    conv2                  2207222                  0.01003 
    norm2                   360973                  0.00164 
    pool2                   197444                  0.00090 
    conv3                   976419                  0.00444 
    conv4                   761188                  0.00346 
    conv5                   521782                  0.00237 
    yolov2Conv1             660213                  0.00300 
    yolov2Conv2             661162                  0.00301 
    yolov2ClassConv         136816                  0.00062 
 * The clock frequency of the DL processor is: 220MHz

Отображение результатов прогнозирования.

[bboxesn, scoresn, labelsn] = yolo_post_proc(prediction,I_pre,anchorBoxes,{'Vehicle'});
I_new3 = insertObjectAnnotation(I,'rectangle',bboxesn,scoresn);
figure
imshow(I_new3)