Обнаружение объектов Используя глубокое обучение YOLO v2

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

Глубокое обучение является мощным методом машинного обучения, который можно использовать, чтобы обучить устойчивые детекторы объектов. Несколько методов для обнаружения объектов существуют, включая Faster R-CNN и вы только смотрите однажды (YOLO) v2. Этот пример обучает детектор YOLO v2 транспортного средства с помощью trainYOLOv2ObjectDetector функция. Для получения дополнительной информации смотрите, что Обнаружение объектов использует Глубокое обучение (Computer Vision Toolbox).

Загрузите предварительно обученный детектор

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

doTraining = false;
if ~doTraining && ~exist('yolov2ResNet50VehicleExample_19b.mat','file')    
    disp('Downloading pretrained detector (98 MB)...');
    pretrainedURL = 'https://www.mathworks.com/supportfiles/vision/data/yolov2ResNet50VehicleExample_19b.mat';
    websave('yolov2ResNet50VehicleExample_19b.mat',pretrainedURL);
end

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

Этот пример использует набор данных небольшого транспортного средства, который содержит 295 изображений. Каждое изображение содержит один или два помеченных экземпляра транспортного средства. Маленький набор данных полезен для исследования метода обучения YOLO v2, но на практике, более помеченные изображения необходимы, чтобы обучить устойчивый детектор. Разархивируйте изображения транспортного средства и загрузите достоверные данные транспортного средства.

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

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

% Display first few rows of the data set.
vehicleDataset(1:4,:)
ans=4×2 table
              imageFilename                vehicle   
    _________________________________    ____________

    {'vehicleImages/image_00001.jpg'}    {1×4 double}
    {'vehicleImages/image_00002.jpg'}    {1×4 double}
    {'vehicleImages/image_00003.jpg'}    {1×4 double}
    {'vehicleImages/image_00004.jpg'}    {1×4 double}

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

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

rng(0);
shuffledIndices = randperm(height(vehicleDataset));
idx = floor(0.6 * length(shuffledIndices) );

trainingIdx = 1:idx;
trainingDataTbl = vehicleDataset(shuffledIndices(trainingIdx),:);

validationIdx = idx+1 : idx + 1 + floor(0.1 * length(shuffledIndices) );
validationDataTbl = vehicleDataset(shuffledIndices(validationIdx),:);

testIdx = validationIdx(end)+1 : length(shuffledIndices);
testDataTbl = vehicleDataset(shuffledIndices(testIdx),:);

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

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

imdsValidation = imageDatastore(validationDataTbl{:,'imageFilename'});
bldsValidation = boxLabelDatastore(validationDataTbl(:,'vehicle'));

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

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

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

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

data = read(trainingData);
I = data{1};
bbox = data{2};
annotatedImage = insertShape(I,'Rectangle',bbox);
annotatedImage = imresize(annotatedImage,2);
figure
imshow(annotatedImage)

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

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

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

  • Сетевой входной размер

  • Поля привязки

  • Сеть извлечения признаков

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

inputSize = [224 224 3];

Задайте количество классов объектов, чтобы обнаружить.

numClasses = width(vehicleDataset)-1;

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

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

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

   145   122
    81    76
   160   132
    41    34
    63    62
   103    97
    33    23

meanIoU = 0.8630

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

Теперь используйте resnet50 загружать предварительно обученную модель ResNet-50.

featureExtractionNetwork = resnet50;

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

featureLayer = 'activation_40_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,@augmentData);

Считайте то же изображение многократно и отобразите увеличенные обучающие данные.

% Visualize the augmented images.
augmentedData = cell(4,1);
for k = 1:4
    data = read(augmentedTrainingData);
    augmentedData{k} = insertShape(data{1},'Rectangle',data{2});
    reset(augmentedTrainingData);
end
figure
montage(augmentedData,'BorderSize',10)

Предварительно обработайте обучающие данные

Предварительно обработайте увеличенные обучающие данные и данные о валидации, чтобы подготовиться к обучению.

preprocessedTrainingData = transform(augmentedTrainingData,@(data)preprocessData(data,inputSize));
preprocessedValidationData = transform(validationData,@(data)preprocessData(data,inputSize));

Считайте предварительно обработанные обучающие данные.

data = read(preprocessedTrainingData);

Отобразите поля изображения и ограничительные рамки.

I = data{1};
bbox = data{2};
annotatedImage = insertShape(I,'Rectangle',bbox);
annotatedImage = imresize(annotatedImage,2);
figure
imshow(annotatedImage)

Обучите детектор объектов YOLO v2

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

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

Используйте trainYOLOv2ObjectDetector функция, чтобы обучить детектор объектов YOLO v2, если doTraining верно. В противном случае загрузите предварительно обученную сеть.

if doTraining       
    % Train the YOLO v2 detector.
    [detector,info] = trainYOLOv2ObjectDetector(preprocessedTrainingData,lgraph,options);
else
    % Load pretrained detector for the example.
    pretrained = load('yolov2ResNet50VehicleExample_19b.mat');
    detector = pretrained.detector;
end

Этот пример был проверен на Титане NVIDIA™ X графических процессоров с 12 Гбайт памяти. Если ваш графический процессор имеет меньше памяти, у можно закончиться память. Если это происходит, понизьте 'MiniBatchSize' использование trainingOptions функция. Обучение этой сети заняло приблизительно 7 минут с помощью этой настройки. Учебное время варьируется в зависимости от оборудования, которое вы используете.

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

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

Отобразите результаты.

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

Оцените детектор Используя набор тестов

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

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

preprocessedTestData = transform(testData,@(data)preprocessData(data,inputSize));

Запустите детектор на всех тестовых изображениях.

detectionResults = detect(detector, preprocessedTestData);

Оцените детектор объектов с помощью средней метрики точности.

[ap,recall,precision] = evaluateDetectionPrecision(detectionResults, preprocessedTestData);

Точность/отзыв (PR), который подсвечивает кривая, насколько точный детектор на различных уровнях отзыва. Идеальная точность 1 на всех уровнях отзыва. Использование большего количества данных может помочь улучшить среднюю точность, но может потребовать большего количества учебного времени. Постройте кривую PR.

figure
plot(recall,precision)
xlabel('Recall')
ylabel('Precision')
grid on
title(sprintf('Average Precision = %.2f',ap))

Генерация кода

Если детектор обучен и оценен, можно сгенерировать код для yolov2ObjectDetector использование GPU Coder™. Смотрите Генерацию кода для Обнаружения объектов при помощи (GPU Coder) пример YOLO v2 для получения дополнительной информации.

Вспомогательные Функции

function B = augmentData(A)
% Apply random horizontal flipping, and random X/Y scaling. Boxes that get
% scaled outside the bounds are clipped if the overlap is above 0.25. Also,
% jitter image color.
B = cell(size(A));

I = A{1};
sz = size(I);
if numel(sz)==3 && sz(3) == 3
    I = jitterColorHSV(I,...
        'Contrast',0.2,...
        'Hue',0,...
        'Saturation',0.1,...
        'Brightness',0.2);
end

% Randomly flip and scale image.
tform = randomAffine2d('XReflection',true,'Scale',[1 1.1]);
rout = affineOutputView(sz,tform,'BoundsStyle','CenterOutput');
B{1} = imwarp(I,tform,'OutputView',rout);

% Apply same transform to boxes.
[B{2},indices] = bboxwarp(A{2},tform,rout,'OverlapThreshold',0.25);
B{3} = A{3}(indices);

% Return original data only when all boxes are removed by warping.
if isempty(indices)
    B = A;
end
end

function data = preprocessData(data,targetSize)
% Resize image and bounding boxes to the targetSize.
scale = targetSize(1:2)./size(data{1},[1 2]);
data{1} = imresize(data{1},targetSize(1:2));
data{2} = bboxresize(data{2},scale);
end

Ссылки

[1] Redmon, Джозеф и Али Фархади. "YOLO9000: лучше, быстрее, более сильный". 2 017 конференций по IEEE по компьютерному зрению и распознаванию образов (CVPR). IEEE, 2017.