exponenta event banner

Обнаружение транспортных средств с использованием сети DAG 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 (для получения более подробной информации см. Предварительно обученные глубокие нейронные сети). В этом примере для извлечения элементов используются ResNet-18. В зависимости от требований приложений можно также использовать другие предварительно обученные сети, такие как StartNet 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

Дополнительные сведения о выборе анкерных ящиков см. в разделах Оценка анкерных ящиков по учебным данным (панель инструментов компьютерного зрения) (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 (панель инструментов компьютерного зрения).

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

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

Использовать 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 |         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 класс. При создании объекта укажите сеть и имя битового потока. Укажите сохраненную сеть серии 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 '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]

Программирование битового потока на 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)