主要内容

基于pointnet++深度学习的航空激光雷达语义分割

这个例子展示了如何训练pointnet++深度学习网络对航空激光雷达数据进行语义分割。

从机载激光扫描系统获得的激光雷达数据用于地形测绘、城市建模、生物量测量和灾害管理等应用。从这些数据中提取有意义的信息需要语义分割,在这个过程中,点云中的每个点都被分配一个唯一的类标签。

在这个例子中,您使用代顿注释激光雷达地球扫描(DALES)数据集训练pointnet++网络来执行语义分割[1].该数据集包含来自城市、郊区、农村和商业环境的密集、标记的航空激光雷达数据场景。数据集为建筑、汽车、卡车、电线杆、电线、栅栏、地面和植被等8类提供语义分割标签。

加载DALES数据

DALES数据集包含40个空中激光雷达数据场景。在40个场景中,29个场景用于训练,其余11个场景用于测试。数据中的每个像素都有一个类标签。按照说明书上的说明操作山谷网站将数据集下载到指定的文件夹dataFolder变量。创建文件夹来存储训练和测试数据。

dataFolder = fullfile(tempdir,“山谷”);trainDataFolder = fullfile(数据文件夹,“dales_las”“火车”);testDataFolder = fullfile(数据文件夹,“dales_las”“测试”);

从训练数据中预览点云。

lasReader = lasFileReader(fullfile(trainDataFolder,5080 _54435.las));[pc,attr] = readPointCloud(lasReader,“属性”“分类”);标签= atr .分类;只选择有标签的数据。PC = select(PC,labels~=0);标签=标签(标签~=0);classNames = [“地面”“植物”“汽车”“卡车”“电线”“篱笆”“两极”“建筑”];图;ax = pcshow(pc.Location,labels);helperLabelColorbar (ax,类名);标题(语义标签叠加的点云);

数据进行预处理

DALES数据集中的每个点云覆盖面积为500 × 500米,这比地面激光雷达点云覆盖的典型区域要大得多。为了有效地处理内存,可以使用函数将点云划分为小的、不重叠的块blockedPointCloud(激光雷达工具箱)对象。

属性定义块尺寸blockSize参数。由于数据集中每个点云的大小不同,将块的z维设置为避免沿z轴创建块。

blocksize = [51 51 Inf];

创建一个matlab.io.datastore.FileSet对象来收集训练数据中的所有点云文件。

fs = matlab.io.datastore.FileSet(trainDataFolder);

创建一个blockedPointCloud(激光雷达工具箱)对象使用文件集对象。

bpc = blockedPointCloud(fs,blocksize);

注意:处理过程可能需要一些时间。该代码暂停MATLAB®执行,直到处理完成。

使用helperCalculateClassWeightsHelper函数,作为支持文件附加到此示例,用于计算训练数据集中所有类的点分布。金宝app

numClasses = numel(classNames);[weights,maxLabel,maxWeight] = helperCalculateClassWeights(fs,numClasses);

创建培训数据存储对象

创建一个blockedPointCloudDatastore(激光雷达工具箱)对象使用阻塞的点云,bpc训练网络。

ldsTrain = blockedPointCloudDatastore(bpc);

指定标签id,从1到类的个数。

labelIDs = 1: numClasses;

预览和显示点云。

ptcld =预览(ldsTrain);图;pcshow (ptcld.Location);标题(“裁剪点云”);

为了更快的训练,为每个单元设置固定的点数。

numPoints = 8192;

控件转换数据,使其与网络的输入层兼容helperTransformToTrainData函数,在本例的末尾定义。遵循以下步骤来应用转换。

  • 提取点云和各自的标签。

  • 下采样点云,标签到指定的数字,numPoints

  • 将点云归一化到范围[0 1]。

  • 转换点云和相应的标签,使其与网络的输入层兼容。

ldsTransformed = transform(ldsTrain,@(x,info)) helperTransformToTrainData(x,...信息,numPoints labelIDs,类名),“IncludeInfo”,真正的);阅读(ldsTransformed)
ans =1×2单元格数组{8192×1×3 double} {8192×1 categorical}

定义pointnet++模型

pointnet++是一种流行的用于无组织激光雷达点云语义分割的神经网络。语义分割将3-D点云中的每个点与一个类别标签关联起来,例如汽车、卡车、地面或植被。有关更多信息,请参见开始使用pointnet++(激光雷达工具箱)

定义pointnet++体系结构pointnetplusLayers(激光雷达工具箱)函数。

lgraph = pointnetplusLayers(numPoints,3,numClasses);

为了处理DALES数据集上的类不平衡,加权交叉熵损失从pixelClassificationLayer(计算机视觉工具箱)函数被使用。如果属于权重较低的类的点被错误分类,这将对网络造成更大的惩罚。

将FocalLoss层替换为pixelClassificationLayer。larray = pixelClassificationLayer(“名字”“SegmentationLayer”“ClassWeights”...重量、“类”类名);lgraph =替换层(lgraph,“FocalLoss”, larray);

指定培训项目

使用A大坝训练网络的优化算法。使用trainingOptions函数指定超形参。

learningRate = 0.0005;l2Regularization = 0.01;numEpochs = 20;miniBatchSize = 16;learnratdropfactor = 0.1;learnratdropperiod = 10;gradientDecayFactor = 0.9;squaredGradientDecayFactor = 0.999;选项= trainingOptions(“亚当”...“InitialLearnRate”learningRate,...“L2Regularization”l2Regularization,...“MaxEpochs”numEpochs,...“MiniBatchSize”miniBatchSize,...“LearnRateSchedule”“分段”...“LearnRateDropFactor”learnRateDropFactor,...“LearnRateDropPeriod”learnRateDropPeriod,...“GradientDecayFactor”gradientDecayFactor,...“SquaredGradientDecayFactor”squaredGradientDecayFactor,...“阴谋”“训练进步”...“ExecutionEnvironment”“图形”);

注:减少miniBatchSize值来控制训练时的内存使用。

火车模型

为了训练网络,设置doTraining参数真正的.否则,加载一个预先训练好的网络。要训练网络,可以使用CPU或GPU。使用GPU需要并行计算工具箱™和支持CUDA®的NVIDIA®GPU。有关更多信息,请参见GPU支金宝app持版本(并行计算工具箱)

doTraining = false;如果doTraining使用在ldsTransformed数据存储上训练网络trainNetwork函数。[net,info] = trainNetwork(ldsTransformed,lgraph,options);其他的加载预训练的网络。负载(“pointnetplusTrained”“净”);结束

航拍点云

要在测试点云上执行分割,首先创建一个blockedPointCloud(激光雷达工具箱)对象,然后创建一个blockedPointCloudDatastore(激光雷达工具箱)对象。

将训练数据上使用的类似转换应用于测试数据:

  • 提取点云和各自的标签。

  • 对点云进行下采样,并将标签设置为指定的数字,numPoints

  • 将点云归一化到范围[0 1]。

  • 转换点云,使其与网络的输入层兼容。

tbpc = blockedPointCloud(fullfile(testDataFolder,5080 _54470.las), blocksize);tbpcds = blockedPointCloudDatastore(tbpc);

定义numNearestNeighbors而且半径为密集点云中的每个点找到下采样点云中最近的点,并有效地进行插值。

numNearestNeighbors = 20;半径= 0.05;

初始化预测标签和目标标签的占位符。

labelsDensePred = [];labelsDenseTarget = [];

在此测试点云上执行推断以计算预测标签。插值预测标签,得到稠密点云上的预测标签。在所有不重叠的块上迭代该过程,并使用semanticseg(计算机视觉工具箱)f津津有味。

hasdata (tbpcds)读取块和块信息。[ptCloudDense,infoDense] = read(tbpcds);从块信息中提取标签。labelsDense = infoDense.PointAttributes.Classification;只选择有标签的数据。ptCloudDense = select(ptCloudDense{1},labelsDense~=0);labelsDense = labelsDense(labelsDense~=0);使用helperDownsamplePoints函数,该函数作为的支金宝app持文件,以提取下采样点云%密度点云。ptCloudSparse = helpdownsamplepoints (ptCloudDense,...labelsDense numPoints);%使密集点云和稀疏点的空间范围%云一样。限值= [ptCloudDense.XLimits;ptCloudDense.YLimits;ptCloudDense.ZLimits];ptCloudSparseLocation = ptCloudSparse.Location;ptCloudSparseLocation(1:2,:) = limits(:,1:2)';ptCloudSparse = pointCloud(ptCloudSparseLocation,“颜色”, ptCloudSparse。的颜色,...“强度”, ptCloudSparse。强度,...“正常”, ptCloudSparse.Normal);使用附加到本示例中的helperNormalizePointCloud函数% a支金宝app持文件,将点云归一化到0到1之间。ptCloudSparseNormalized = helperNormalizePointCloud(ptCloudSparse);ptCloudDenseNormalized = helperNormalizePointCloud(ptCloudDense);使用在后面定义的helperTransformToTestData函数%示例,将点云转换为单元格数组,并将%的维度,使其与输入层兼容网络的%。ptCloudSparseForPrediction = helptransformtotestdata (ptCloudSparseNormalized);获取输出预测。labelsSparsePred = semanticseg(ptCloudSparseForPrediction{1,1},...“OutputType”“uint8”);使用helperInterpolate函数,该函数作为%支金宝app持文件,为密集点云计算标签,%,利用稀疏点云和稀疏点云上预测的标签。interpolatedLabels = helpinterpolate (ptCloudDenseNormalized,...ptCloudSparseNormalized、labelsSparsePred numNearestNeighbors,...半径,maxLabel numClasses);连接块中的预测标签和目标标签。labelsDensePred = vertcat(labelsDensePred,interpolatedLabels);labelsDenseTarget = vertcat(labelsDenseTarget,labelsDense);结束
使用“本地”配置文件启动并行池(parpool)…连接到并行池(工人数:6)。

为了更好的可视化,只显示从点云数据推断出来的块。

图;ax = pcshow(ptCloudDense.Location,interpolatedLabels);轴;helperLabelColorbar (ax,类名);标题(“用检测到的语义标签覆盖的点云”);

评估网络

根据测试数据评估网络性能。使用evaluateSemanticSegmentation(计算机视觉工具箱)函数从测试集结果计算语义分割度量。目标标签和预测标签是预先计算的,并存储在labelsDensePredlabelsDenseTarget变量分别。

confusimatrix = segmentationconfusimatrix (double(labelsDensePred),...双(labelsDenseTarget),“类”1: numClasses);metrics = evaluateSemanticSegmentation({confusionMatrix},classNames,“详细”、假);

您可以使用交集-over-union (IoU)度量来度量每个类的重叠量。

evaluateSemanticSegmentation(计算机视觉工具箱)函数返回整个数据集、单个类和每个测试图像的指标。要查看数据集级别的指标,请使用指标。DataSetMetrics财产。

指标。DataSetMetrics
ans =1×4表GlobalAccuracy MeanAccuracy MeanIoU WeightedIoU  ______________ ____________ _______ ___________ 0.93104 0.65003 0.52971 0.87937

数据集指标提供了网络性能的高级概述。类检查每个类的度量,以查看每个类对总体性能的影响指标。ClassMetrics财产。

指标。ClassMetrics
ans =8×2表精度借条________ _________地面0.98381 0.93339植被0.86131 0.81124汽车0.67507 0.38561卡车0.012988 0.0094479电力线0.76932 0.70852围栏0.39146 0.23877杆子0.57564 0.25588建筑物0.93064 0.89481

虽然整体网络性能是好的,类指标为一些类卡车表示需要更多的训练数据才能获得更好的表现。

金宝app支持功能

helperLabelColorbar函数将颜色条添加到当前轴。颜色条被格式化以显示带有颜色的类名。

函数helperLabelColorbar (ax,类名)原始类的% Colormap。Cmap = [[0 0 255];[0 255 0];[255 192 203];[255 255 0];[255 0 255];[255 165 0];[139 0 150];[255 0 0]];Cmap = Cmap ./255;cmap = cmap(1:numel(classNames),:); colormap(ax,cmap);将色条添加到当前图形。C = colorbar(ax);c.Color =' w '居中标记,并使用类名作为标记。numClasses = size(classNames,1);c.Ticks = 1:1:numClasses;c.TickLabels = classNames;删除标记。c.TickLength = 0;结束

helperTransformToTrainData函数对输入数据执行以下转换集:

  • 提取点云和各自的标签。

  • 下采样点云,标签到指定的数字,numPoints

  • 将点云归一化到范围[0 1]。

  • 转换点云和相应的标签,使其与网络的输入层兼容。

函数[cellout,dataout] = helperTransformToTrainData(data,numPoints,info,...labelIDs一会)如果~iscell(data) data = {data};结束numObservations = size(data,1);cellout = cell(numObservations,2);dataout = cell(numObservations,2);i = 1:numObservations classification = info.PointAttributes(i).Classification;使用helperDownsamplePoints函数,该函数作为%支金宝app持文件,提取下采样点云及其标签%来自稠密点云。[ptCloudOut,labelsOut] = helperDownsamplePoints(data{i,1},...分类、numPoints);%使密集点云和稀疏点的空间范围%云一样。限值= [ptCloudOut.XLimits;ptCloudOut.YLimits;...ptCloudOut.ZLimits];ptCloudSparseLocation = ptCloudOut.Location;ptCloudSparseLocation(1:2,:) = limits(:,1:2)';ptCloudSparseUpdated = pointCloud(ptCloudSparseLocation,...“强度”, ptCloudOut。强度,...“颜色”, ptCloudOut。的颜色,...“正常”, ptCloudOut.Normal);使用附加到本示例中的helperNormalizePointCloud函数% a支金宝app持文件,将点云归一化到0到1之间。ptCloudOutSparse = helperNormalizePointCloud(...ptCloudSparseUpdated);tmp = ptCloudOutSparse.Location;%排列输出。Cellout {i,1} = permute(tmp,[1 3 2]);cellout{i,2} = permute(categorical(labelsOut,labelIDs,classNames),[1 3 2]);一般输出。dataout{i,1} = ptCloudOutSparse;dataout{i,2} = labelsOut;结束结束

helperTransformToTestData函数将点云转换为单元格数组,并排列点云的尺寸,使其与网络的输入层兼容。

函数data = helptransformtotestdata (data)如果~iscell(data) data = {data};结束numObservations = size(data,1);i = 1:numObservations tmp = data{i,1}.Location;数据{i,1} = permute(tmp,[1 3 2]);结束结束

参考文献

[1] Varney, Nina, Vijayan K. Asari和Quinn Graehling。“DALES:用于语义分割的大规模航空激光雷达数据集。”ArXiv:2004.11985 [Cs,统计]2020年4月14日。https://arxiv.org/abs/2004.11985

[2]齐,查尔斯R.,李毅,苏昊和列奥尼达J.古伯斯。“点net ++:度量空间中点集的深度层次特征学习。”ArXiv: 1706.02413 (Cs)2017年6月7日。https://arxiv.org/abs/1706.02413