В этом примере показано, как создать код CUDA ® MEX для сети глубокого обучения для лидарной семантической сегментации. В этом примере используется предварительно обученная сеть SqueezeSegV2 [1], которая может сегментировать организованные облака точек лидара, относящиеся к трем классам (фон, автомобиль и грузовик). Сведения о процедуре обучения для сети см. в разделе Семантическая сегментация Lidar Point Cloud Using SqueezeSegV2 Deep Learning Network (Lidar Toolbox). Сгенерированный код MEX принимает облако точек в качестве входных данных и выполняет прогнозирование облака точек с помощью DAGNetwork для SqueezeSegV2 сети.
В этом примере создается CUDA MEX со следующими требованиями сторонних производителей.
Графический процессор NVIDIA ® с поддержкой CUDA и совместимый драйвер.
Для построений, отличных от MEX, таких как статические, динамические библиотеки или исполняемые файлы, этот пример имеет следующие дополнительные требования.
Инструментарий NVIDIA.
Библиотека NVIDIA cuDNN.
Библиотека NVIDIA TensorRT.
Переменные среды для компиляторов и библиотек. Дополнительные сведения см. в разделах Аппаратное обеспечение сторонних производителей (GPU Coder) и Настройка необходимых продуктов (GPU Coder).
Чтобы убедиться, что компиляторы и библиотеки для выполнения этого примера настроены правильно, используйте coder.checkGpuInstall (Кодер графического процессора).
envCfg = coder.gpuEnvConfig('host'); envCfg.DeepLibTarget = 'cudnn'; envCfg.DeepCodegen = 1; envCfg.Quiet = 1; coder.checkGpuInstall(envCfg);
SqueezeSegV2 - сверточная нейронная сеть (CNN), предназначенная для семантической сегментации организованных лидарных точечных облаков. Это глубокая сеть сегментации кодера-декодера, обученная на лидарном наборе данных и импортированная в MATLAB ® для вывода. В SqueezeSegV2, подсеть кодера состоит из уровней свертки, которые перемежаются с уровнями максимального объединения. Эта компоновка последовательно уменьшает разрешение входного изображения. Подсеть декодера состоит из ряда транспонированных слоев свертки, которые последовательно увеличивают разрешение входного изображения. Кроме того, сеть SqueezeSegV2 уменьшает влияние отсутствующих данных путем включения модулей агрегирования контекста (CAM). КУЛАК - сверточная подсеть с filterSize стоимости [7, 7], что совокупности контекстная информация от более крупной восприимчивой области, которая улучшает надежность сети к недостающим данным. В этом примере SqueezeSegV2 сеть обучается сегментным точкам, принадлежащим к трем классам (фоновый режим, автомобиль и грузовик).
Дополнительные сведения об обучении сети семантической сегментации в MATLAB ® с помощью набора данных Mathworks lidar см. в разделе Семантическая сегментация Lidar Point Cloud с использованием сети Deep Learning Network (Lidar Toolbox).
Загрузите предварительно подготовленную сеть SqueezeSegV2.
net = getSqueezeSegV2Net();
Downloading pretrained SqueezeSegV2 (2 MB)...
Сеть DAG содержит 238 уровней, включая уровни свертки, ReLU и пакетной нормализации, а также уровень вывода фокальных потерь. Для отображения интерактивной визуализации архитектуры сети глубокого обучения используйте analyzeNetwork функция.
analyzeNetwork(net);
squeezesegv2_predict Функция точки входа squeezesegv2_predict.m входная функция, которая присоединена к этому примеру, принимает облако точек в качестве входных данных и выполняет на нем прогнозирование с использованием сети глубокого обучения, сохраненной в SqueezeSegV2Net.mat файл. Функция загружает сетевой объект из SqueezeSegV2Net.mat файл в постоянную переменную mynet и повторно использует постоянную переменную в последующих вызовах прогнозирования.
type('squeezesegv2_predict.m');function out = squeezesegv2_predict(in)
%#codegen
% A persistent object mynet is used to load the DAG network object. At
% the first call to this function, the persistent object is constructed and
% setup. When the function is called subsequent times, the same object is
% reused to call predict on inputs, thus avoiding reconstructing and
% reloading the network object.
% Copyright 2020 The MathWorks, Inc.
persistent mynet;
if isempty(mynet)
mynet = coder.loadDeepLearningNetwork('SqueezeSegV2Net.mat');
end
% pass in input
out = predict(mynet,in);
Создание кода CUDA MEX для squeezesegv2_predict.m создание объекта конфигурации кода GPU для цели MEX и установка целевого языка на C++. Используйте coder.DeepLearningConfig (Кодер графического процессора) для создания CuDNN глубокий объект конфигурации обучения и назначить его DeepLearningConfig свойства объекта конфигурации кода графического процессора. Запустить codegen , указывая размер ввода [64, 1024, 5]. Это значение соответствует размеру входного уровня сети SqueezeSegV2.
cfg = coder.gpuConfig('mex'); cfg.TargetLang = 'C++'; cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn'); codegen -config cfg squeezesegv2_predict -args {ones(64,1024,5,'uint8')} -report
Code generation successful: View report
Для создания кода CUDA C++, использующего преимущества библиотек NVIDIA TensorRT, в коде укажите coder.DeepLearningConfig('tensorrt') вместо coder.DeepLearningConfig('cudnn').
Информацию о том, как создавать MEX-код для сетей глубокого обучения на процессорах Intel ®, см. в разделе Создание кода для сетей глубокого обучения с MKL-DNN (MATLAB Coder).
Загрузите организованное облако тестовых точек в MATLAB ®. Преобразование облака точек в пятиканальное изображение для прогнозирования .
ptCloud = pcread('ousterLidarDrivingData.pcd'); I = pointCloudToImage(ptCloud); % Examine converted data whos I
Name Size Bytes Class Attributes I 64x1024x5 327680 uint8
Изображение имеет пять каналов. Координаты (x, y, z) точек содержат первые три канала. Четвертый канал содержит измерение интенсивности лидара. Пятый канал содержит информацию о диапазоне, которая вычисляется y2 + z2.
Визуализация канала интенсивности изображения.
intensityChannel = I(:,:,4);
figure;
imshow(intensityChannel);
title('Intensity Image');
Звонить squeezesegv2_predict_mex на пятиканальном изображении.
predict_scores = squeezesegv2_predict_mex(I);
predict_scores переменная является трехмерной матрицей, которая имеет три канала, соответствующие баллам пиксельного прогнозирования для каждого класса. Вычислите канал, используя максимальную оценку прогнозирования, чтобы получить пиксельные метки
[~,argmax] = max(predict_scores,[],3);
Наложение сегментированных меток на изображение канала интенсивности и отображение сегментированной области. Измените размер сегментированных выходных данных и добавьте панель цветов для лучшей визуализации.
classes = [
"background"
"car"
"truck"
];
cmap = lidarColorMap();
SegmentedImage = labeloverlay(intensityChannel,argmax,'ColorMap',cmap);
SegmentedImage = imresize(SegmentedImage, 'Scale', [2 1], 'method', 'nearest');
figure;
imshow(SegmentedImage);
N = numel(classes);
ticks = 1/(N*2):1/N:1;
colorbar('TickLabels',cellstr(classes),'Ticks',ticks,'TickLength',0,'TickLabelInterpreter','none');
colormap(cmap)
title('Semantic Segmentation Result');
Считывание последовательности облака входных точек. Последовательность содержит 10 организованных pointCloud кадры, собранные с помощью датчика Ouster OS1 lidar. Входные данные имеют высоту 64 и ширину 1024, таким образом, размер каждого объекта «» Cloud «» равен 64 на 1024.
dataFile = 'highwaySceneData.mat'; % Load data in workspace. load(dataFile);
Настройка различных цветов для визуализации точечных меток для различных классов интересов.
% Apply the color red to cars. carClassCar = zeros(64, 1024, 3, 'uint8'); carClassCar(:,:,1) = 255*ones(64, 1024, 'uint8'); % Apply the color blue to trucks. truckClassColor = zeros(64, 1024, 3, 'uint8'); truckClassColor(:,:,3) = 255*ones(64, 1024, 'uint8'); % Apply the color gray to background. backgroundClassColor = 153*ones(64, 1024, 3, 'uint8');
Установите pcplayer свойства функции для отображения последовательности и выходных прогнозов. Считывайте кадр входной последовательности по кадрам и обнаруживайте интересующие классы с помощью модели.
xlimits = [0 120.0]; ylimits = [-80.7 80.7]; zlimits = [-8.4 27]; player = pcplayer(xlimits, ylimits, zlimits); set(get(player.Axes,'parent'), 'units','normalized','outerposition',[0 0 1 1]); zoom(get(player.Axes,'parent'),2); set(player.Axes,'XColor','none','YColor','none','ZColor','none'); for i = 1 : numel(inputData) ptCloud = inputData{i}; % Convert point cloud to five-channel image for prediction. I = pointCloudToImage(ptCloud); % Call squeezesegv2_predict_mex on the 5-channel image. predict_scores = squeezesegv2_predict_mex(I); % Convert the numeric output values to categorical labels. [~,predictedOutput] = max(predict_scores,[],3); predictedOutput = categorical(predictedOutput, 1:3, classes); % Extract the indices from labels. carIndices = predictedOutput == 'car'; truckIndices = predictedOutput == 'truck'; backgroundIndices = predictedOutput == 'background'; % Extract a point cloud for each class. carPointCloud = select(ptCloud, carIndices, 'OutputSize','full'); truckPointCloud = select(ptCloud, truckIndices, 'OutputSize','full'); backgroundPointCloud = select(ptCloud, backgroundIndices, 'OutputSize','full'); % Fill the colors to different classes. carPointCloud.Color = carClassCar; truckPointCloud.Color = truckClassColor; backgroundPointCloud.Color = backgroundClassColor; % Merge and add all the processed point clouds with class information. coloredCloud = pcmerge(carPointCloud, truckPointCloud, 0.01); coloredCloud = pcmerge(coloredCloud, backgroundPointCloud, 0.01); % View the output. view(player, coloredCloud); drawnow; end

Ниже приведены вспомогательные функции, используемые в этом примере.
type pointCloudToImage.mfunction image = pointCloudToImage(ptcloud) %pointCloudToImage Converts organized 3-D point cloud to 5-channel % 2-D image. image = ptcloud.Location; image(:,:,4) = ptcloud.Intensity; rangeData = iComputeRangeData(image(:,:,1),image(:,:,2),image(:,:,3)); image(:,:,5) = rangeData; % Cast to uint8. image = uint8(image); end %-------------------------------------------------------------------------- function rangeData = iComputeRangeData(xChannel,yChannel,zChannel) rangeData = sqrt(xChannel.*xChannel+yChannel.*yChannel+zChannel.*zChannel); end
type lidarColorMap.mfunction cmap = lidarColorMap() cmap = [ 0.00 0.00 0.00 % background 0.98 0.00 0.00 % car 0.00 0.00 0.98 % truck ]; end
[1] У, Бичэнь, Сюанью Чжоу, Сичэн Чжао, Сянъу Юэ и Курт Кэйцзер. «SqueezeSegV2: Улучшенная структура модели и незарегистрированная адаптация домена для сегментации дорожных объектов из облака точек LiDAR». Препринт, представлен 22 сентября 2018 года. http://arxiv.org/abs/1809.08495.