В этом примере показано, как сгенерировать код CUDA ® MEX для нейронной сети для глубокого обучения для семантической сегментации лидара. Этот пример использует предварительно обученную сеть SqueezeSegV2 [1], которая может сегментировать организованные облака точек лидара, принадлежащие трем классам (фон, автомобиль и грузовик). Для получения информации о процедуре обучения для сети смотрите Lidar Point Cloud Semantic Segmentation Using SqueezeSegV2 Deep Learning Network (Lidar Toolbox). Сгенерированный код MEX принимает облако точек как вход и выполняет предсказание для облака точек при помощи DAGNetwork
объект для SqueezeSegV2 сети.
Этот пример генерирует CUDA MEX и имеет следующие требования к третьим лицам.
CUDA включает графический процессор NVIDIA ® и совместимый драйвер.
Для сборок, не являющихся MEX, таких как статические, динамические библиотеки или исполняемые файлы, этот пример имеет следующие дополнительные требования.
Набор инструментальных средств NVIDIA.
Библиотека NVIDIA cuDNN.
Библиотека NVIDIA TensorRT.
Переменные окружения для компиляторов и библиотек. Для получения дополнительной информации смотрите Оборудование сторонних производителей и Настройка предварительных Продуктов.
Чтобы убедиться, что компиляторы и библиотеки для выполнения этого примера настроены правильно, используйте coder.checkGpuInstall
функция.
envCfg = coder.gpuEnvConfig('host'); envCfg.DeepLibTarget = 'cudnn'; envCfg.DeepCodegen = 1; envCfg.Quiet = 1; coder.checkGpuInstall(envCfg);
SqueezeSegV2 - сверточная нейронная сеть (CNN), предназначенная для семантической сегментации организованных лидаров облаков точек. Это глубокая сеть сегментации энкодера-декодера, обученная на лидаре данных и импортированная в MATLAB ® для вывода. В SqueezeSegV2 подсеть энкодера состоит из слоев свертки, которые перемежаются слоями max-pooling. Эта схема последовательно уменьшает разрешение входного изображения. Подсеть декодера состоит из ряда транспонированных слоев свертки, которые последовательно увеличивают разрешение входного изображения. В сложение SqueezeSegV2 сеть снижает влияние недостающих данных, включая модули агрегирования контекста (CAM). КУЛАК - сверточная подсеть с filterSize значения [7, 7], что совокупности контекстная информация от более крупной восприимчивой области, которая улучшает робастность сети к недостающим данным. Сеть SqueezeSegV2 в этом примере обучена сегментным точкам, относящимся к трем классам (фон, автомобиль и грузовик).
Для получения дополнительной информации о обучении сети семантической сегментации в MATLAB ® с помощью набора данных Mathworks lidar, смотрите Lidar Point Cloud Semantic Segmentation Using PointSeg Deep Learning Network (Lidar Toolbox).
Загрузите предварительно обученную сеть SqueezeSegV2.
net = getSqueezeSegV2Net();
Downloading pretrained SqueezeSegV2 (2 MB)...
Сеть DAG содержит 238 слоев, включая свертки, ReLU и слои нормализации партии ., и выходной слой фокальных потерь. Чтобы отобразить интерактивную визуализацию архитектуры нейронной сети для глубокого обучения, используйте analyzeNetwork
(Deep Learning Toolbox) функция.
analyzeNetwork(net);
squeezesegv2_predict
Функция точки входаThe 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);
Чтобы сгенерировать код MEX CUDA для squeezesegv2_predict.m
функция точки входа, создайте объект строения кода GPU для цели MEX и установите целевой язык на C++. Используйте coder.DeepLearningConfig
функция для создания CuDNN
объект строения глубокого обучения и присвоение его DeepLearningConfig
свойство объекта строения кода GPU. Запуск 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 ® смотрите Code Generation for Нейронные Сети для Глубокого Обучения with MKL-DNN.
Загрузите организованное облако тестовых точек в 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) состоят из первых трех каналов. Четвертый канал содержит измерение интенсивности лидара. Пятый канал содержит информацию о области значений, которая вычисляется как.
Визуализация канала интенсивности изображения.
intensityChannel = I(:,:,4);
figure;
imshow(intensityChannel);
title('Intensity Image');
Функции squeezesegv2_predict_mex
на пятиканальном изображении.
predict_scores = squeezesegv2_predict_mex(I);
The 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, поэтому каждый объект pointCloud имеет размер 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.m
function 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.m
function 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: улучшенная структура модели и неконтролируемая адаптация области для сегментации дорог и объектов из облака точек лИДАР». Препринт, представленный 22 сентября 2018 года. http://arxiv.org/abs/1809.08495.