主要内容

使用PointPillars深度学习的激光雷达三维目标检测

此示例显示如何在点云中培训用于对象检测的尖峰网络。

激光雷达点云数据可以通过多种激光雷达传感器获取,包括Velodyne®、Pandar和Ouster传感器。这些传感器可以捕捉场景中物体的三维位置信息,这对自动驾驶和增强现实的许多应用都很有用。然而,由于每个目标数据的稀疏性、目标遮挡和传感器噪声,用点云数据训练鲁棒检测器是具有挑战性的。深度学习技术已经被证明可以通过直接从点云数据中学习稳健的特征表示来解决许多这些挑战。PointPillars是一种用于三维物体检测的深度学习技术[1].PointPillars网络使用与PointNet类似的架构,从称为柱子的稀疏点云中提取密集、健壮的特征,然后使用一个带有改进的SSD对象检测网络的2d深度学习网络来估计联合3d包围盒、方向和类预测。

这个示例使用PandaSet [2]来自Hesai和Scale的数据集。PANDASET包含使用PANDAR64传感器捕获的各种城市场景的8240个未组织的LIDAR点云扫描。数据集提供了3-D边界框标签,可为18个不同的对象类,包括汽车,卡车和行人。

下载激光雷达数据集

此示例使用包含2560个预处理有组织点云的PANDASET子集。每个点云覆盖 360. O. ,并指定为64 × 1856矩阵。点云以PCD格式存储,其对应的地面真值数据存储在PandasetLidargroundTruth.Mat文件。该文件包含三个类的3-D边界框信息,即汽车,卡车和行人。数据集的大小为5.2 GB。

属性从给定的URL下载Pandaset数据集HelperdownloadPandasetData.辅助函数,在本例的最后定义。

outputfolder = fullfile(tempdir,'pandaset');lidarURL = ['https://ssd.mathwands.com/万博1manbetxsupportfiles/lidar/data/'......'pandaset_lidardata.tar.gz'];HelperdownloadPandasetData(outputFolder,Lidarurl);

根据您的Internet连接,下载过程可能需要一些时间。代码暂停MATLAB®执行,直到下载过程完成。或者,您可以使用Web浏览器将数据设置为本地磁盘并提取文件。如果你这样做,改变outputFolder代码中的变量到下载的文件的位置。

下载掠夺网络

使用给定的URL从给定的URL下载预磨削的网络帮手D.AmeryLoadProTratePointPillarsnet.辅助函数,在本例的最后定义。预先训练的模型允许您运行整个示例,而不必等待训练完成。如果你想训练网络,设置用圆形变量来真的

pretrainedNetURL = ['https://ssd.mathwands.com/万博1manbetxsupportfiles/lidar/data/'......'trouthpointpillarspandasetnet.zip'];dotraining = false;如果〜Dotraining HelperDownloadPropretedPoptPillarsnet(outputfolder,pretrowneturl);结束

加载数据

使用。创建文件数据存储来从指定的路径加载PCD文件p功能。

路径= fullfile (outputFolder,激光雷达的);lidardata = filedatastore(路径,'readfcn',@(x)pcread(x));

装载汽车和卡车物体的3-D边界盒标签。

gtPath = fullfile (outputFolder,“长方体”'pandasetlidargroundtruthmat');data =负载(gtPath'lidargtlabels');标签=时间表2Table(data.lidargtlabels);boxlabels =标签(:,2:3);

显示全视线云。

图ptld = read(lidarData);ax = pcshow (ptCld.Location);集(ax,“XLim”50 [-50],'ylim',[ -  40 40]);变焦(斧头,2.5);轴

重置(Lidardata);

预处理数据

PandaSet数据由全视图点云组成。对于本例,使用标准参数将全视图点云裁剪为前视图点云[1].这些参数确定传递给网络的输入的大小。沿X,Y和Z轴选择较小的点云,有助于检测更靠近原点的对象,并且还降低了网络的整体培训时间。

Xmin = 0.0;沿x轴的%最小值。ymin = -39.68;沿y轴的%最小值。zmin = -5.0;沿z轴的%最小值。Xmax = 69.12;% x轴上的最大值。YMAX = 39.68;% y轴上的最大值。zMax = 5.0;沿z轴的%最大值。xStep = 0.16;沿x轴的分辨率。yStep = 0.16;沿y轴的分辨率。dsfactor = 2.0;百分比下采样因子。%计算伪图像的尺寸。xn = round(((xmax  -  xmin)/ xstep));yn = round(((ymax  -  ymin)/ ystep));%定义柱提取参数。gridparams = {{xmin,ymin,zmin},{xmax,ymax,zmax},{xstep,ystep,dsfactor},{xn,yn}};

使用C.ropfrontviewfromlidardata.Helper函数,作为支持文件附加到本例中:万博1manbetx

  • 从输入的全视图点云裁剪前视图。

  • 选择ROI中指定的框标签格里克朗

[CROMPEDPOINTCLOUDOBJ,PROCESSEDLABELS] = CROMFRONTVIEWFROMLIDADDATA(......lidarData、boxLabels gridParams);
处理数据100%完成

使用使用的裁剪点云和地面真相标签helperDisplay3DBoxesOverlaidPointCloud在示例的最后定义的辅助函数。

PC = CROMPEDPOINTPOINTCLOUDOBJ {1,1};gtlabelscar = processedlabels.car {1};gtlabelstruct = processedlabels.truck {1};Helperdisplay3dboxesoverlaidPointPlod(PC.Location,GTLabelsCar,......“绿色”gtLabelsTruck,“红色”“裁剪点云”);

重置(Lidardata);

创建数据存储区对象以进行培训

将数据集分为培训和测试集。选择70%的数据以培训网络以及其余的评估。

rng (1);shuffledIndices = randperm(大小(processedLabels, 1));idx = floor(0.7 * length(shuffledIndices));trainData = croppedPointCloudObj (shuffledIndices (1: idx):);testData = croppedPointCloudObj (shuffledIndices (idx + 1:结束):);trainLabels = processedLabels (shuffledIndices (1: idx):);testLabels = processedLabels (shuffledIndices (idx + 1:结束):);

这样您就可以轻松访问数据存储,通过使用使用的PCD文件将培训数据保存为PCD文件saveptCldToPCD辅助函数,附加到此示例作为支持文件。万博1manbetx你可以设置writefile错误的”如果您的培训数据保存在文件夹中并得到支持万博1manbetxp功能。

writefiles = true;datalocation = fullfile(outputfolder,“InputData”);[trainData, trainLabels] = saveptCldToPCD (trainData trainLabels,......Datalocation,Writefiles);
处理数据100%完成

使用。创建文件数据存储fileDatastore使用使用的PCD文件p功能。

lds = filedataStore(Datalocation,'readfcn',@(x)pcread(x));

Createa Box标签数据存储使用boxlabeldatastore.用于加载3-D边界框标签。

bds = boxLabelDatastore (trainLabels);

使用结合函数将点云和3-D包围盒标签合并到一个用于训练的数据存储中。

cd =结合(摩门教,bds);

数据增强

本例使用了地面真值数据增强和其他一些全局数据增强技术,为训练数据和相应的框添加更多的多样性。有关在使用激光雷达数据的三维物体检测工作流程中使用的典型数据增强技术的更多信息,请参见利用深度学习的LIDAR对象检测的数据增强

在使用增强之前读取并显示点云helperDisplay3DBoxesOverlaidPointCloud辅助函数,在示例的最后定义。

augData =阅读(cds);augptCld = augData {1};augLabels = augData {1,2};augClass = augData {1,3};labelsCar = augLabels (augClass = ='车':);labelsTruck = augLabels (augClass = ='卡车':);Helperdisplay3dboxesoverlaidPointCloud(奥古斯特·普利.Location,Labelscar,“绿色”......Labelstruck,“红色”'在数据增强之前');

重置(CD);

使用世代特拉多法悬念辅助函数,作为支持文件附加到本示例中,用于从训练数据中提取所有地面真值边界框。万博1manbetx

gtData = generateGTDataForAugmentation (trainData trainLabels);

使用groundTruthDataAugmentation帮助函数,附加到这个例子作为支持文件,随机添加一个固定数量的汽车和卡车类对象到每个点云。万博1manbetx使用转变函数将地面真实值和自定义数据增强应用到训练数据。

samplesToAdd =结构('车'10,'卡车'10);cdsAugmented = transform(cds,@(x) groundTruthDataAugmenation(x,gtData,samplesToAdd));

此外,对每个点云应用以下数据增强。

  • 随机翻转沿x轴

  • 随机缩放5%

  • 从[-pi/4, pi/4]沿z轴随机旋转

  • 随机平移分别沿X-,Y和Z轴[0.2,0.2,0.1]米[0.2,0.2,0.1]米

cdsAugmented = transform(cdsAugmented,@(x) augmentData(x));

使用该增强点云显示一个增强点云使用地面真理增强框helperDisplay3DBoxesOverlaidPointCloud辅助函数,在示例的最后定义。

奥杜塔=读(Cdsaugmented);augptCld = augData {1};augLabels = augData {1,2};augClass = augData {1,3};labelsCar = augLabels (augClass = ='车':);labelsTruck = augLabels (augClass = ='卡车':);Helperdisplay3dboxesoverlaidPointPlod(AugptCld(:,1:3),Labelscar,“绿色”......Labelstruck,“红色”'数据增强后');

重置(CDS-ummented);

提取支柱信息

您可以将2-D卷积架构应用于点云以进行更快的处理。为此,请先将3-D点云转换为2-D表示。使用转变函数与createpillars.辅助功能,附加到此示例作为支持文件,从点云中创建支柱功能和支柱指数。万博1manbetx辅助功能执行以下操作:

  • 将三维点云离散成x-y平面上均匀间隔的网格,创建一组称为柱子的垂直柱子。

  • 根据每个支柱的点数(n)选择突出的支柱(p)。

  • 计算柱子中所有点的算术平均值的距离。

  • 计算柱中心的偏移量。

  • 使用x、y、z位置、强度、距离和偏移值为柱子中的每个点创建一个9维(9-D)向量。

%定义突出的支柱数量。P = 12000;%定义每支柱的点数。n = 100;cdstransformed = transform(cdsaummented,@(x)createpillars(x,gridparams,p,n));

定义网络

PointPillars网络使用PointNet网络的简化版本,它将支柱特性作为输入。对于每个支柱特征,网络应用线性层,然后是批处理归一化和ReLU层。最后,网络在通道上应用最大池操作来获得高级编码特征。这些编码的特征被分散到原来的柱子位置,使用自定义层创建一个伪图像helperscatterLayer,附加到该示例作为支持文件。万博1manbetx然后,网络将伪图像处理有2-D卷积骨干,然后进行各种SSD检测磁头以预测三维边界盒以及其类。

基于要检测的类定义锚框维度。通常,这些维度是训练集中所有边界框值的均值[1].或者,您也可以使用calculateAnchorBoxes辅助函数,附加到示例中,用于从任何训练集获取适当的锚盒。锚框在格式中定义{长度,宽度,高度,Z中心,偏航角}。

anchorboxes = CalculateanchorspointPillars(Trainlabels);numanchors =尺寸(锚箱,2);ClassNames = trainlabels.properties.variablenames;numclasses = numel(classnames);

接下来,使用介绍PointPillars网络pointpillarNetwork辅助函数,附加到此示例作为支持文件。万博1manbetx

Lgraph = Pointpillarnetwork(Numanchors,Gridparams,P,N,Numcrasses);

指定培训选项

指定以下培训选项。

  • 将时代数量设置为60。

  • 将迷你批量大小设置为2.如果您有更多可用内存,可以将迷你批次大小设置为更高的值。

  • 将学习率设置为0.0002。

  • 学习ropperiod.此参数表示基于公式的学习率的时代的数量表示 learningRate × 迭代 学习ropperiod. × learnRateDropFactor

  • learnRateDropFactor0.8。此参数表示按照每个参数降低学习率的速率学习ropperiod.

  • 将渐变衰减因子设置为0.9。

  • 将平方梯度衰减因子设置为0.999。

  • 初始化渐变的平均值到[]。这是由ADAM优化器使用的。

  • 初始化梯度的平方平均值为[]。这是由ADAM优化器使用的。

numEpochs = 60;miniBatchSize = 2;learningRate = 0.0002;learnRateDropPeriod = 15;learnRateDropFactor = 0.8;gradientDecayFactor = 0.9;squaredGradientDecayFactor = 0.999;trailingAvg = [];trailingAvgSq = [];

火车模型

使用CPU或GPU列车网络。使用GPU需要并行计算工具箱™和CUDA®的NVIDIA®GPU。有关更多信息,请参阅GPU支万博1manbetx持情况(并行计算工具箱).若要自动检测您是否有可用的GPU,请设置executionEnvironment“汽车”.如果您没有GPU,或者不想使用一个用于培训,请设置executionEnvironment“中央处理器”.确保使用GPU进行培训,设置executionEnvironment“GPU”

接下来,创建一个小公子(深度学习工具箱)以批量加载数据miniBatchSize在培训。

executionenvironment =“汽车”如果CanUseCallallPool DispartinBackground = True;其他的Disparctinbackground = false;结束mbq = minibatchqueue(......CDStransformed,3,......“MiniBatchSize”miniBatchSize,......“ouppantenvironment”,execultionenvironment,......“MiniBatchFcn”,@(功能,指数,框,标签)......HelpercreatebatchData(功能,指数,盒子,标签,ClassNames),......“MiniBatchFormat”,[“SSCB”“SSCB”],......“DispatchInBackground”,真的);

要使用自定义训练循环训练网络并启用自动分化,将图层图转换为adlnetwork(深度学习工具箱)对象。创建训练进度绘图器helperConfigureTrainingProgressPlotter辅助函数,在本例的最后定义。

最后,指定自定义训练循环。每一次迭代:

  • 阅读点云和地面真相盒小公子(深度学习工具箱)对象使用下一个(深度学习工具箱)功能。

  • 使用dlfeval.(深度学习工具箱)modelGradients功能。这modelGradients在示例的最后定义的Helper函数,返回相对于中可学习参数的损失梯度,相应的迷你批量丢失和当前批次的状态。

  • 使用adamupdate(深度学习工具箱)功能。

  • 更新的状态参数

  • 更新培训进度情节。

如果用圆形将层图转换为dlnetwork。net = dlnetwork(3);%初始化图。无花果=图;lossPlotter = helperConfigureTrainingProgressPlotter(图);迭代= 0;%自定义训练循环。为了epoch = 1:numepochs%重置数据存储。重置(MBQ);(hasdata(mbq)) iteration = iteration + 1;%读取数据批次。[Pillarfeatures,Pillarindices,Boxlabels] =下一个(MBQ);%使用dlfeval评估模型梯度和损耗%和MapeStradients函数。[渐变,损失,状态] = DLFeval(@ MapeStradients,Net,......Pillarfeatures,Pillarindices,Booklabels,Gridparams,......anchorBoxes、numClasses executionEnvironment);%如果是NaN值,则不更新网络可学习参数%以梯度或损失值表示。如果helperCheckForNaN(梯度、损失)继续结束%更新DLNetwork的状态参数。网。=状态;%使用adam更新网络学习参数%的优化器。[net.learnables,trailingavg,trailingavgsq] =......adamupdate(净。可学的、渐变trailingAvg,......TrailIghaVGSQ,迭代,学会,......梯度Dayfactor,SquaredgradientDecayfactor);%更新培训情节与新点。addpoints (lossPlotter、迭代、双(收集(extractdata(损失))));标题(“培训时代”+ epoch +“ 的 ”+ numepochs);粗暴;结束%更新每个学习后的学习率。如果mod(epoch,learnRateDropPeriod) == 0 learningRate = learningRate * learnRateDropFactor;结束结束其他的pretratematfile = fullfile(outputfolder,'trouthpointpillarspandasetnet.mat');pretrainedNetwork =负载(preTrainedMATFile,'网');net = pretratenetwork.net;结束

生成检测

使用经过训练的网络检测测试数据中的对象:

  • 从测试数据中读取点云。

  • 使用生成pilphillardetects.辅助函数,作为支持文件附加到本示例中,以获得预测的边界框和置信度得分。万博1manbetx

  • 用边框显示点云helperDisplay3DBoxesOverlaidPointCloud辅助函数,在示例的最后定义。

45 ptCloud = testData {1};gtLabels = testLabels(45岁);%GeneratePointPillardetections函数检测%边界框,以及给定点云的分数。confidenceThreshold = 0.5;overlapThreshold = 0.1;[框,分数,标签] =生成pointpillardtections(net,ptcloud,锚箱,......Gridparams,ClassNames,ConcidenceThreshold,Overlapthreshold,P,N,......刽子毒环境;boxlabelscar = box(标签'=='车':);boxlabelsTruck(标签' = = =框'卡车':);%在点云上显示预测。Helperdisplay3dboxesoverlaidPointCloud(PTCloud.Location,Boxlabelscar,“绿色”......Boxlabelstruck,“红色”“预测边界框”);

评估模型

计算机Vision Toolbox™提供对象检测器评估功能,以测量平均精度等常用度量evaluateDetectionAOS.对于本例,使用平均精度度量。平均精度提供了一个单一的数字,该数字包括探测器进行正确分类的能力(精度)和探测器找到所有相关对象的能力(回忆)。

评估培训dlnetwork(深度学习工具箱)目的按照以下步骤测试数据。

  • 指定仅使用置信度分数的置信阈值以上该值。

  • 指定重叠阈值以消除重叠检测。

  • 使用生成pilphillardetects.辅助函数,作为支持文件附加到本示例中,以获取边界框、对象置信度得分和类标签。万博1manbetx

  • 称呼evaluateDetectionAOS检测结果groundTruthData作为论点。

numinputs = numel(testdata);%从长方体标签生成旋转的矩形。bds = boxLabelDatastore (testLabels);groundTruthData = transform(bds,@(x) createRotRect(x));%设置阈值。nmsPositiveIoUThreshold = 0.5;confidenceThreshold = 0.25;overlapThreshold = 0.1;%SET NUMSAMPLESTOTEST到NUMInputs以评估整个模型%测试数据集。numSamplesToTest = 50;detectionResults =表(“大小”numSamplesToTest [3],......'variabletypes',{“细胞”“细胞”“细胞”},......'variablenames',{'盒子''分数'“标签”});为了num = 1:numsamplestotest ptcloud = testdata {num,1};[框,分数,标签] =生成pointpillardtections(net,ptcloud,锚箱,......Gridparams,ClassNames,ConfidenceThreshold,Orectapthreshold,......P, N, executionEnvironment);%将检测到的框转换为旋转矩形格式。如果detectionResults ~ isempty(盒)。盒子{num} =盒(:,(1、2、4、5、7]);其他的indectResults.boxes {num} =框;结束检测仪器{num} =得分;检测results.labels {num} =标签;结束Metrics =评估术(检测结果,地下数据,......nmspositiveiouthreshold);DISP(指标(:,1:2))
AOS AP _______ _______汽车0.86746 0.86746卡车0.61463 0.61463

辅助功能

模型梯度

功能modelGradientsdlnetwork(深度学习工具箱)目的和迷你批次输入数据支柱Pillarindices.使用相应的地面真相盒,锚箱和网格参数。该函数返回关于可学习参数的丢失渐变,相应的迷你批量丢失和当前批次的状态。

模型梯度函数通过执行这些操作来计算总损耗和渐变。

  • 使用该预测从网络中提取预测向前(深度学习工具箱)功能。

  • 通过使用地面真实数据,网格参数和锚框来生成损耗计算的目标。

  • 计算来自网络的所有六个预测的损失函数。

  • 将总损失计算为所有损失的总和。

  • 在总损失方面计算学习栏的渐变。

函数[渐变,损失,状态] = MaposgRadients(网,Pillarfeatures,......Parkarindices,Boxlabels,Gridparams,锚盒,......numClasses,executionEnvironment) numAnchors = size(锚盒,2);%从网络中提取预测。ypredictions = cell(size(net.outputnames));[ypredictions {:},州] =前进(净,柱,支柱);%从地面真实数据生成预测目标。YTargets = generatePointPillarTargets (YPredictions boxLabels pillarIndices,......Gridparams,锚盒,numcrasses);ytargets = Cellfun(@ Dlarray,Ytargets,'统一输出'、假);如果(execultenvironment ==.“汽车”&& canusegpu)||executionenvironment ==.“GPU”YTargets = cellfun(@ gpuArray,YTargets,'统一输出'、假);结束[angloss,occloss,locloss,szloss,hdloss,clfloss] =......choppeintpillarloss(ypredictions,ytargets,gridparams,......numClasses numAnchors);%计算总损失。丢失= angloss + occloss + locloss + szloss + hdloss + clfloss;%在丢失方面计算了学习栏的渐变。梯度= Dlgradient(损失,Net.Learnables);结束函数[支柱,柱状,标签] = HelpercreatebatchData(......特性、指标groundTruthBoxes groundTruthClasses,类名)%返回柱子特征和索引沿批量尺寸组合沿标签中的批量维度连接的%和边界框。沿批处理维度的%连接功能和指标。Pillarfeatures = Cat(4,特征{:,1});Pillarindices = Cat(4,索引{:,1});%从类名获取类id。ClassNames = Repmat({分类(ClassNames')},大小(地面基条));[〜,classIndices] = Cellfun(@(a,b)ismember(a,b),地区,......一会,'统一输出'、假);%附加类索引并创建单个响应数组。= cellfun(@(bbox,classid) [bbox,classid],......地下框,分类,'统一输出'、假);len = max(cellfun(@(x)大小(x,1),contistresponses));PaddedBboxes = Cellfun(@(v)padarray(v,[len size(v,1),0],0,“职位”),......联邦责任,'统一输出'、假);标签=猫(4,paddedBBoxes {: 1});结束函数helperDownloadPandasetData (outputFolder lidarURL)%从给定的URL下载到输出文件夹的数据集。lidarDataTarFile = fullfile (outputFolder,'pandaset_lidardata.tar.gz');如果〜存在(LidardataTarfile,'文件'mkdir (outputFolder);disp (“正在下载PandaSet激光雷达驱动数据(5.2 GB)……”);Websave(LidardataTarfile,Lidarurl);Untar(LidardataTarfile,Outputfolder);结束%解压文件。如果(~存在(fullfile (outputFolder激光雷达的),“dir”))......&&(〜存在(fullfile(outputfile,“长方体”),“dir”)解压(lidarDataTarFile outputFolder);结束结束函数helperDownloadPretrainedPointPillarsNet (outputFolder pretrainedNetURL)%下载预先训练过的PointPillars网络。pretratematfile = fullfile(outputfolder,'trouthpointpillarspandasetnet.mat');pretrayzipfile = fullfile(outputfolder,'trouthpointpillarspandasetnet.zip');如果〜存在(pretratematfile,'文件'如果〜存在(pretrowzipfile,'文件') disp ('下载掠夺探测器(8.4 MB)......');websave (preTrainedZipFile pretrainedNetURL);结束解压缩(PretRateZipFile,OutputFolder);结束结束函数lossPlotter = helperConfigureTrainingProgressPlotter (f)%配置各种损耗的训练进度表。图(f);clf ylabel('总体损耗');Xlabel(“迭代”);lossPlotter = animatedline;结束函数retValue = helperCheckForNaN(梯度、损失)%已知最后一个卷积头'occupancy|conv2d'包含nan%的梯度。这个函数检查梯度值是否包含%纳尼。如果NANS将其他卷积头值添加到条件下%出现在梯度中。gradvalue =渐变.Value((渐变.Layer ==“入住率| conv2d”)&......(渐变。参数= ='偏见'));如果(SUM(ISNAN(提取数据(丢失)),“所有”) > 0) ||......(和(isnan (extractdata (gradValue {1 1})),“所有”)> 0)RetValue = True;其他的etvalue = false;结束结束函数Helperdisplay3dboxesoverlaidPointPlod(PTCLD,Labelscar,Carcolor,......LabelStruck,TruckColor,TitleFutigure)%显示不同颜色边界框的点云%班级。数字;AX = PCSHOW(PTCLD);showshape('长方体',labelscar,'父母'ax,'不透明度',0.1,......“颜色”,arcolor,'行宽', 0.5);抓住;showshape('长方体',labelstruck,'父母'ax,'不透明度',0.1,......“颜色”,卡车色,'行宽', 0.5);标题(titleForFigure);变焦(ax, 1.5);结束

参考文献

[1] LANG,ALEX H.,Sourabh Vora,Holger Caesar,Lubing Zhou,Jiong Yang和Oscar Beijbom。“PointPillars:来自点云的对象检测的快速编码器。”在2019 IEEE/CVF计算机视觉与模式识别会议(CVPR), 12689 - 12697。美国加州长滩:IEEE, 2019。https://doi.org/10.1109/cvpr.2019.01298

Hesai和Scale。PandaSet。https://scale.com/open-datasets/pandaset