主要内容

激光雷达点云分割网络的代码生成

这个例子展示了如何为激光雷达语义分割的深度学习网络生成CUDA®MEX代码。本例使用预训练的SqueezeSegV2[1]网络,该网络可以将有组织的激光雷达点云分为三类(背景,卡车).有关网络训练程序的信息,请参见基于SqueezeSegV2深度学习网络的激光雷达点云语义分割.生成的MEX代码以点云作为输入,并使用DAGNetwork对象用于SqueezeSegV2网络。

第三方的先决条件

要求

本例生成CUDA MEX,第三方需求如下。

  • CUDA支持NVIDIA®GPU和兼容的驱动程序。

可选

对于非mex构建,例如静态、动态库或可执行文件,此示例具有以下附加要求。

检查GPU环境

要验证用于运行此示例的编译器和库是否正确设置,请使用coder.checkGpuInstall(GPU编码器)函数。

envCfg = code . gpuenvconfig (“主机”);envCfg。DeepLibTarget =“cudnn”;envCfg。DeepCodegen = 1;envCfg。安静= 1;coder.checkGpuInstall (envCfg);

分割网络

SqueezeSegV2是一种卷积神经网络(CNN),用于有组织的激光雷达点云的语义分割。它是在激光雷达数据集上训练的深度编码器-解码器分割网络,并导入MATLAB®进行推理。在SqueezeSegV2中,编码器子网由卷积层组成,卷积层中穿插着最大池化层。这种排列依次降低了输入图像的分辨率。解码器子网络由一系列转置卷积层组成,依次增加输入图像的分辨率。此外,SqueezeSegV2网络通过包含上下文聚合模块(CAMs)减轻了数据丢失的影响。CAM是一个具有filterSize值[7,7]的卷积子网络,它聚合来自更大接受域的上下文信息,这提高了网络对缺失数据的鲁棒性。本例中的SqueezeSegV2网络被训练为分割属于三个类别(背景、汽车和卡车)的点。

有关使用Mathworks激光雷达数据集在MATLAB®中训练语义分割网络的更多信息,请参见基于PointSeg深度学习网络的激光雷达点云语义分割

下载预训练的SqueezeSegV2网络。

net = getsqueezegv2net ();
下载预训练的SqueezeSegV2 (2 MB)…

DAG网络包含238层,包括卷积层、ReLU层和批归一化层,以及一个焦损失输出层。要显示深度学习网络体系结构的交互式可视化,请使用analyzeNetwork(深度学习工具箱)函数。

analyzeNetwork(净);

squeezesegv2_predict入口点函数

squeezesegv2_predict.m入口点函数,附在本例中,以点云为输入,并使用保存在SqueezeSegV2Net.mat文件。方法加载网络对象SqueezeSegV2Net.mat文件转换为持久变量mynet并在后续的预测调用中重用持久变量。

类型(“squeezesegv2_predict.m”);
一个持久化对象mynet用于加载DAG网络对象。在%第一次调用此函数时,将构造持久对象,并且% setup。当该函数随后被调用时,相同的对象将被%重用,以便对输入调用predict,从而避免重构和%重新加载网络对象。The MathWorks, Inc. persistent mynet;if isempty(mynet) mynet = code . loaddeeplearningnetwork ('SqueezeSegV2Net.mat');End % pass in input out = predict(mynet,in);

生成CUDA MEX代码

生成CUDA MEX代码squeezesegv2_predict.m入口点函数,为MEX目标创建GPU代码配置对象,并设置目标语言为c++。使用编码器。DeepLearningConfig(GPU编码器)函数创建CuDNN深度学习配置对象,并将其分配给DeepLearningConfigGPU代码配置对象的属性。运行codegen命令,指定输入大小为[64,1024,5]。该值对应于SqueezeSegV2网络输入层的大小。

cfg = code . gpuconfig (墨西哥人的);cfg。TargetLang =“c++”;cfg。DeepLearningConfig =编码器。DeepLearningConfig (“cudnn”);codegen配置cfgsqueezesegv2_predictarg游戏{(64、1024、5、uint8)}报告
代码生成成功:查看报告

要生成利用NVIDIA TensorRT库的CUDA c++代码,在代码中指定coder.DeepLearningConfig(“tensorrt”)而不是coder.DeepLearningConfig(“cudnn”)

有关如何在Intel®处理器上为深度学习网络生成MEX代码的信息,请参见基于mml - dnn的深度学习网络代码生成(MATLAB编码器)

准备数据

在MATLAB®中加载一个有组织的测试点云。将点云转换为五通道图像进行预测。

ptCloud = pcread(“ousterLidarDrivingData.pcd”);I = pointCloudToImage(ptCloud);检查转换后的数据
名称大小字节类型属性I 64x1024x5 327680 uint8

图像有五个通道。的(x, y, z)点坐标包括前三个通道。第四通道包含激光雷达强度测量。第五个通道包含范围信息,计算方法为 r x 2 + y 2 + z 2

可视化图像的强度通道。

intensityChannel = I(:,:,4);图;imshow (intensityChannel);标题(“强度图像”);

在数据上运行生成的MEX

调用squeezesegv2_predict_mex在五通道图像上。

predict_scores = squeezesegv2_predict_mex(I);

predict_scoresVariable是一个三维矩阵,它有三个通道,对应于每个类的像素级预测分数。通过使用最大预测分数来计算通道以获得像素级标签

[~,argmax] = max(predict_scores,[],3);

将分割的标签叠加在强度通道图像上,并显示分割的区域。调整分段输出的大小,并添加一个颜色条,以便更好地可视化。

类= [“背景”“汽车”“卡车”];cmap = lidarColorMap();SegmentedImage = labeloverlay(强度通道,argmax,“ColorMap”,提出);SegmentedImage = imresize(SegmentedImage,“规模”, [2 1],“方法”“最近的”);图;imshow (SegmentedImage);N =数目(类);ticks = 1/(N*2):1/N:1;colorbar (“TickLabels”cellstr(类),“滴答”蜱虫,“TickLength”0,“TickLabelInterpreter”“没有”);colormap城市规划机构(cmap)标题(“语义分割结果”);

在点云序列上运行生成的MEX代码

读取输入点云序列。序列包含10个有组织的pointCloud使用Ouster OS1激光雷达传感器收集的帧。输入数据的高为64,宽为1024,因此每个pointCloud对象的大小为64 × 1024。

外部=“highwaySceneData.mat”在工作区中加载数据。负载(功能);

设置不同的颜色来为感兴趣的不同类别显示逐点标签。

把红色涂在汽车上。carClassCar = 0 (64,1024,3,“uint8”);carClassCar(:,:,1) = 255*ones(64,1024,“uint8”);在卡车上涂上蓝色。truckClassColor = 0 (64,1024,3,“uint8”);truckClassColor(:,:,3) = 255*ones(64,1024,“uint8”);应用灰色的背景。backgroundClassColor = 153*ones(64, 1024,3,“uint8”);

设置pcplayer函数属性显示序列和输出预测。逐帧读取输入序列,并使用模型检测感兴趣的类。

Xlimits = [0 120.0];Ylimits = [-80.7 80.7];Zlimits = [-8.4 27];玩家= pcplayer(xlimits, ylimits, zlimits);集(get(球员。轴,“父”),“单位”“归一化”“outerposition”,[0 0 1 1]);变焦(get(球员。轴,“父”), 2);集(球员。轴,“XColor”“没有”“YColor”“没有”“ZColor”“没有”);i = 1: numel(inputData) ptCloud = inputData{i};%将点云转换为五通道图像进行预测。I = pointCloudToImage(ptCloud);在5通道映像上调用squeezesegv2_predict_mex。predict_scores = squeezesegv2_predict_mex(I);将数值输出值转换为类别标签。[~,predictedOutput] = max(predict_scores,[],3);predictedOutput = categorical(predictedOutput, 1:3, classes);从标签中提取索引。carIndices = predictedOutput ==“汽车”;truckIndices = predictedOutput ==“卡车”;backgroundIndices = predictedOutput ==“背景”为每个类提取一个点云。carPointCloud = select(ptCloud, carindexes,“OutputSize”“全部”);truckPointCloud = select(ptCloud, truckIndices,“OutputSize”“全部”);backgroundPointCloud = select(ptCloud, backgrounddindices,“OutputSize”“全部”);填充不同类别的颜色。carPointCloud。Color = carClassCar;truckPointCloud。Color = truckClassColor;backgroundPointCloud。Color = backgroundClassColor;合并并添加所有处理过的带类信息的点云。colordcloud = pcmerge(carPointCloud, truckPointCloud, 0.01);coloredCloud = pcmerge(coloredCloud, backgroundPointCloud, 0.01);%查看输出信息。视图(球员,coloredCloud);drawnow;结束

辅助函数

本例中使用的辅助函数如下。

类型pointCloudToImage.m
pointCloudToImage将组织好的3-D点云转换为5通道% 2-D图像。image = ptcloud.Location;image(:,:,4) = ptcloud.Intensity;rangeData = iComputeRangeData(图像(:,:1)、图像(:,:2),图片(:,:,3));image(:,:,5) = rangeData;%投射到uint8。Image = uint8(Image);结束  %-------------------------------------------------------------------------- 函数rangeData = iComputeRangeData xChannel, yChannel, zChannel rangeData =√(xChannel * xChannel + yChannel。* yChannel + zChannel。* zChannel);结束
类型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卡车];结束

参考文献

[1]吴碧晨周宣宇赵思成岳翔宇Kurt Keutzer“SqueezeSegV2:改进的模型结构和无监督域自适应,用于从激光雷达点云分割道路目标。”预印本,2018年9月22日提交。http://arxiv.org/abs/1809.08495。