主要内容

点云分类使用点深深学习

这个例子展示了如何训练一个PointNet网络来进行点云分类。

点云数据由各种传感器获取,如激光雷达、雷达和深度摄像机。这些传感器可以捕捉场景中物体的三维位置信息,这对自动驾驶和增强现实的许多应用都很有用。例如,区分车辆和行人对于规划自动驾驶汽车的路径至关重要。然而,使用点云数据训练稳健的分类器是具有挑战性的,因为每个目标的数据稀疏性、目标遮挡和传感器噪声。深度学习技术已经被证明可以通过直接从点云数据中学习稳健的特征表示来解决许多这些挑战。点云分类的重要深度学习技术之一是PointNet [1]。

此示例在悉尼大学创建的悉尼城市对象数据集上训练PointNet分类器[2]。该数据集提供了使用LIDAR传感器从城市环境获取的点云数据集合。数据集具有100个具有14个不同类别的标记对象,例如汽车,行人和公共汽车。

加载数据集

下载并将Sydney Urban Objects数据集提取到一个临时目录。

downloadDirectory = tempdir;datapath公司= downloadSydneyUrbanObjects (downloadDirectory);

使用下载下载的培训和验证数据设置loadydneyurnanobjectsdata.在这个例子的最后列出的辅助函数。前三个数据折叠用于训练,第四个数据折叠用于验证。

foldsTrain=1:3;foldsVal=4;dsTrain=loadSydneyUrbanObjectsData(数据路径,foldsTrain);dsVal=loadSydneyUrbanObjectsData(数据路径,foldsVal);

阅读其中一个训练样本,并使用它来形象化pcshow

data =阅读(dsTrain);ptCloud数据= {1};标签={1,2}数据;图pcshow(ptcloud.location,[0 1 0],“MarkerSize”,40,“VerticalAxisDir”“向下”)包含(“X”) ylabel (“Y”)Zlabel(“Z”标题(标签)

阅读标签并计算分配给每个标签的点数,以更好地理解数据集中标签的分布。

dsLabelCounts = transform(dsTrain,@(data){data{2} data{1}.Count}); / /显示数据labelCounts = readall (dsLabelCounts);标签= vertcat (labelCounts {: 1});数量= vertcat (labelCounts {: 2});

接下来,使用直方图来可视化类的分布。

图直方图(标签)

从标签直方图上可以看出,数据集是不平衡的,偏向于汽车和行人,这阻碍了鲁棒分类器的训练。可以通过对不常见的类进行过采样来解决类不平衡问题。对于Sydney Urban Objects数据集,复制与不频繁类对应的文件是解决类不平衡的简单方法。

按标签对文件进行分组,计算每个类的观察数,并使用randReplicateFilesHelper函数,在本例的最后列出,它可以随机地对文件进行过抽样,以达到每个类所需的观察数。

rng(0)[G,类]=FindGroup(标签);numObservations=splitapply(@numel,labels,G);desiredNumObservationsPerClass=最大值(numObservations);files=splitapply(@(x){randReplicateFiles(x,desiredNumObservationsPerClass)},dsTrain.files,G);files=vertcat(files{:});dsTrain.Files=文件;

数据增加

复制文件以解决类不平衡问题会增加过度拟合网络的可能性,因为大部分训练数据都是相同的。若要抵消此影响,请使用变换augmentPointCloud辅助功能,随机旋转点云,随机删除点,随机抖动点和高斯噪声点。

dsTrain =变换(dsTrain @augmentPointCloud);

预览其中一个增强训练示例。

data =预览(dsTrain);ptCloud数据= {1};标签={1,2}数据;图pcshow(ptcloud.location,[0 1 0],“MarkerSize”,40,“VerticalAxisDir”“向下”)包含(“X”) ylabel (“Y”)Zlabel(“Z”标题(标签)

注意,由于用于测量训练网络性能的数据必须是原始数据集的代表,因此数据增广不适用于验证或测试数据。

数据预处理

准备用于训练和预测的点云数据需要两个预处理步骤。

首先,为了在训练过程中进行批处理,从每个点云中选择固定数量的点。最佳的点数取决于数据集和精确捕捉物体形状所需的点数。为了帮助选择适当的点数,计算每个类的最小、最大和平均点数。

minPointCount=splitapply(@min,counts,G);maxPointCount=splitapply(@max,counts,G);meanPointCount=splitapply(@x)轮(平均数(x)),计数,G);stats=table(类,numObservations,minPointCount,maxPointCount,meanPointCount)
统计=14×5表类numObservations minPointCount maxPointCount meanPointCount  ______________ _______________ _____________ _____________ ______________ 4 wd 15 140 1955 751 126 11767 193 8455 2708总线11 2190车64 52 2377 528步行15 80 751 357 107 297 110柱杆13 253 90红绿灯36 38 352 161交通标志40 18 736 126Tree 24 53 2953 470 truck 9 445 3013 1376 trunk 42 32 766 241 ute 12 90 1380 580 van 28 91 5809 1125

由于每个类的点数的类内和级别的帧间互变性,选择适合所有类的值是困难的。一个启发式是选择足够的点来充分捕捉物体的形状,同时不会通过处理太多点来提高计算成本。值1024在这两个方面之间提供了良好的权衡。您还可以根据实证分析选择最佳点数。但是,这超出了这个例子的范围。使用变换函数在训练和验证集中选择1024个点。

numPoints = 1024;dsTrain =变换(dsTrain @(数据)selectPoints(数据、numPoints));dsVal =变换(dsVal @(数据)selectPoints(数据、numPoints));

最后的预处理步骤是将0到1之间的点云数据标准化,以考虑数据值范围的较大差异。例如,与进一步远离的物体相比,更接近LIDAR传感器的物体具有较小的值。这些差异可以在训练期间阻碍网络的收敛性。用变换对训练集和验证集中的点云数据进行归一化处理。

dsTrain =变换(dsTrain @preprocessPointCloud);dsVal =变换(dsVal @preprocessPointCloud);

预览增强和预处理的训练数据。

data =预览(dsTrain);图pcshow(data{1,1},[0 1 0],“MarkerSize”,40,“VerticalAxisDir”“向下”);包含(“X”) ylabel (“Y”)Zlabel(“Z”{1,2})标题(数据)

定义PointNet模型

PointNet分类模型由两个组件组成。第一个组件是点云编码器,它学习将稀疏的点云数据编码成密集的特征向量。第二个组件是一个分类器,用于预测每个编码点云的分类类别。

PointNet编码器模型进一步由四个模型和一个max操作组成。

  1. 输入变换模型

  2. 共享网络模型

  3. 功能变换模型

  4. 共享网络模型

共享MLP模型使用一系列卷积、批处理归一化和ReLU操作来实现。卷积操作被配置为在输入点云之间共享权值。转换模型由共享的MLP和应用于每个点云的可学习的转换矩阵组成。共享的MLP和max操作使PointNet编码器对处理点的顺序保持不变,而转换模型对方向变化提供不变性。

定义注意力点编码器模型参数

共享的MLP和转换模型通过输入通道的数量和隐藏通道的大小进行参数化。本例中选择的值是通过调优Sydney Urban Objects数据集上的超参数来选择的。注意,如果希望将PointNet应用于不同的数据集,则必须执行额外的超参数调优。

将输入变换模型输入通道大小设置为3,将隐藏通道大小设置为64、128和256,然后使用initializeTransform.辅助功能,在此示例结束时列出,以初始化模型参数。

inputChannelSize = 3;hiddenChannelSize1 = [64128];hiddenChannelSize2 = 256;(参数。在putTransform, state.InputTransform] = initializeTransform(inputChannelSize,hiddenChannelSize1,hiddenChannelSize2);

设置第一个共享的MLP模型输入通道大小为3,隐藏通道大小为64,并使用initializeSharedMLP辅助功能,在此示例结束时列出,以初始化模型参数。

inputChannelSize = 3;hiddenchannelsize = [64 64];[parameters.sharedmlp1,state.sharedmlp1] = initializeSharedmlp(InputChannelsize,HiddenChannelsize);

将要素转换模型输入通道大小设置为64,将隐藏通道大小设置为64、128和256,然后使用initializeTransform.辅助功能,在此示例结束时列出,以初始化模型参数。

inputChannelSize = 64;hiddenChannelSize1 = [64128];hiddenChannelSize2 = 256;(参数。FeatureTransform,状态。FeatureTransform] = initializeTransform (inputChannelSize, hiddenChannelSize hiddenChannelSize2);

设置第二个共享MLP模型输入通道大小为64,隐藏通道大小为64,并使用initializeSharedMLP函数,在本例末尾列出,用于初始化模型参数。

inputChannelSize=64;hiddenChannelSize=64;[parameters.SharedMLP2,state.SharedMLP2]=初始化SharedMLP(inputChannelSize,hiddenChannelSize);

定义点网分类器模型参数

PointNet分类器模型由一个共享MLP、一个完全连接的操作和一个softmax激活组成。设置分类器模型输入大小为64,隐藏通道大小为512和256,使用initalizeClassifier辅助功能,在此示例结束时列出,以初始化模型参数。

inputChannelSize = 64;hiddenChannelSize = [512256];numClasses =元素个数(类);(参数。ClassificationMLP,状态。ClassificationMLP] = initializeClassificationMLP (inputChannelSize, hiddenChannelSize numClasses);

定义PointNet函数

创建函数pointnetClassifier,以计算PointNet模型的输出。函数模型将点云数据、可学习的模型参数、模型状态和指定模型返回输出用于训练还是预测的标志作为输入。网络返回对输入点云进行分类的预测。

定义模型梯度函数

创建函数modelGradients,它将模型参数、模型状态和一小批输入数据作为输入,并返回相对于模型中可学习参数的损失梯度和相应的损失。

指定培训选项

训练10个纪元,批量装载数据128次。设置初始学习率为0.002,L2正则化系数为0.01。

numEpochs = 10;learnRate = 0.002;miniBatchSize = 128;l2Regularization = 0.01;learnRateDropPeriod = 15;learnRateDropFactor = 0.5;

初始化ADAM优化选项。

gradientDecayFactor = 0.9;squaredGradientDecayFactor = 0.999;

火车PointNet

使用自定义训练循环训练模型。

在训练开始时洗牌数据。

每一次迭代:

  • 读取一批数据。

  • 评估模型梯度。

  • 应用L2权值正则化。

  • adamupdate更新模型参数。

  • 更新培训进度图。

在每个阶段的最后,根据验证数据集评估模型,并收集混淆指标来衡量训练过程中的分类精度。

在完成learnRateDropPeriod时代,减少了学习率learnRateDropFactor

初始化参数梯度的移动平均值和Adam优化器使用的梯度的元素平方。

avgGradients = [];avgSquaredGradients = [];

训练模型,如果doTraining是真的。否则,加载预训练的网络。

请注意,训练是在带有12gb GPU内存的NVIDIA Titan X上验证的。如果你的GPU内存更少,你可能会在训练期间耗尽内存。如果发生这种情况,降低miniBatchSize.训练这个网络大约需要5分钟。取决于你的GPU硬件,它可能需要更长的时间。

doTraining = false;如果doTraining%创建一个minibatchqueue来批处理来自培训和验证的数据%数据存储。使用batchData函数,列在%例如,批处理点云数据并对标签进行热编码%的数据。numoutsfromdsread=2;mbqTrain=minibatchqueue(dsTrain,numoutsfromdsread,...“迷你atchsize”,小批量,...“MiniBatchFcn”@batchData,...“MiniBatchFormat”,[“SCSB”“公元前”]);mbqVal=minibatchqueue(dsVal,numoutsfromdsread,...“迷你atchsize”,小批量,...“MiniBatchFcn”@batchData,...“MiniBatchFormat”,[“SCSB”“公元前”]);%使用configureTrainingProgressPlot函数,列在文件末尾%示例,初始化训练进度图以显示训练%损失,培训准确性和验证准确性。[lossPlotter, trainAccPlotter,valAccPlotter] = initializeTrainingProgressPlot;numClasses =元素个数(类);迭代= 0;开始=抽搐;时代= 1:numEpochs%每个epoch Shuffle data。洗牌(mbqTrain);%遍历数据集。尽管hasdata(mbqTrain) iteration = iteration + 1;%读取下一批训练数据。[XTrain, YTrain] = next(mbqTrain);使用dlfeval和% modelGradients函数。[gradient, loss, state, acc] = dlfeval(@modelGradients,XTrain,YTrain,parameters,state);% L2正规化。梯度= dlupdate(@(g,p)g + l2regularization * p,梯度,参数);%使用Adam优化器更新网络参数。[parameter, avgGradients, avgSquaredGradients] = adamupdate(parameter, gradients, avgSquaredGradients)...avgGradients avgSquaredGradients,迭代,...学习,梯度dayfactor,squaredgradientdecayfactor);%更新培训进度。d =持续时间(0,0,toc(start),“格式”“hh: mm: ss”);标题(lossPlotter。父母,”时代:“+时代+”,过去:“+字符串(d))addpoints(lockplotter,reateration,double(收集(提取数据(丢失))))等分点(训练料accplotter,迭代,acc);drawn结束%根据验证数据评估模型。Cmat =稀疏(Numcrasses,Numcrasses);尽管hasdata (mbqVal)读取下一批验证数据。[XVal, YVal] = next(mbqVal);%计算标签预测。isTraining = false;YPred = pointnetClassifier (XVal、参数状态,isTraining);%选择得分最高的预测作为类标签% XTest。[~, YValLabel] = max (YVal [], 1);[~, YPredLabel] = max (YPred [], 1);收集混淆指标。cmat = aggreateConfusionMetric (cmat YValLabel YPredLabel);结束%以平均分类精度更新训练进度图。acc=总和(诊断(cmat))。/总和(cmat,“所有”);addpoints (valAccPlotter迭代,acc);%更新学习率。如果mod(epoch,sechnratedropperiod)== 0 snownrate = lavingrate * shearchratedropfactor;结束%重置训练和验证数据队列。重置(MBQTrain);重置(MBQVAL);结束别的%下载返回售价模型参数,模型状态和验证%的结果。pretrainedURL =“https://ssd.mathworks.com/金宝appsupportfiles/vision/data/pointnetSydneyUrbanObjects.zip”;pretrainedResults = downloadPretrainedPointNet (pretrainedURL);参数= pretrainedResults.parameters;状态= pretrainedResults.state;cmat = pretrainedResults.cmat;%如果可能的话,将模型参数移动到GPU并转换为dlarray。参数= prepareForPrediction(参数,@ (x) dlarray (toDevice (x, canUseGPU)));%如果可能,将模型状态移到GPU。状态= prepareForPrediction(状态,@ (x) toDevice (x, canUseGPU));结束

显示验证混淆矩阵。

Figure chart = confusionchart(cma,classes);

计算平均训练和验证精度。

acc=总和(诊断(cmat))。/总和(cmat,“所有”
acc = 0.5742

由于悉尼城市对象数据集中的训练样本数量有限,将验证精度提高到60%以上是一项挑战。如果没有在AugmentPointClouddata.helper函数。为了提高PointNet分类器的鲁棒性,需要进行额外的训练。

使用PointNet对点云数据进行分类

加载点云数据pcread,使用训练时使用的相同函数对点云进行预处理,并将结果转换为dlarray.

ptCloud = pcread (“car.pcd”);X = preprocessPointCloud (ptCloud);dlX = dlarray (X {1},“SCSB”);

用的方法预测点云标签pointnetClassifier模型的功能。

YPred = pointnetClassifier (dlX、参数、状态、错误);[~, classIdx] = max (YPred [], 1);

显示得分最高的点云和预测标签。

图pcshow(ptcloud.location,[0 1 0],“MarkerSize”,40,“VerticalAxisDir”“向下”标题(类(classIdx))

模型梯度函数

modelGradients函数将一小批数据作为输入dlX,对应的目标海底,并返回损失相对于可学习参数和相应损失的梯度。损失包括一个正则化项,该正则化项旨在确保PointNet编码器预测的特征变换矩阵近似正交。要计算梯度,请计算modelGradients函数使用dlfeval在训练循环中起作用。

功能[gradient, loss, state, acc] = modelGradients(X,Y,parameters,state)%执行模型函数。isTraining = true;[YPred、州dlT] = pointnetClassifier (X,参数,状态,isTraining);%添加正则化术语以确保功能变换矩阵是%大致正交的。K =大小(dlT, 1);B = size(dlT, 4);我= repelem(眼(K), 1, 1, 1, B);dlI = dlarray(我“SSCB”);treg = mse(dlI,pagemtimes(dlT,permute(dlT,[2 1 3 4])));系数= 0.001;%计算丢失。loss = crossentropy(YPred,Y) + factor*treg;%在丢失上计算参数梯度。gradient = dlgradient(loss, parameters);%计算训练精度度量。[~,欧美]= max (Y, [], 1);[~, YPred] = max (YPred [], 1);acc = gather(extractdata(sum(YTest == YPred)./numel(YTest)));结束

PointNet分类器函数

pointnetClassifier函数将点云数据dlX、可学习的模型参数、模型状态和标志isstrain作为输入,isstrain表示模型返回的输出是用于训练还是预测。然后,函数调用PointNet编码器和多层感知器来提取分类特征。在训练过程中,每一次感知器操作后都应用dropout。在最后一个感知器a之后完全连接操作将分类功能映射到类的数量,并且softmax激活用于将输出标准化为标签的概率分布。概率分布,更新的模型状态和注意力编码器预测的特征变换矩阵作为输出返回。

功能(海底、州dlT) = pointnetClassifier (dlX、参数、状态、isTraining)%调用PointNet编码器。[dlY,state,dlT]=pointnetEncoder(dlX,参数,状态,正在训练);%调用分类器。p = parameters.ClassificationMLP.Perceptron;s = state.ClassificationMLP.Perceptron;k = 1:元素个数(p)[海底,s (k)] =感知器(海底,p (k), s (k), isTraining);%如果进行训练,则应用倒退的概率为0.3。如果约束概率= 0.3;dropoutScaleFactor = 1 -概率;dropoutMask = (rand(size(dlY),“喜欢”, d) > probability) / dropoutScaleFactor;海底=海底。* dropoutMask;结束结束state.ClassificationMLP.Perceptron = s;%应用最终的完全连接和softmax操作。权重=parameters.ClassificationMLP.FC.weights;bias=parameters.ClassificationMLP.FC.bias;dlY=完全连接(dlY,权重,bias);dlY=softmax(dlY);结束

点网编码器函数

pointnetEncoder函数使用一个输入转换、一个共享MLP、一个特征转换、第二个共享MLP和一个max操作处理输入dlX,并返回max操作的结果。

功能(海底,状态,T) = pointnetEncoder (dlX、参数、状态、isTraining)%输入变换。[dlY,state.InputTransform]=数据转换(dlX,parameters.InputTransform,state.InputTransform,isTraining);%共享延时。(海底,state.SharedMLP1。感知器]= sharedMLP(海底,parameters.SharedMLP1.Perceptron, state.SharedMLP1.Perceptron isTraining);%功能变换。(海底,状态。FeatureTransform T] = dataTransform(海底,parameters.FeatureTransform, state.FeatureTransform isTraining);%共享延时。(海底,state.SharedMLP2。感知器]= sharedMLP(海底,parameters.SharedMLP2.Perceptron, state.SharedMLP2.Perceptron isTraining);%最大操作。海底= max(海底,[],1);结束

共享多层感知器函数

共享的多层感知器函数使用一系列感知机操作处理输入dlX,并返回最后一个感知机的结果。

功能[dlY,state] = sharedMLP(dlX,parameters,state, is拴住)k = 1:numel(parameters) [dlY, state(k)] =感知机(dlY,parameters(k),state(k), istrain);结束结束

Perceptron功能

感知器函数使用卷积、批处理和relu操作处理输入dlX,并返回relu操作的输出。

功能(海底、州)=感知器(dlX、参数、状态、isTraining)%卷积。W = parameters.Conv.Weights;B = parameters.Conv.Bias;海底= dlconv (dlX, W, B);%批正常化。在培训时更新批标准化状态。抵消= parameters.BatchNorm.Offset;规模= parameters.BatchNorm.Scale;trainedMean = state.BatchNorm.TrainedMean;trainedVariance = state.BatchNorm.TrainedVariance;如果isTraining[Dy,trainedMean,trainedVariance]=批次标准(Dy,偏移量,比例,trainedMean,trainedVariance);%更新状态。state.BatchNorm.TrainedMean = trainedMean;state.BatchNorm.TrainedVariance = trainedVariance;别的海底= batchnorm(海底、抵消、规模、trainedMean trainedVariance);结束% ReLU。海底= relu(海底);结束

数据转换功能

dataTransform函数处理输入dlX使用一个共享的MLP,一个max操作,和另一个共享的MLP来预测一个变换矩阵t。该函数返回批处理矩阵相乘和变换矩阵的结果。

功能(海底,状态,T) = dataTransform (dlX、参数、状态、isTraining)%共享延时。(海底,state.Block1。感知器]= sharedMLP (dlX、parameters.Block1.Perceptron state.Block1.Perceptron, isTraining);%最大操作。海底= max(海底,[],1);%共享延时。(海底,state.Block2。感知器]= sharedMLP(海底,parameters.Block2.Perceptron, state.Block2.Perceptron isTraining);%变换网(T-Net)。将上次完全连接的操作(如W*X)应用到%预测变换矩阵T。海底=挤压(海底);%N×BT =参数。变换* stripdims(海底);% K ^ 2-by-B%将T重塑为一个方阵。K =√大小(T, 1));T =重塑(T, K, K, 1, []);% k + k + bT = T +眼(K);%使用批处理矩阵乘法输入dlX。[C,B]=尺寸(dlX,[34]);%[M 1 K B]dlX =重塑(dlX, [], C, 1 B);(b) n ' m / bY = pagemtimes (dlX T);海底= dlarray (Y,“SCSB”);结束

模型参数初始化函数

initializeTransform.函数

initializeTransform.函数接受两个共享mlp的通道大小和隐藏通道数量作为输入,并在结构中返回初始化的参数。使用He权重初始化参数[3.]。

功能[params,state] = initializeTransform(inputChannelSize,block1,block2)Block1] = initializeSharedMLP (inputChannelSize Block1);[params.Block2状态。Block2] = initializeSharedMLP (block1(结束),Block2);%变换矩阵的参数。参数个数。变换= dlarray (0 (inputChannelSize ^ 2, block2(结束)));结束

initializeSharedMLP函数

initializeShareDMLP函数作为输入频道大小和隐藏的通道大小,并在结构中返回初始化参数。使用他的重量初始化初始化参数。

功能[params,state] = initializesharedmlp(inputchcannelsize,hiddenhennelsize)权重= initializewightshe([1 1 inputchcannelsize hiddenhannelsize(1)]);BIAS = Zeros(HiddenChannelsize(1),1,“单身”);p.Conv.Weights = dlarray(重量);p.Conv.Bias = dlarray(偏差);p.BatchNorm.Offset = dlarray (0 (hiddenChannelSize (1), 1,“单身”)); p、 BatchNorm.Scale=dlarray(个数(hiddenChannelSize(1),1,“单身”));s.BatchNorm.TrainedMean = 0 (hiddenChannelSize (1), 1,“单身”);s.BatchNorm.TrainedVariance = 1 (hiddenChannelSize (1), 1,“单身”);params.Perceptron (1) = p;state.Perceptron (1) = s;k = 2:numel(hiddenChannelSize) weights = initializeWeightsHe([1 1 hiddenChannelSize(k-1))]);偏见= 0 (hiddenChannelSize (k), 1,“单身”);p.Conv.Weights = dlarray(重量);p.Conv.Bias = dlarray(偏差);p.BatchNorm.Offset = dlarray (0 (hiddenChannelSize (k), 1,“单身”));p.BatchNorm.Scale=dlarray(个数(hiddenChannelSize,k),1,“单身”));s.BatchNorm.TrainedMean = 0 (hiddenChannelSize (k), 1,“单身”);s.BatchNorm.TrainedVariance=个(hiddenChannelSize(k),1,“单身”);params.Perceptron (k) = p;state.Perceptron (k) = s;结束结束

initializeClassificationMLP函数

initializeClassificationMLP函数接受通道大小、隐藏的通道大小和类的数量作为输入,并在结构中返回初始化的形参。共享MLP使用He权值初始化,最终的全连接操作使用随机高斯值初始化。

功能[params,state] = initializeSharedMLP(inputChannelSize,hiddenChannelSize,numClasses);weights = initializeWeightsGaussian([numClasses hiddenChannelSize(end)]);偏见= 0 (numClasses 1“单身”);params.fc.weights = dlarray(重量);params.fc.bias = dlarray(偏见);结束

initializeWeightsHe函数

initializeWeightsHe函数使用He初始化参数。

功能x = initializeWeightsHe(sz) fanIn = prod(sz(1:3));stddev =√2 /扇入);X = stddev .* randn(sz); / /指定一个数组结束

initializeWeightsGaussian函数

initializeWeightsGaussian函数使用标准偏差为0.01的高斯初始化方法初始化参数。

功能x = initializeWeightsGaussian(sz)“单身”) * 0.01;结束

数据预处理功能

预处理点云数据函数

预处理点云数据功能从输入数据中提取x,y,z点数据,并将数据归一化0到1之间的数据。函数返回归一化x,y,z数据。

功能数据=预处理点云(数据)如果〜Iscell(数据)数据= {data};结束numObservations =大小(数据,1);i = 1:numobservations百分数在0到1之间。xlim ={我1}.XLimits数据;ylim ={我1}.YLimits数据;zlim ={我1}.ZLimits数据;xyzMin = [xlim(1) ylim(1) zlim(1)];drawtext (xyzDiff = [diff(xlim) diff(ylim) diff(zlim)]];{我1}=(数据{1}我。位置- xyzMin) ./ xyzDiff;结束结束

selectPoints函数

selectPoints函数对期望的点数进行采样。当点云包含的点超过所需的数量时,该函数使用pcdownsample随机选择点。否则,该函数复制数据以产生所需的点数。

功能numPoints data = selectPoints(数据)%通过向下采样或复制选择所需的点数%点云数据。numObservations =大小(数据,1);i = 1:numObservations ptCloud = data{i,1};如果ptCloud。Count > numPoints percentage = numPoints/ptCloud.Count;数据{1}= pcdownsample (ptCloud,“随机”、比例);别的replicationFactor=ceil(numPoints/ptCloud.Count);ind=repmat(1:ptCloud.Count,1,replicationFactor);data{i,1}=select(ptCloud,ind(1:numPoints));结束结束结束

数据增强功能

AugmentPointClouddata.函数围绕z轴随机旋转点云,随机下降30%的点,并使用高斯噪声随机抖动点位置。

功能data=augmentPointCloud(data)numObservations=size(data,1);i = 1:numObservations ptCloud = data{i,1};%旋转点云的“上轴”,也就是这个数据集的Z轴。tform = randomAffine3d (...“XReflection”,真的,...“yreflection”,真的,...“旋转”, @randomRotationAboutZ);ptCloud = pctransform (ptCloud tform);%随机丢弃了分数的30%。如果rand > 0.5 ptCloud = pcdownsample(ptCloud,“随机”, 0.3);结束如果兰德> 0.5%抖动的点位置与高斯噪声的平均值为0和通过创建一个随机位移场,得到0.02的标准偏差。D = 0.02 * randn(size(ptCloud.Location));ptCloud = pctransform (ptCloud D);结束数据{1}= ptCloud;结束结束功能[旋转轴,theta] = randomRotationAboutZ()旋转轴= [0 0 1];θ= 2 *π*兰特;结束

金宝app支持功能

aggregateconfusionmetric函数

aggregateconfusionmetric函数根据预测结果递增地填充混淆矩阵伊普雷德预期结果ytest.

功能cmat = aggreateConfusionMetric(cmat,YTest,YPred) YTest = gather(extractdata(YTest));YPred =收集(extractdata (YPred));[m, n] =大小(cmat);cmat = cmat + full(稀疏(YTest,YPred,1,m,n));结束

初始化TrainingProgressPlot函数

初始化TrainingProgressPlot函数配置用于显示训练损失、训练精度和验证精度的两个绘图。

功能[绘图仪,trainAccPlotter valAccPlotter] = initializeTrainingProgressPlot ()%绘制损失、培训准确度和验证准确度。图形%损失情节Subplot (2,1,1) = animatedline;包含(“迭代”) ylabel (“损失”%准确性图subplot(2,1,2) trainAccPlotter = animatedline(“颜色”“b”);valAccPlotter = animatedline (“颜色”“g”);传奇(“训练的准确性”“验证准确性”“位置”“西北”);包含(“迭代”) ylabel (“准确性”结束

replicateFiles函数

replicateFiles函数随机过度清除一组文件并返回一组文件numdesired.元素。

功能n = nummel (files); / /文件的数量印第安纳州=兰迪(n, numDesired, 1);文件=文件(印第安纳州);结束

downloadSydneyUrbanObjects函数

downloadSydneyUrbanObjects函数下载数据集并将其保存到临时目录。

功能datapath公司= downloadSydneyUrbanObjects (dataLoc)如果nargin == 0 dataLoc = pwd;结束dataLoc=字符串(dataLoc);url=“http://www.acfr.usyd.edu.au/papers/data/”;名称=“sydney-urban-objects-dataset.tar.gz”;datapath公司= fullfile (dataLoc,“sydney-urban-objects-dataset”);如果~存在(datapath公司,“dir”)disp(“正在下载悉尼城市物体数据集……”);解压(url +名字,dataLoc);结束结束

loadydneyurnanobjectsdata.函数

的loadSydneyUrbanObjectsData函数创建用于加载点云的数据存储和来自悉尼城市对象数据集的标签数据。

功能ds = loadSydneyUrbanObjectsData (datapath公司、折叠)如果nargin == 0.返回结束如果Nargin < 2 fold = 1:4;结束datapath公司=字符串(datapath公司);路径= fullfile (datapath公司,'物体', filesep);%向数据存储中添加折叠。foldNames {1} = importdata (fullfile (datapath公司,“折叠”“fold0.txt”));foldNames {2} = importdata (fullfile (datapath公司,“折叠”“fold1.txt”));foldNames {3} = importdata (fullfile (datapath公司,“折叠”“fold2.txt”));foldNames{4}=importdata(完整文件(数据路径,“折叠”“fold3.txt”));名称= foldNames(折叠);名称= vertcat(名字{:});fullFilenames = append(路径、名称);ds = fileDatastore (fullFilenames,“ReadFcn”,@ExtrainingData,“FileExtensions”“。斌”);结束

batchData函数

batchData函数将数据整理成批,并将数据移动到GPU进行处理。

功能[X,Y] = batchData(ptCloud,labels) X = cat(4,ptCloud{:});标签=猫(1、标签{:});Y = onehotencode(标签,2);结束

提取器Data.函数

extractTrainingData函数从悉尼城市对象数据集中提取点云和标签数据。

功能dataOut=extractTrainingData(fname)[pointData,intensity]=readbin(fname);[~,name]=fileparts(fname);name=string(name);name=extractBefore(name,“。”);名称=替换(名称,“_”' ');labelNames = [“四轮驱动”“建筑”“公共汽车”“汽车”“行人”“支柱”...“极”“红绿灯”“交通标志”“树”“卡车”“树干”“哑巴”“范”];标签=分类(名称、labelNames);dataOut = {pointCloud (pointData'强度',强度),标签};结束

readbin函数

readbin函数从Sydney Urban Object二进制文件中读取点云数据。

功能(pointData、强度)= readbin(帧)% readbin从悉尼城市目标二进制中读取点和强度数据%的文件。% name = ['t','intensity','id',…]% ' x ', ' y ', ' z ',……%“方位角”、“距离”、“pid”]% formats = ['int64', 'uint8', 'uint8',…% ` float32 `, ` float32 `, ` float32 `,…% ` float32 `, ` float32 `, ` int32 `]fid = fopen(帧,“r”);c = oncleanup(@()fclose(fid));FSEEK(FID,10,-1);从开始移动到第一个X点位置10个字节x = fread(fid,inf,“单身”, 30);fseek (fid, 14日1);Y =从文件中读(fid,正无穷,“单身”, 30);fseek(支撑材,18岁,1);Z =从文件中读(fid,正无穷,“单身”, 30);fseek(支撑材8 1);强度=从文件中读(fid,正无穷,“uint8”33);pointData = [X, Y, Z];结束

downloadPretrainedPointNet函数

downloadPretrainedPointNet函数下载预先训练的pointnet模型。

功能data = downloadPretrainedPointNet (pretrainedURL)%下载和加载一个预先训练的pointnet模型。如果~ ('pointnetSydneyUrbanObjects.mat'“文件”如果~ (“pointnetSydneyUrbanObjects.zip”“文件”)disp(“下载预训练探测器(5mb)……”);韦伯斯韦(“pointnetSydneyUrbanObjects.zip”,pretrowsurl);结束解压(“pointnetSydneyUrbanObjects.zip”);结束data =负载(“pointnetSydneyUrbanObjects.mat”);结束

prepareForPrediction函数

prepareForPrediction函数用于将用户定义的函数应用于嵌套的结构数据。用于将模型参数和状态数据移动到GPU。

功能p = prepareForPrediction (p, fcn)i = 1:元素个数(p) p (i) = structfun (@ (x)调用(fcn x)、p (i),“UniformOutput”,0);结束功能data =调用(fcn、数据)如果isstruct(数据)数据=准备预测(数据,fcn);别的data = fcn(数据);结束结束结束%将数据移动到GPU。功能x = toDevice (x, useGPU)如果useGPU x = gpuArray(x);结束结束

参考文献

Charles, R. Qi, Hao Su, Mo Kaichun, Leonidas J. gu巴斯。PointNet:用于三维分类和分割的点集深度学习。在2017年IEEE计算机视觉和模式识别会议(CVPR),77-85。檀香山,嗨:IEEE,2017. https://doi.org/10.1109/cvpr.2017.16。

[2] de Deuge,Mark,Alastair Quadras,Calvin Hung和Bertrand Douillad.“户外3D扫描分类的无监督特征学习”,摘自2013澳大拉西亚机器人与自动化会议(ACRA 13).澳大利亚悉尼:ACRA, 2013。

[3] 何开明、张向宇、任少清和孙健。“深入研究整流器:在ImageNet分类上超越人类水平的性能。”年2015 IEEE计算机视觉国际会议(ICCV)1026 - 34。智利圣地亚哥:IEEE, 2015。https://doi.org/10.1109/ICCV.2015.123。

相关的话题