Обнаружение транспортных средств с использованием основанного на сети DAG YOLO v2 развертывания в FPGA

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

Глубокое обучение является мощным методом машинного обучения, который можно использовать для обучения устойчивых детекторов объектов. Существует несколько методов обнаружения объектов, включая Faster 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 (для получения дополнительной информации смотрите Pretrained Глубоких нейронных сетей). Этот пример использует ResNet-18 для редукции данных. Можно также использовать другие предварительно обученные сети, такие как MobileNet v2 или ResNet-50 в зависимости от требований приложения. Подсеть обнаружения является небольшой CNN по сравнению с сетью редукции данных и состоит из нескольких сверточных слоев и слоев, характерных для YOLO v2.

Используйте yolov2Layers функция для создания сети обнаружения объектов YOLO v2 автоматически задает предварительно обученную ResNet-18 редукции данных сеть. 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

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

Теперь используйте resnet18, чтобы загрузить предварительно обученную модель ResNet-18.

featureExtractionNetwork = resnet18;

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

featureLayer = 'res4b_relu';

Создайте сеть обнаружения объектов 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 (Computer Vision Toolbox).

Увеличение количества данных

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

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

augmentedTrainingData = transform(trainingData,@yolo_augmentData);

Предварительная обработка обучающих данных и Train детектора объектов 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 |         8.43 |         71.1 |          0.0010 |
|       5 |          50 |       00:01:26 |         0.71 |          0.5 |          0.0010 |
|      10 |         100 |       00:02:46 |         0.75 |          0.6 |          0.0010 |
|      14 |         150 |       00:04:04 |         0.53 |          0.3 |          0.0010 |
|      19 |         200 |       00:05:23 |         0.48 |          0.2 |          0.0010 |
|      20 |         220 |       00:05:53 |         0.57 |          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 класс. Когда вы создаете объект, задайте сеть и имя битового потока. Укажите сохраненную предварительно обученную последовательную сеть, 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 'zscore' normalization                          (SW Layer)
     2   'conv1'                 Convolution                64 7×7×3 convolutions with stride [2  2] and padding [3  3  3  3]     (HW Layer)
     3   'bn_conv1'              Batch Normalization        Batch normalization with 64 channels                                  (HW Layer)
     4   'conv1_relu'            ReLU                       ReLU                                                                  (HW Layer)
     5   'pool1'                 Max Pooling                3×3 max pooling with stride [2  2] and padding [1  1  1  1]           (HW Layer)
     6   'res2a_branch2a'        Convolution                64 3×3×64 convolutions with stride [1  1] and padding [1  1  1  1]    (HW Layer)
     7   'bn2a_branch2a'         Batch Normalization        Batch normalization with 64 channels                                  (HW Layer)
     8   'res2a_branch2a_relu'   ReLU                       ReLU                                                                  (HW Layer)
     9   'res2a_branch2b'        Convolution                64 3×3×64 convolutions with stride [1  1] and padding [1  1  1  1]    (HW Layer)
    10   'bn2a_branch2b'         Batch Normalization        Batch normalization with 64 channels                                  (HW Layer)
    11   'res2a'                 Addition                   Element-wise addition of 2 inputs                                     (HW Layer)
    12   'res2a_relu'            ReLU                       ReLU                                                                  (HW Layer)
    13   'res2b_branch2a'        Convolution                64 3×3×64 convolutions with stride [1  1] and padding [1  1  1  1]    (HW Layer)
    14   'bn2b_branch2a'         Batch Normalization        Batch normalization with 64 channels                                  (HW Layer)
    15   'res2b_branch2a_relu'   ReLU                       ReLU                                                                  (HW Layer)
    16   'res2b_branch2b'        Convolution                64 3×3×64 convolutions with stride [1  1] and padding [1  1  1  1]    (HW Layer)
    17   'bn2b_branch2b'         Batch Normalization        Batch normalization with 64 channels                                  (HW Layer)
    18   'res2b'                 Addition                   Element-wise addition of 2 inputs                                     (HW Layer)
    19   'res2b_relu'            ReLU                       ReLU                                                                  (HW Layer)
    20   'res3a_branch2a'        Convolution                128 3×3×64 convolutions with stride [2  2] and padding [1  1  1  1]   (HW Layer)
    21   'bn3a_branch2a'         Batch Normalization        Batch normalization with 128 channels                                 (HW Layer)
    22   'res3a_branch2a_relu'   ReLU                       ReLU                                                                  (HW Layer)
    23   'res3a_branch2b'        Convolution                128 3×3×128 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    24   'bn3a_branch2b'         Batch Normalization        Batch normalization with 128 channels                                 (HW Layer)
    25   'res3a'                 Addition                   Element-wise addition of 2 inputs                                     (HW Layer)
    26   'res3a_relu'            ReLU                       ReLU                                                                  (HW Layer)
    27   'res3a_branch1'         Convolution                128 1×1×64 convolutions with stride [2  2] and padding [0  0  0  0]   (HW Layer)
    28   'bn3a_branch1'          Batch Normalization        Batch normalization with 128 channels                                 (HW Layer)
    29   'res3b_branch2a'        Convolution                128 3×3×128 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    30   'bn3b_branch2a'         Batch Normalization        Batch normalization with 128 channels                                 (HW Layer)
    31   'res3b_branch2a_relu'   ReLU                       ReLU                                                                  (HW Layer)
    32   'res3b_branch2b'        Convolution                128 3×3×128 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    33   'bn3b_branch2b'         Batch Normalization        Batch normalization with 128 channels                                 (HW Layer)
    34   'res3b'                 Addition                   Element-wise addition of 2 inputs                                     (HW Layer)
    35   'res3b_relu'            ReLU                       ReLU                                                                  (HW Layer)
    36   'res4a_branch2a'        Convolution                256 3×3×128 convolutions with stride [2  2] and padding [1  1  1  1]  (HW Layer)
    37   'bn4a_branch2a'         Batch Normalization        Batch normalization with 256 channels                                 (HW Layer)
    38   'res4a_branch2a_relu'   ReLU                       ReLU                                                                  (HW Layer)
    39   'res4a_branch2b'        Convolution                256 3×3×256 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    40   'bn4a_branch2b'         Batch Normalization        Batch normalization with 256 channels                                 (HW Layer)
    41   'res4a'                 Addition                   Element-wise addition of 2 inputs                                     (HW Layer)
    42   'res4a_relu'            ReLU                       ReLU                                                                  (HW Layer)
    43   'res4a_branch1'         Convolution                256 1×1×128 convolutions with stride [2  2] and padding [0  0  0  0]  (HW Layer)
    44   'bn4a_branch1'          Batch Normalization        Batch normalization with 256 channels                                 (HW Layer)
    45   'res4b_branch2a'        Convolution                256 3×3×256 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    46   'bn4b_branch2a'         Batch Normalization        Batch normalization with 256 channels                                 (HW Layer)
    47   'res4b_branch2a_relu'   ReLU                       ReLU                                                                  (HW Layer)
    48   'res4b_branch2b'        Convolution                256 3×3×256 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    49   'bn4b_branch2b'         Batch Normalization        Batch normalization with 256 channels                                 (HW Layer)
    50   'res4b'                 Addition                   Element-wise addition of 2 inputs                                     (HW Layer)
    51   'res4b_relu'            ReLU                       ReLU                                                                  (HW Layer)
    52   'yolov2Conv1'           Convolution                256 3×3×256 convolutions with stride [1  1] and padding 'same'        (HW Layer)
    53   'yolov2Batch1'          Batch Normalization        Batch normalization with 256 channels                                 (HW Layer)
    54   'yolov2Relu1'           ReLU                       ReLU                                                                  (HW Layer)
    55   'yolov2Conv2'           Convolution                256 3×3×256 convolutions with stride [1  1] and padding 'same'        (HW Layer)
    56   'yolov2Batch2'          Batch Normalization        Batch normalization with 256 channels                                 (HW Layer)
    57   'yolov2Relu2'           ReLU                       ReLU                                                                  (HW Layer)
    58   'yolov2ClassConv'       Convolution                42 1×1×256 convolutions with stride [1  1] and padding [0  0  0  0]   (HW Layer)
    59   'yolov2Transform'       YOLO v2 Transform Layer.   YOLO v2 Transform Layer with 7 anchors.                               (SW Layer)
    60   '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'
5 Memory Regions created.

Skipping: data
Compiling leg: conv1>>pool1 ...
Compiling leg: conv1>>pool1 ... complete.
Compiling leg: res2a_branch2a>>res2a_branch2b ...
Compiling leg: res2a_branch2a>>res2a_branch2b ... complete.
Compiling leg: res2b_branch2a>>res2b_branch2b ...
Compiling leg: res2b_branch2a>>res2b_branch2b ... complete.
Compiling leg: res3a_branch1 ...
Compiling leg: res3a_branch1 ... complete.
Compiling leg: res3a_branch2a>>res3a_branch2b ...
Compiling leg: res3a_branch2a>>res3a_branch2b ... complete.
Compiling leg: res3b_branch2a>>res3b_branch2b ...
Compiling leg: res3b_branch2a>>res3b_branch2b ... complete.
Compiling leg: res4a_branch1 ...
Compiling leg: res4a_branch1 ... complete.
Compiling leg: res4a_branch2a>>res4a_branch2b ...
Compiling leg: res4a_branch2a>>res4a_branch2b ... complete.
Compiling leg: res4b_branch2a>>res4b_branch2b ...
Compiling leg: res4b_branch2a>>res4b_branch2b ... complete.
Compiling leg: yolov2Conv1>>yolov2ClassConv ...
Compiling leg: yolov2Conv1>>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"     "4.0 MB"        
    "SystemBufferOffset"        "0x02000000"     "28.0 MB"       
    "InstructionDataOffset"     "0x03c00000"     "4.0 MB"        
    "ConvWeightDataOffset"      "0x04000000"     "20.0 MB"       
    "EndOffset"                 "0x05400000"     "Total: 84.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]

Программируйте Bitstream на FPGA и загружайте сетевые веса

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

hW.deploy
### Programming FPGA Bitstream using Ethernet...
Downloading target FPGA device configuration over Ethernet to SD card ...
# Copied /tmp/hdlcoder_rd to /mnt/hdlcoder_rd
# Copying Bitstream hdlcoder_system.bit to /mnt/hdlcoder_rd
# Set Bitstream to hdlcoder_rd/hdlcoder_system.bit
# Copying Devicetree devicetree_dlhdl.dtb to /mnt/hdlcoder_rd
# Set Devicetree to hdlcoder_rd/devicetree_dlhdl.dtb
# Set up boot for Reference Design: 'AXI-Stream DDR Memory Access : 3-AXIM'

Downloading target FPGA device configuration over Ethernet to SD card done. The system will now reboot for persistent changes to take effect.


System is rebooting . . . . . .
### Programming the FPGA bitstream has been completed successfully.
### Loading weights to Conv Processor.
### Conv Weights loaded. Current time is 04-Jan-2021 13:59:03

Загрузите изображение примера и запустите предсказание

Выполните функцию предсказания на 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                   16974672                  0.07716                       1           16974672             13.0
    conv1                  2224187                  0.01011 
    pool1                   573166                  0.00261 
    res2a_branch2a          972763                  0.00442 
    res2a_branch2b          972632                  0.00442 
    res2a                   209363                  0.00095 
    res2b_branch2a          972674                  0.00442 
    res2b_branch2b          973107                  0.00442 
    res2b                   209914                  0.00095 
    res3a_branch1           538478                  0.00245 
    res3a_branch2a          747078                  0.00340 
    res3a_branch2b          904530                  0.00411 
    res3a                   104830                  0.00048 
    res3b_branch2a          904540                  0.00411 
    res3b_branch2b          904278                  0.00411 
    res3b                   104900                  0.00048 
    res4a_branch1           485804                  0.00221 
    res4a_branch2a          485923                  0.00221 
    res4a_branch2b          880309                  0.00400 
    res4a                    52446                  0.00024 
    res4b_branch2a          880071                  0.00400 
    res4b_branch2b          880065                  0.00400 
    res4b                    52456                  0.00024 
    yolov2Conv1             880210                  0.00400 
    yolov2Conv2             880375                  0.00400 
    yolov2ClassConv         179300                  0.00081 
 * 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)