基于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®执行,直到处理完成。
使用helperCalculateClassWeights
Helper函数,作为支持文件附加到此示例,用于计算训练数据集中所有类的点分布。金宝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
(计算机视觉工具箱)函数从测试集结果计算语义分割度量。目标标签和预测标签是预先计算的,并存储在labelsDensePred
和labelsDenseTarget
变量分别。
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.