实验点云数据点云累计-cloudcomare标签制作流程
学习汇报
1 点云数据处理
1.1 预处理
- 原始pcap数据
- 读取pcap文件,保存为pointCloud格式
clc
clear
close
filename= 'D:\leidashuji\LIDAR_0515\01.pcap'; %文件位置
veloReader = velodyneFileReader(filename,"VLP16"); % 读取.pcap文件
ptCloud_original=cell(1,veloReader.NumberOfFrames); % 定义储存原始点云数据的元组
num=60;%过多的点云帧的累积误差有点大,这里设置为60帧
for i=1:num%veloReader.NumberOfFrames
ptCloud_original{1,i}=readFrame(veloReader,i); % 依次读取每次采样周期的数据,将其保存为pointCloud格式
- 点云累积
![](https://tsyblog-figure.oss-cn-hangzhou.aliyuncs.com/img/202205161626096.png)
roi = [-20 20 -20 40 -4 1]; % roi区域筛选
k=1;
indices_1{1,i} = findPointsInROI(ptCloud_original{1,i},roi);
ptCloud_interest{1,i}=select(ptCloud_original{1,i},indices_1{1,i});
end
ptCloudRef = ptCloud_interest{1}; % 将第1帧点云定义为参考点云
ptCloudCurrent = ptCloud_interest{2}; % 将第2帧定义为待处理点云
%% 下采样
gridSize = 0.5; %定义下采样网格大小
percentage=0.5;
fixed = pcdownsample(ptCloudRef, 'random', percentage);
moving = pcdownsample(ptCloudCurrent, 'random', percentage); % 下采样
tform = pcregistericp(moving, fixed, 'Metric','pointToPlane','Extrapolate', true); % matlab自带ICP算法,得到moving点云至fixed点云之间的坐标转换矩阵tform
ptCloudAligned = pctransform(ptCloudCurrent,tform); % 将第2帧点云通过求得的坐标转换矩阵进行转换
mergeSize = 0.025;
ptCloudScene = pcmerge(ptCloudRef, ptCloudAligned, mergeSize);
accumTform = tform;
mergeSize = 0.025;
ptCloudScene = pcmerge(ptCloudRef, ptCloudAligned, mergeSize);
figure
hAxes = pcshow(ptCloudScene);
title('Updated world scene')
%% 设置轴属性以更快地渲染
hAxes.CameraViewAngleMode = 'auto';
hScatter = hAxes.Children;
for i = 3:num%length(ptCloud_original) % 依次检索没帧点云
ptCloudCurrent = ptCloud_interest{i};% 将第i帧数据赋值给待处理点云 ptCloudCurrent
fixed = moving; % 将前一帧的移动点云作为后一帧点云的参考点云
moving = pcdownsample(ptCloudCurrent, 'gridAverage', gridSize);% 将待处理点云作为移动点云
% 应用CIP算法得到moving到fixed的坐标转换矩阵
tform = pcregistericp(moving, fixed, 'Metric','pointToPlane','Extrapolate', true);
% 通过当前转换矩阵乘以前面累积的转换矩阵,得到当前帧转换至第一帧的坐标转换矩阵
accumTform = affine3d(tform.T * accumTform.T);
ptCloudAligned = pctransform(ptCloudCurrent, accumTform);
% 更新全局累积的点云数据
ptCloudScene = pcmerge(ptCloudScene, ptCloudAligned, mergeSize);
hScatter.XData = ptCloudScene.Location(:,1);
hScatter.YData = ptCloudScene.Location(:,2);
hScatter.ZData = ptCloudScene.Location(:,3);
end
figure
pcshow(ptCloudScene)
- 坐标转换
![](https://tsyblog-figure.oss-cn-hangzhou.aliyuncs.com/img/202205161627987.png)
%% 坐标转换
thetax = 23.46*pi/180;%
thetay =0*pi/180;
thetaz = 0;
rotx = [1 0 0; ...
0 cos(thetax) -sin(thetax); ...
0 sin(thetax) cos(thetax)];
rotz=[cos(thetaz) sin(thetaz) 0; ...
-sin(thetaz) cos(thetaz) 0; ...
0 0 1];
roty=[cos(thetay) 0 sin(thetay);
0 1 0;
-sin(thetay) 0 cos(thetay)];
trans = [0, 0, 0];
tform = rigid3d(roty*rotx*rotz,trans);
ptcloud_zuobiao=pctransform(ptCloudScene,tform);
figure
pcshow(ptcloud_zuobiao)
- 路面范围提取,保存为.csv文件
![](https://tsyblog-figure.oss-cn-hangzhou.aliyuncs.com/img/202205161628923.png)
%% 路面范围提取
roi = [-1 1 2 4 -2 -0.5]; % roi区域筛选
indices_2 = findPointsInROI(ptcloud_zuobiao,roi);
ptCloud_road=select(ptcloud_zuobiao,indices_2);
figure
pcshow(ptCloud_road)
csvwrite('lidar_01.csv',ptCloud_road.Location )%将预处理提取的路面点云保存为CSV格式
%注:lidar_01.csv的名称需根据前面导入pcap文件进行更改,如lidar_02,lidar_03...
1.2 通过CloudCompare打标签流程
CloudCompare下载地址:https://www.cloudcompare.org/
- 导入csv点云文件
- 直接apply
- 点击lidar_01-cloud
- 点击Edit>Mesh>Delaunay2.5D(best fitting plane)
- 默认0
- 平滑:点击Edit>Mesh>smooth
- 迭代次数:20,平滑因子:0.2
- 添加Z坐标参考,以高程图渲染点云
- 将.mmesh网格转换为点云格式,采样点数量设置为100000
- 点击生成的.sampled数据
- 点击分割按钮
- 鼠标左键连续点击框选凹坑或凸起区域,注:鼠标左键点击间距应尽可能小,完成框选后鼠标右键确定。再按图中第2步,第3步操作。如果点云中有多个凹坑和凸起,重复第10步
- 对分割后的点云添加标签:将lidar_01-cloud删除,方便后续保存
- 依次选择分割后点云,如选择第2个为凸起点云,第1个可看作是正常路面点云
- 添加分类标签,注:统一将正常路面设为1,凸起设为2,凹坑设为3
- 标签全部设置完后,合并点云,首先全选点云(记得在第11步删除lidar_01-cloud),点击合并按钮
- 合并后选择Classification可查看分割状态
- 导出为.csv格式,点击保存按钮,保存为csv格式
- 导出设置,精度选择8和6,分隔符选择comma,header全选
- 导出数据如图所示
2 基于pointnet的点云语义分割
2.1 pointnet介绍
-
PointNet 架构。 分类网络将 n 个点作为输入,应用输入和特征变换,然后通过最大池来聚合点要素。 输出是 k 类的分类分数。 分段网络是分类网络的扩展。 它将每个点的全局和局部特征和输出连接在一起。 “mlp” 代表多层感知器,括号中的数字是层大小。 Batchnorm 用于 ReLU 的所有层。Dropout 图层用于分类网中的最后一个 mlp。
-
由于点云旋转的不变性,Pointnet的解决方法是学习一个变换矩阵T ,即T − N e t 结构。由于loss的约束,使得T 矩阵训练会学习到最有利于最终分类的变换,如把点云旋转到正面。论文的架构中,分别在输入数据后和第一层特征中使用了T 矩阵,大小为3x3和64x64。其中第二个T矩阵由于参数过多,考虑添加正则项,使其接近于正交矩阵,减少点云的信息丢失
-
其中最典型的MLP包括包括三层:输入层、隐层和输出层,MLP神经网络不同层之间是全连接的(全连接的意思就是:上一层的任何一个神经元与下一层的所有神经元都有连接)。
2.2 python复现
- modelnet40_normal_resampled数据集下载
- 该数据集针对室内场景的分割,实现的是对室内各个物体的分类
-
shapenet数据集下载,ShapeNetCore 是完整 ShapeNet 数据集的子集,具有单个干净的 3D 模型和手动验证的类别和对齐注释。它涵盖了 55 个常见的对象类别和大约 51,300 个独特的 3D 模型。流行的计算机视觉 3D 基准数据集PASCAL 3D+的 12 个对象类别都被 ShapeNetCore 覆盖
-
数据集结构:
-
数字文件夹里面放的都是每个大类的点云数据。例如,第一个就是飞机大类。
- 对于train_test_split文件夹是一个划分数据的jason 文件。它将数据集划分为训练集 测试集 和验证集。每个元素都是一个点云数据,按斜杠划分第二个是该点云数据所属的类别,第三个是该点云数据的名称。例如,在test jason文件中的名称 ,就是用来测试的点云数据的名称。
- 目前代码在给定数据集上已经能跑通,在自己数据集上还有个.json的数组文件没太弄懂
2.2 matlab实现
- csv数据处理
filename_train=dir('D:\leidashuji\lidar_label\code\train_data\*.csv');
filename_test=dir('D:\leidashuji\lidar_label\code\test_data\*.csv');
for i=1:length(filename_train)
csvname_trian=[filename_train(i,1).folder '\' filename_train(i,1).name];
csvdata_trian{i} = readmatrix(csvname_trian);
data_orgin_trian{i} =csvdata_trian{i}(:,1:4);
numPoint_trian(i)=length(data_orgin_trian{i});
pointcloud_trian{i}=pointCloud(data_orgin_trian{i}(:,1:3));
end
for i=1:length(filename_test)
csvname_test=[filename_test(i,1).folder '\' filename_test(i,1).name];
csvdata_test{i} = readmatrix(csvname_test);
data_orgin_test{i} =csvdata_test{i}(:,1:4);
numPoint_test(i)=length(data_orgin_test{i});
pointcloud_test{i}=pointCloud(data_orgin_test{i}(:,1:3));
end
%% 预览数据
classNames = [ "ground" ;"humps" ;"pothloes"];
for i=1:9
subplot(3,3,i)
labels=data_orgin_trian{i}(:,4);
ax = pcshow(pointcloud_trian{i}.Location,labels);
helperLabelColorbar(ax,classNames);
end
- 数据预览