主要内容

训练分类网络对三维点云目标进行分类

这个例子demontrates中概述的方法[1,点云数据预处理为体素化编码,然后直接使用一个简单的3-D卷积神经网络结构进行对象分类。在最近的一些方法中,如[2],点云数据的编码可能更为复杂,并且可以通过网络执行分类/目标检测/分割任务来学习端到端的编码。然而,从不规则无序点移动到网格结构的一般模式在所有t这是我的建议。

导入和分析数据

在这个例子中,我们的工作与悉尼市区对象数据集。在这个例子中,我们使用来自数据作为训练集折叠1-3和折叠4作为验证组。

dataPath公司= downloadSydneyUrbanObjects (tempdir);dsTrain = loadSydneyUrbanObjectsData(数据路径,[1 2 3]);dsVal = loadSydneyUrbanObjectsData (dataPath公司,4);

分析培训集以了解数据中的标签以及标签的总体分布。

dsLabels =变换(dsTrain,@(数据)数据{2});标签= readall(dsLabels);图直方图(标签)

从直方图中可以明显看出,训练数据中存在类不平衡问题,其中某些对象类汽车行人比不那么频繁的课程更常见吗尤特

数据增强管道

为了避免过拟合并增强分类器的鲁棒性,在训练网络时,通常需要进行一定数量的随机数据增强。的函数randomAffine2dpctransform使在点云数据上定义随机仿射变换变得容易。我们还为每个点云中的每个点添加了一些随机逐点抖动。函数增强点云数据包含在下面的支持功能部分中。金宝app

dsTrain =变换(dsTrain @augmentPointCloudData);

验证点云数据的增加是否合理。

DATAOUT =预览(dsTrain);图pcshow(DATAOUT {1});标题(DATAOUT {2});

接下来,我们添加为前面的例子中所讨论的,我们的输入点云转化为可使用卷积神经网络中使用的伪像一个简单的体素化转换到每一个输入点云。使用简单占用电网。

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

查看最终素化量,我们将提供给网络,以验证voxelixation正常工作的一个样本。

数据=预览(dsTrain);图P =补丁(等值面(数据{1},0.5));p.FaceColor =“红色”;p.EdgeColor ='没有任何';daspect([1 1 1])视图(45,45)camlight;灯光标题(数据{2});

定义网络架构

在本例中,我们使用了一个简单的三维分类体系结构,如[1]所述。

[image3dInputLayer([32 32 32],]),“名字”“inputLayer”'正常化''没有任何'),convolution3dLayer(5,32,“步”,2,“名字”'CONV1'),leakyReluLayer (0.1,“名字”“leakyRelu1”),32岁的convolution3dLayer (3“步”1,“名字”“Conv2”),leakyReluLayer (0.1,“名字”'leakyRulu2'),maxPooling3dLayer (2“步”,2,“名字”“maxPool”),fullyConnectedLayer(128,“名字”“fc1”),reluLayer (“名字”“雷卢”),dropoutLayer (0.5,“名字”'dropout1'),fullyConnectedLayer(14日“名字”“取得”),softmaxLayer(“名字”“softmax”),classificationLayer(“名字”'crossEntropyLoss')];voxnet=图层图(图层);图形图(voxnet);

设置培训选项

使用带动量的随机梯度下降,并对学习率计划进行分段调整。这个例子是在TitanX GPU上运行的,对于内存更少的GPU,可能需要减少批大小。尽管3D卷积网络具有概念简单的优点,但它们在训练时使用大量内存的缺点。

miniBatchSize=32;dsLength=length(dsTrain.underyingDataStore.Files);iterationsPerEpoch=floor(dsLength/miniBatchSize);dropPeriod=floor(8000/iterationsPerEpoch);options=trainingOptions('SGDM''InitialLearnRate',0.01%,“MiniBatchSize”,miniBatchSize,'LearnRateSchedule'“分段”“LearnRateDropPeriod”,dropPeriod,“验证数据”,dsVal,“MaxEpochs”60,“调度背景”错误的“洗牌”“永远”);

列车网络

voxnet = trainNetwork (dsTrain、voxnet选项);
关于单CPU的培训。|=======================================================================================================================================================================================================================================================================================================================================历元|迭代|经过的时间|小批量|验证|小批量|验证|基础学习| | | |(hh:mm:ss)第二方第第第二方第第二方第第二方第第第二方第第第第二方第第第第第第第第第二方第第第第第第二方第第第二方第第第第第第第第第第二方第第第二方第第二方第第第二方第第二方第第二方第二方第第=============================================第第第第第第第=====================第第第第第第第第第第第第第==============================第第第第第第第第第第第第第第第第第第第第第===================================================第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第第6579 | 2.6466 | 0.0100 | 4 | 50 | 00:01:53 | 31.25%| 29.03%| 2.1520 | 2.3095 | 0.0100 | 8 | 100 | 00:03:33 | 28.12%| 36.77%| 2.2633 |2.1510 | 0.0100 | | 12 | 150 | 00:05:11 | 43.75% | 46.45% | 2.0506 | 1.9057 | 0.0100 | | 16 | 200 | 00:06:49 | 37.50% | 52.26% | 1.8627 | 1.6161 | 0.0100 | | 20 | 250 | 00:08:35 | 50.00% | 59.35% | 1.8573 | 1.4587 | 0.0100 | | 24 | 300 | 00:10:14 | 34.38% | 58.06% | 1.8636 | 1.4360 | 0.0100 | | 27 | 350 | 00:11:51 | 62.50% | 61.94% | 1.4174 | 1.3093 | 0.0100 | | 31 | 400 | 00:13:31 | 65.62% | 64.52% | 1.1966 | 1.2727 | 0.0100 | | 35 | 450 | 00:15:09 | 56.25% | 61.94% | 1.3562 | 1.2473 | 0.0100 | | 39 | 500 | 00:16:49 | 62.50% | 66.45% | 1.2819 | 1.1354 | 0.0100 | | 43 | 550 | 00:18:27 | 56.25% | 65.16% | 1.4563 | 1.1351 | 0.0100 | | 47 | 600 | 00:20:05 | 56.25% | 66.45% | 1.3096 | 1.1142 | 0.0100 | | 50 | 650 | 00:21:40 | 56.25% | 65.16% | 1.0104 | 1.1023 | 0.0100 | | 54 | 700 | 00:23:21 | 75.00% | 70.32% | 0.9403 | 1.0848 | 0.0100 | | 58 | 750 | 00:25:00 | 65.62% | 71.61% | 1.0909 | 1.1003 | 0.0100 | | 60 | 780 | 00:25:59 | 65.62% | 72.26% | 0.9628 | 1.0406 | 0.0100 | |======================================================================================================================|

评估网络

遵循[1,本例仅从悉尼城市对象中形成训练和验证集。使用验证来评估经过训练的网络的性能,因为它没有被用来训练网络。

valLabelSet =变换(dsVal,@(数据)数据{2});valLabels = readall(valLabelSet);outputLabels =分类(voxnet,dsVal);精度= NNZ(outputLabels == valLabels)/ numel(outputLabels);DISP(精度)
0.7226

查看混淆矩阵来研究跨各个类别标签的准确性

confusionchart(valLabels,outputLabels)

训练集中注意标签不平衡是分类准确率的问题。混乱图表示出更高的精度和召回为行人,最常见的类,比较不常见的类似货车。由于这个例子的目的是demonstate与点云数据的基本分类网络培训的方式,即可能采取的下一步措施,以提高分类性能,例如重新采样训练集或取得更好的标签平衡或使用损失函数更稳健label imbalance (e.g. weighted cross-entropy) will not be explored.

工具书类

1)用于实时物体识别的三维卷积神经网络丹尼尔·马图拉纳,塞巴斯蒂安·舍雷尔,2015年智能机器人与系统IEEE / RSJ国际会议(IROS)

2)PointPillars:用于点云对象检测的快速编码器,亚历克斯·H.郎,Sourabh沃拉等,CVPR 2019

3)悉尼城市对象数据集,阿拉斯泰尔·德罗斯,詹姆斯·安德伍德,伯特兰Douillard,悉尼城市物体

金宝app支持功能

作用datasetPath = downloadSydneyUrbanObjects(dataLoc)如果nargin == 0 dataLoc = PWD();结束dataLoc =串(dataLoc);URL =.“http://www.acfr.usyd.edu.au/papers/data/”;姓名=“sydney-urban-objects-dataset.tar.gz”如果~ (fullfile (dataLoc,存在“悉尼城市对象数据集”),“dir”)DISP(“正在下载悉尼城市对象数据集……”);untar(url+名称,数据地址);结束datasetPath = dataLoc.append(“悉尼城市对象数据集”);结束作用ds=loadSydneyUrbanObjectsData(数据路径,折叠)% loadSydneyUrbanObjectsData数据存储与点云和悉尼城市对象数据集的相关分类标签。%ds=loadSydneyUrbanObjectsData(数据路径)构造一个%代表悉尼城市的点云和相关类别%对象数据集。输入,数据路径,是一个字符串或字符数组,其%表示对象根目录的路径%数据集。% ds = loadSydneyUrbanObjectsData(___,折叠)可选允许你想所需的褶皱%规范被列入%输出ds。例如,[1 2 4]指定您想要第一个,%第二次和第四次折叠数据集。默认值:[1 2 3 4]。如果Nargin < 2 fold = 1:4;结束datapath公司=字符串(datapath公司);路径= fullfile (datapath公司,“对象”, filesep);%目前,包括数据存储所有的折叠foldNames{1}=importdata(完整文件(数据路径,“褶皱”“fold0.txt”));foldNames {2} = importdata (fullfile (datapath公司,“褶皱”'fold1.txt')); foldNames{3}=importdata(完整文件(数据路径,“褶皱”“fold2.txt”));foldNames {4} = IMPORTDATA(完整文件(数据路径,“褶皱”'fold3.txt'));names=foldNames(fold);names=vertcat(names{:});fullFilenames=append(path,names);ds=fileDatastore(fullFilenames,“ReadFcn”@ extractTrainingData,“文件扩展名”“。斌”);%洗牌ds.Files = ds.Files(randperm(长度(ds.Files)));结束作用DATAOUT = extractTrainingData(FNAME)[pointData,强度] = readbin(FNAME);[〜,名称] = fileparts(FNAME);名称=串(姓名);NAME = extractBefore(姓名,“。”);name =取代(名称、“_”' ');标签名称=[“四轮驱动”“建筑”“公共汽车”“汽车”“行人”“支柱”“极”“红绿灯”“交通标志”“树”“卡车”“树干”“哑巴”“范”];标签=分类(名称、labelNames);dataOut = {pointCloud (pointData“强度”强度),标签};结束作用(pointData、强度)= readbin(帧)% readbin从悉尼城市目标二进制中读取点和强度数据%的文件。%名= [ 'T', '强度', 'ID',...% ' x ', ' y ', ' z ',……% '方位角', '范围', 'PID']%格式=['int64','uint8','uint8',。。。% 'FLOAT32', 'FLOAT32', 'FLOAT32',...% ` float32 `, ` float32 `, ` int32 `]FID = FOPEN(FNAME,“r”)c=一次清理(@()fclose(fid));fseek(fid,10,-1);从开始移动到第一个X点位置10个字节X =的fread(FID,INF,'单身的',30);fseek(fid,14,-1);Y=fread(fid,inf,'单身的', 30);fseek(支撑材,18岁,1);Z =从文件中读(fid,正无穷,'单身的', 30);fseek(支撑材8 1);强度=从文件中读(fid,正无穷,“uint8”,33);pointData = [X,Y,Z];结束作用dataOut = formOccupancyGrid(data) grid = pcbin(data{1},[32 32 32]);occupancyGrid = 0(大小(网格),'单身的');II = 1:numel(网格)occupancyGrid(ⅱ)=〜的isEmpty(网格{II});结束label=数据{2};dataOut={occountcyGrid,label};结束作用dataOut=augmentPointCloudData(data)ptCloud=data{1};label=data{2};%应用绕Z轴的旋转的随机。tform = randomAffine3d (“旋转”,@()交易([0 0 1],360*兰特),'规模',[0.98,1.02],“XReflection”,真的,'YReflection',真正的);绕Z轴的随机%旋转ptCloud = pctransform (ptCloud tform);%应用抖动在点云的每个点amountOfJitter = 0.01;numPoints =大小(ptCloud.Location, 1);D = 0(大小(ptCloud.Location),'喜欢', ptCloud.Location);D (: 1) = diff (ptCloud.XLimits) *兰德(numPoints, 1);D (:, 2) = diff (ptCloud.YLimits) *兰德(numPoints, 1);D (: 3) = diff (ptCloud.ZLimits) *兰德(numPoints, 1);D = amountOfJitter。* D;ptCloud = pctransform (ptCloud D);dataOut = {ptCloud、标签};结束