В этом примере показано создание кода для приложения сегментации изображений, использующего глубокое обучение. Он использует codegen команда для генерации функции MEX, которая выполняет прогнозирование на объекте сети DAG для U-Net, сети глубокого обучения для сегментации изображения.
Для аналогичного примера, охватывающего сегментацию изображений с использованием U-Net без codegen см. раздел Семантическая сегментация многоспектральных изображений с использованием глубокого обучения (панель инструментов обработки изображений).
Необходимый
В этом примере создается CUDA MEX со следующими требованиями сторонних производителей.
Графический процессор NVIDIA ® с поддержкой CUDA ® и совместимый драйвер.
Дополнительный
Для построений, отличных от MEX, таких как статические, динамические библиотеки или исполняемые файлы, этот пример имеет следующие дополнительные требования.
Инструментарий NVIDIA.
Библиотека NVIDIA cuDNN.
Переменные среды для компиляторов и библиотек. Дополнительные сведения см. в разделах Аппаратное обеспечение сторонних производителей и Настройка необходимых продуктов.
Используйте coder.checkGpuInstall для проверки правильности настройки компиляторов и библиотек, необходимых для выполнения этого примера.
envCfg = coder.gpuEnvConfig('host'); envCfg.DeepLibTarget = 'cudnn'; envCfg.DeepCodegen = 1; envCfg.Quiet = 1; coder.checkGpuInstall(envCfg);
U-Net [1] - тип сверточной нейронной сети (CNN), предназначенный для сегментации семантического изображения. В U-Net начальные серии сверточных слоев перемежаются с максимальными слоями объединения, последовательно уменьшая разрешение входного изображения. За этими слоями следует ряд сверточных слоев, перемежающихся операторами повышающей дискретизации, последовательно повышая разрешающую способность входного изображения. Объединение этих двух последовательных путей образует U-образный граф. Сеть была первоначально обучена и использовалась для прогнозирования приложений для сегментации биомедицинских изображений. Этот пример демонстрирует способность сети отслеживать изменения лесного покрова с течением времени. Природоохранные учреждения отслеживают обезлесение для оценки и оценки состояния окружающей среды и состояния окружающей среды в регионе.
Семантическая сегментация на основе глубокого обучения может обеспечить точное измерение растительного покрова с помощью аэрофотоснимков высокого разрешения. Одной из проблем является дифференциация классов, которые имеют схожие визуальные характеристики, например, попытка классифицировать зеленый пиксель как траву, кустарник или дерево. Для повышения точности классификации некоторые наборы данных содержат многоспектральные изображения, которые предоставляют дополнительную информацию о каждом пикселе. Например, набор данных парка штата Хэмлин-Бич дополняет цветные изображения каналами ближнего инфракрасного диапазона, которые обеспечивают более четкое разделение классов.
В этом примере используются данные парка штата Хэмлин-Бич [2] вместе с предварительно подготовленной сетью U-Net для правильной классификации каждого пикселя.
Используемый U-Net обучается сегментации пикселей, принадлежащих 18 классам, которые включают в себя:
0. Other Class/Image Border 7. Picnic Table 14. Grass 1. Road Markings 8. Black Wood Panel 15. Sand 2. Tree 9. White Wood Panel 16. Water (Lake) 3. Building 10. Orange Landing Pad 17. Water (Pond) 4. Vehicle (Car, Truck, or Bus) 11. Water Buoy 18. Asphalt (Parking Lot/Walkway) 5. Person 12. Rocks 6. Lifeguard Chair 13. Other Vegetation
segmentImageUnet Функция точки входа segmentImageUnet.m функция начальной точки выполняет разрозненную семантическую сегментацию на входном изображении с помощью сети multispectralUnet, найденной в multispectralUnet.mat файл. Функция загружает сетевой объект из multispectralUnet.mat в постоянный переменный mynet и повторно использует постоянную переменную при последующих вызовах прогнозирования.
type('segmentImageUnet.m')
% OUT = segmentImageUnet(IM, PATCHSIZE) returns a semantically segmented
% image, segmented using the network multispectralUnet. The segmentation
% is performed over each patch of size PATCHSIZE.
%
% Copyright 2019-2020 The MathWorks, Inc.
function out = segmentImageUnet(im, patchSize)
%#codegen
persistent mynet;
if isempty(mynet)
mynet = coder.loadDeepLearningNetwork('trainedUnet/multispectralUnet.mat');
end
[height, width, nChannel] = size(im);
patch = coder.nullcopy(zeros([patchSize, nChannel-1]));
% pad image to have dimensions as multiples of patchSize
padSize = zeros(1,2);
padSize(1) = patchSize(1) - mod(height, patchSize(1));
padSize(2) = patchSize(2) - mod(width, patchSize(2));
im_pad = padarray (im, padSize, 0, 'post');
[height_pad, width_pad, ~] = size(im_pad);
out = zeros([size(im_pad,1), size(im_pad,2)], 'uint8');
for i = 1:patchSize(1):height_pad
for j =1:patchSize(2):width_pad
for p = 1:nChannel-1
patch(:,:,p) = squeeze( im_pad( i:i+patchSize(1)-1,...
j:j+patchSize(2)-1,...
p));
end
% pass in input
segmentedLabels = activations(mynet, patch, 'Segmentation-Layer');
% Takes the max of each channel (6 total at this point)
[~,L] = max(segmentedLabels,[],3);
patch_seg = uint8(L);
% populate section of output
out(i:i+patchSize(1)-1, j:j+patchSize(2)-1) = patch_seg;
end
end
% Remove the padding
out = out(1:height, 1:width);
trainedUnet_url = 'https://www.mathworks.com/supportfiles/vision/data/multispectralUnet.mat';
downloadTrainedUnet(trainedUnet_url,pwd);
Downloading Pre-trained U-net for Hamlin Beach dataset... This will take several minutes to download... done.
ld = load("trainedUnet/multispectralUnet.mat");
net = ld.net;
Сеть DAG содержит 58 уровней, включая уровни свертки, максимального объединения, конкатенации глубины и выходные уровни классификации пикселей. Для отображения интерактивной визуализации архитектуры сети глубокого обучения используйте analyzeNetwork (Deep Learning Toolbox). analyzNetwork (сеть);
Загрузите данные парка штата Хэмлин-Бич.
if ~exist(fullfile(pwd,'data')) url = 'http://www.cis.rit.edu/~rmk6217/rit18_data.mat'; downloadHamlinBeachMSIData(url,pwd+"/data/"); end
Downloading Hamlin Beach dataset... This will take several minutes to download... done.
Загрузите и проверьте данные в MATLAB.
load(fullfile(pwd,'data','rit18_data','rit18_data.mat')); % Examine data whos test_data
Name Size Bytes Class Attributes test_data 7x12446x7654 1333663576 uint16
Изображение имеет семь каналов. Цветовые каналы RGB являются четвертым, пятым и шестым каналами изображения. Первые три канала соответствуют ближним инфракрасным полосам и выделяют различные компоненты изображения на основе их тепловых сигнатур. Канал 7 представляет собой маску, которая указывает допустимую область сегментации.
Данные многоспектрального изображения расположены в виде массивов numChannel-by-width-by-height. В MATLAB многоканальные изображения располагаются как массивы width-by-height-by-numChannel. Чтобы изменить форму данных таким образом, чтобы каналы находились в третьем измерении, используйте вспомогательную функцию, switchChannelsToThirdPlane.
test_data = switchChannelsToThirdPlane(test_data); % Confirm data has the correct structure (channels last). whos test_data
Name Size Bytes Class Attributes test_data 12446x7654x7 1333663576 uint16
Создание кода CUDA для segmentImageUnet.m , создайте объект конфигурации GPU для цели MEX, установив целевой язык на C++. Используйте coder.DeepLearningConfig для создания функции CuDNN глубокий объект конфигурации обучения и назначить его DeepLearningConfig свойства объекта конфигурации кода графического процессора. Запустить codegen команда, задающая размер ввода [12446,7654,7] и размер исправления [1024,1024]. Эти значения соответствуют всему размеру test_data. Меньшие размеры сегментов ускоряют вывод. Сведения о том, как рассчитываются исправления, см. в разделе segmentImageUnet.m функция точки входа.
cfg = coder.gpuConfig('mex'); cfg.TargetLang = 'C++'; cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn'); codegen -config cfg segmentImageUnet -args {ones(size(test_data),'uint16'),coder.Constant([1024 1024])} -report
Code generation successful: To view the report, open('codegen/mex/segmentImageUnet/html/report.mldatx').
Это segmentImageUnet функция принимает данные для проверки (test_data) и вектор, содержащий размеры используемого размера фрагмента. Возьмите фрагменты изображения, спрогнозируйте пикселы в определенном фрагменте, а затем объедините все фрагменты вместе. Из-за размера test_data (12446х7654х7) обрабатывать такое большое изображение в патчах проще.
segmentedImage = segmentImageUnet_mex(test_data,[1024 1024]);
Чтобы извлечь только допустимую часть сегментации, умножьте сегментированное изображение на канал маски тестовых данных.
segmentedImage = uint8(test_data(:,:,7)~=0) .* segmentedImage;
Поскольку вывод семантической сегментации является шумным, удалите шум и паразитные пикселы, используя medfilt2 функция.
segmentedImage = medfilt2(segmentedImage,[5,5]);
Следующая строка кода создает вектор имен классов.
classNames = [ "RoadMarkings","Tree","Building","Vehicle","Person", ... "LifeguardChair","PicnicTable","BlackWoodPanel",... "WhiteWoodPanel","OrangeLandingPad","Buoy","Rocks",... "LowLevelVegetation","Grass_Lawn","Sand_Beach",... "Water_Lake","Water_Pond","Asphalt"];
Наложите метки на сегментированное тестовое изображение RGB и добавьте цветовую полосу к изображению сегментации.
cmap = jet(numel(classNames)); B = labeloverlay(imadjust(test_data(:,:,4:6),[0 0.6],[0.1 0.9],0.55),segmentedImage,'Transparency',0.8,'Colormap',cmap); figure imshow(B) N = numel(classNames); ticks = 1/(N*2):1/N:1; colorbar('TickLabels',cellstr(classNames),'Ticks',ticks,'TickLength',0,'TickLabelInterpreter','none'); colormap(cmap) title('Segmented Image');

[1] Роннебергер, Олаф, Филипп Фишер и Томас Брокс. «U-Net: сверточные сети для сегментации биомедицинских изображений». arXiv препринт arXiv:1505.04597, 2015.
[2] Кемкер, Р., С. Сальваджо и К. Канан. «Многоспектральный набор данных высокого разрешения для семантической сегментации». CoRR, abs/1703.01918, 2017.