exponenta event banner

Создание кода для сети сегментации облака точек Lidar

В этом примере показано, как создать код CUDA ® MEX для сети глубокого обучения для лидарной семантической сегментации. В этом примере используется предварительно обученная сеть SqueezeSegV2 [1], которая может сегментировать организованные облака точек лидара, относящиеся к трем классам (фон, автомобиль и грузовик). Сведения о процедуре обучения для сети см. в разделе Семантическая сегментация Lidar Point Cloud Using SqueezeSegV2 Deep Learning Network (Lidar Toolbox). Сгенерированный код MEX принимает облако точек в качестве входных данных и выполняет прогнозирование облака точек с помощью DAGNetwork для SqueezeSegV2 сети.

Предварительные условия для сторонних производителей

Необходимый

В этом примере создается CUDA MEX со следующими требованиями сторонних производителей.

  • Графический процессор NVIDIA ® с поддержкой CUDA и совместимый драйвер.

Дополнительный

Для построений, отличных от MEX, таких как статические, динамические библиотеки или исполняемые файлы, этот пример имеет следующие дополнительные требования.

Проверка среды графического процессора

Чтобы убедиться, что компиляторы и библиотеки для выполнения этого примера настроены правильно, используйте 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 (Deep Learning Toolbox).

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

Создание кода 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 ®. Преобразование облака точек в пятиканальное изображение для прогнозирования .

ptCloud = pcread('ousterLidarDrivingData.pcd');
I = pointCloudToImage(ptCloud);

% Examine converted data
whos I
  Name       Size                 Bytes  Class    Attributes

  I         64x1024x5            327680  uint8              

Изображение имеет пять каналов. Координаты (x, y, z) точек содержат первые три канала. Четвертый канал содержит измерение интенсивности лидара. Пятый канал содержит информацию о диапазоне, которая вычисляется как r = x2 + y2 + z2.

Визуализация канала интенсивности изображения.

intensityChannel = I(:,:,4);    

figure;
imshow(intensityChannel);
title('Intensity Image');

Выполнить сгенерированный MEX для данных

Звонить 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');

Выполнение сгенерированного кода MEX в последовательности облаков точек

Считывание последовательности облака входных точек. Последовательность содержит 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.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: Улучшенная структура модели и незарегистрированная адаптация домена для сегментации дорожных объектов из облака точек LiDAR». Препринт, представлен 22 сентября 2018 года. http://arxiv.org/abs/1809.08495.

См. также

Функции

Объекты

Связанные темы