В этом примере показано, как обучить одиночный детектор (SSD).
Глубокое обучение - это мощный метод машинного обучения, который автоматически изучает особенности изображения, необходимые для задач обнаружения. Существует несколько методов обнаружения объектов с помощью глубокого обучения, таких как более быстрый R-CNN, однократный просмотр (YOLO v2) и твердотельный накопитель. В этом примере выполняется подготовка детектора автомобиля SSD с помощью trainSSDObjectDetector функция. Дополнительные сведения см. в разделе Обнаружение объектов.
Загрузите предварительно обученный детектор, чтобы избежать необходимости ждать завершения обучения. Если вы хотите обучить детектор, установите doTraining переменной true.
doTraining = false; if ~doTraining && ~exist('ssdResNet50VehicleExample_20a.mat','file') disp('Downloading pretrained detector (44 MB)...'); pretrainedURL = 'https://www.mathworks.com/supportfiles/vision/data/ssdResNet50VehicleExample_20a.mat'; websave('ssdResNet50VehicleExample_20a.mat',pretrainedURL); end
Downloading pretrained detector (44 MB)...
В этом примере используется небольшой набор данных транспортного средства, содержащий 295 изображений. Многие из этих изображений получены из наборов данных Caltech Cars 1999 и 2001, доступных на веб-сайте Caltech Computational Vision, созданном Пьетро Пероной и используемом с разрешения. Каждое изображение содержит один или два помеченных экземпляра транспортного средства. Небольшой набор данных полезен для изучения процедуры обучения SSD, но на практике для обучения надежного детектора требуется больше маркированных изображений.
unzip vehicleDatasetImages.zip data = load('vehicleDatasetGroundTruth.mat'); vehicleDataset = data.vehicleDataset;
Данные обучения хранятся в таблице. Первый столбец содержит путь к файлам изображений. Остальные столбцы содержат метки окупаемости инвестиций для транспортных средств. Просмотрите первые несколько строк данных.
vehicleDataset(1:4,:)
ans=4×2 table
imageFilename vehicle
_________________________________ _________________
{'vehicleImages/image_00001.jpg'} {[220 136 35 28]}
{'vehicleImages/image_00002.jpg'} {[175 126 61 45]}
{'vehicleImages/image_00003.jpg'} {[108 120 45 33]}
{'vehicleImages/image_00004.jpg'} {[124 112 38 36]}
Разбейте набор данных на обучающий набор для обучения детектора и тестовый набор для оценки детектора. Выберите 60% данных для обучения. Используйте остальное для анализа.
rng(0); shuffledIndices = randperm(height(vehicleDataset)); idx = floor(0.6 * length(shuffledIndices) ); trainingData = vehicleDataset(shuffledIndices(1:idx),:); testData = vehicleDataset(shuffledIndices(idx+1:end),:);
Использовать imageDatastore и boxLabelDatastore для загрузки данных изображения и метки во время обучения и оценки.
imdsTrain = imageDatastore(trainingData{:,'imageFilename'});
bldsTrain = boxLabelDatastore(trainingData(:,'vehicle'));
imdsTest = imageDatastore(testData{:,'imageFilename'});
bldsTest = boxLabelDatastore(testData(:,'vehicle'));Объединение хранилищ данных меток изображений и полей.
trainingData = combine(imdsTrain,bldsTrain); 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)
Сеть обнаружения объектов SSD может рассматриваться как имеющая две подсети. Сеть извлечения элементов, за которой следует сеть обнаружения.
Сеть извлечения функций обычно представляет собой предварительно обученный CNN (для получения более подробной информации см. Предварительно обученные нейронные сети (Deep Learning Toolbox)). В этом примере для извлечения элементов используются ResNet-50. Другие предварительно обученные сети, такие как MobileNet v2 или ResNet-18 могут также использоваться в зависимости от основных эксплуатационных характеристик. Подсеть обнаружения является небольшим CNN по сравнению с сетью извлечения признаков и состоит из нескольких сверточных уровней и уровней, специфичных для SSD.
Используйте ssdLayers автоматически модифицировать предварительно подготовленную сеть ResNet-50 в сеть обнаружения объектов SSD. ssdLayers требуется указать несколько входов, которые параметризуют сеть SSD, включая размер сетевого входа и количество классов. При выборе размера сетевого ввода учитывайте размер обучающих изображений и вычислительные затраты, понесенные при обработке данных выбранного размера. Если это возможно, выберите размер сетевого ввода, близкий к размеру обучающего образа. Однако для снижения вычислительных затрат на выполнение этого примера размер сетевого ввода выбирается равным [300 300 3]. Во время обучения, trainSSDObjectDetector автоматически изменяет размер обучающих изображений на размер сетевого ввода.
inputSize = [300 300 3];
Определите количество обнаруживаемых классов объектов.
numClasses = width(vehicleDataset)-1;
Создайте сеть обнаружения объектов SSD.
lgraph = ssdLayers(inputSize, numClasses, 'resnet50');Можно визуализировать сеть с помощью analyzeNetwork или DeepNetworkDesigner от Deep Learning Toolbox™. Обратите внимание, что можно также создать пользовательский сетевой твердотельный накопитель послойно. Дополнительные сведения см. в разделе Создание сети обнаружения объектов SSD.
Увеличение данных используется для повышения точности сети путем случайного преобразования исходных данных во время обучения. С помощью увеличения данных можно добавить большее разнообразие к обучающим данным без фактического увеличения количества маркированных обучающих образцов. Использовать transform для увеличения данных обучения на
Случайное разворот изображения и связанных меток рамки по горизонтали.
Случайное масштабирование изображения, связанных меток полей.
Цвет изображения дрожания.
Обратите внимание, что увеличение данных не применяется к данным теста. В идеале тестовые данные должны быть репрезентативными для исходных данных и оставлены неизмененными для объективной оценки.
augmentedTrainingData = transform(trainingData,@augmentData);
Визуализация дополненных обучающих данных путем многократного чтения одного и того же изображения.
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));
Прочитайте предварительно обработанные данные обучения.
data = read(preprocessedTrainingData);
Отображение изображения и ограничивающих рамок.
I = data{1};
bbox = data{2};
annotatedImage = insertShape(I,'Rectangle',bbox);
annotatedImage = imresize(annotatedImage,2);
figure
imshow(annotatedImage)
Использовать trainingOptions для указания параметров сетевого обучения. Набор 'CheckpointPath' во временное место. Это позволяет экономить частично обученные детекторы в процессе обучения. Если обучение прервано, например, из-за отключения питания или сбоя системы, вы можете возобновить обучение с сохраненной контрольной точки.
options = trainingOptions('sgdm', ... 'MiniBatchSize', 16, .... 'InitialLearnRate',1e-1, ... 'LearnRateSchedule', 'piecewise', ... 'LearnRateDropPeriod', 30, ... 'LearnRateDropFactor', 0.8, ... 'MaxEpochs', 300, ... 'VerboseFrequency', 50, ... 'CheckpointPath', tempdir, ... 'Shuffle','every-epoch');
Использовать trainSSDObjectDetector функция для обучения детектора объекта SSD, если doTraining к true. В противном случае загрузите предварительно подготовленную сеть.
if doTraining % Train the SSD detector. [detector, info] = trainSSDObjectDetector(preprocessedTrainingData,lgraph,options); else % Load pretrained detector for the example. pretrained = load('ssdResNet50VehicleExample_20a.mat'); detector = pretrained.detector; end
Этот пример подтверждается графическим процессором NVIDIA™ Titan X с 12 ГБ памяти. Если на графическом процессоре меньше памяти, может не хватить памяти. Если это произойдет, опустите 'MiniBatchSize'с использованием trainingOptions функция. Обучение этой сети заняло около 2 часов. Время обучения зависит от используемого оборудования.
В качестве быстрого теста запустите детектор на одном тестовом изображении.
data = read(testData);
I = data{1,1};
I = imresize(I,inputSize(1:2));
[bboxes,scores] = detect(detector,I, 'Threshold', 0.4);Просмотрите результаты.
I = insertObjectAnnotation(I,'rectangle',bboxes,scores);
figure
imshow(I)
Оцените обученный детектор объектов на большом наборе изображений для измерения производительности. Computer Vision Toolbox™ предоставляет функции оценки детекторов объектов для измерения общих метрик, таких как средняя точность (evaluateDetectionPrecision) и средние по журналу показатели промахов (evaluateDetectionMissRate). Для этого примера используйте метрику средней точности для оценки производительности. Средняя точность обеспечивает одно число, которое включает в себя способность детектора делать правильные классификации (precision) и способность детектора находить все соответствующие объекты (recall).
Примените к тестовым данным то же преобразование предварительной обработки, что и к учебным данным. Обратите внимание, что увеличение данных не применяется к данным теста. Тестовые данные должны быть репрезентативными для исходных данных и оставляться неизмененными для объективной оценки.
preprocessedTestData = transform(testData,@(data)preprocessData(data,inputSize));
Запустите детектор на всех тестовых изображениях.
detectionResults = detect(detector, preprocessedTestData, 'Threshold', 0.4);Вычислите детектор объекта с помощью метрики средней точности.
[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))

После обучения и оценки детектора можно создать код для ssdObjectDetector с использованием графического процессора Coder™. Дополнительные сведения см. в разделе Создание кода для обнаружения объектов с помощью однокадрового многопоксового детектора.
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); % Sanitize boxes, if needed. A{2} = helperSanitizeBoxes(A{2}, sz); % 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. sz = size(data{1},[1 2]); scale = targetSize(1:2)./sz; data{1} = imresize(data{1},targetSize(1:2)); % Sanitize boxes, if needed. data{2} = helperSanitizeBoxes(data{2}, sz); % Resize boxes. data{2} = bboxresize(data{2},scale); end
[1] Лю, Вэй, Драгомир Ангуэлов, Думитру Эрхан, Кристиан Сегеди, Скотт Рид, Чэн Ян Фу и Александр К. Берг. «SSD: Однокадровый мультибоксовый детектор». 14-я Европейская конференция по компьютерному зрению, ECCV 2016. Спрингер Верлаг, 2016.
combine | estimateAnchorBoxes | evaluateDetectionPrecision | read | transform | analyzeNetwork (инструментарий для глубокого обучения)