当前位置:网站首页>Pointnet/Pointnet++点云数据集处理并训练
Pointnet/Pointnet++点云数据集处理并训练
2022-07-04 17:54:00 【马少爷】
一、三维数据的表示方法
三维数据的表述形式一般分为四种:
① 点云:由N 个D 维的点组成,当这个D = 3 的时候一般代表着( x , y , z ) 的坐标,当然也可以包括一些法向量、强度等别的特征。这是今天主要讲述的数据类型。
② Mesh:由三角面片和正方形面片组成。
③ 体素:由三维栅格将物体用0和1表征。
④ 多角度的RGB图像或者RGB-D图像
而又由于点云更接近于设备的原始表征(即雷达扫描物体直接产生点云)同时它的表达方式更加简单,一个物体仅用一个N × D 的矩阵表示,所以点云成为了众多三维数据表示方法中最重要的一种。在测绘、建筑、电力、工业甚至如今最热门的自动驾驶等领域均有广泛的应用。
二、点云分割数据集处理
我们的点云数据可能与模型需要的数据不符,所以需要自己编写脚本进行数据的规范化。标准的点云数据处理的格式如下:
其只包含了点云的(x,y,z)坐标以及每个点对应的标签。而可能我们从CloudCompare中导出的数据有四列数据还有一列点云的强度信息:
所以编写如下的脚本对多余的第四列数据进行去除(文件的具体路径自己设置):
# -*- coding:utf-8 -*-
import os
filePath = 'D:\\点云数据处理小组\\pointnet-my\\data\\shapenetcore_partanno_segmentation_benchmark_v0_normal\\03797390'
for i,j,k in os.walk(filePath):
for name in k:
print(name)
f = open(filePath+name) # 打开txt文件
line = f.readline() # 以行的形式进行读取文件
list1 = []
while line:
a = line.split()
b = a[0:3]
c = float(a[-1])
print(c)
if(float(a[-1])==36.0):
c=2
if(float(a[-1])==37.0):
c=3
b.append(c)
list1.append(b) # 将其添加在列表之中
line = f.readline()
f.close()
print(list1)
with open(filePath+name, 'w+') as file:
for i in list1:
file.write(str(i[0]))
file.write(' '+str(i[1]))
file.write(' ' + str(i[2]))
file.write(' ' + str(i[3]))
if(i!=list[-1]):
file.write('\n')
file.close()
# path_out = 'test.txt' # 新的txt文件
# with open(path_out, 'w+') as f_out:
# for i in list1:
# fir = '9443_' + i[0] # 第一列加前缀'9443_'
# sec = 9443 + int(i[1]) # 第二列数值都加9443
# # print(fir)
# # print(str(sec))
# f_out.write(fir + ' ' + str(sec) + '\n') # 把前两列写入新的txt文件
接着我们需要对划分训练集、测试集、验证集的json文件进行处理,由于我们采用的是自己的数据集,每一个txt的文件名与之前官方数据集中的文件名一定不一样,所以需要编写脚本对控制训练集、测试集、验证集读入的三个json文件进行修改。具体代码如下(路径名同样需要修改为自己的路径名):
import os
filePath = 'D:\\点云数据处理小组\\pointnet-my\\data\\shapenetcore_partanno_segmentation_benchmark_v0_normal\\03797390'
#####最后一行会出现一个, 报错!!!!!!!!!
######手动删除或改进程序
#####
file = '1.txt'
with open(file,'a') as f:
f.write("[")
for i,j,k in os.walk(filePath):
for name in k:
base_name=os.path.splitext(name)[0] #去掉后缀 .txt
f.write(" \"")
f.write(os.path.join("shape_data/03797390/",base_name))
f.write("\"")
f.write(",")
f.write("]")
f.close()
最后在实际程序运行时发现会由于含0的数据过多而导致模型分类不准确,如下:
而根据具体项目的实际物理意义(这里的全0即表示未被激光探测到的位置,x,y,z坐标均标注为0),所以编写脚本程序对全0的部分进行去除:
# -*- coding:utf-8 -*-
import os
filePath = 'D:\\点云数据处理小组\\pointnet-my\\data\\shapenetcore_partanno_segmentation_benchmark_v0_normal\\03797390'
for i,j,k in os.walk(filePath):
for name in k:
list1 = []
for line in open(filePath+name):
a = line.split()
#print(a)
b = a[0:6]
#print(b)
a1 =float(a[0])
a2 =float(a[1])
a3 =float(a[2])
#print(a1)
if(a1==0 and a2==0 and a3==0):
continue
list1.append(b[0:6])
with open(filePath+name, 'w+') as file:
for i in list1:
file.write(str(i[0]))
file.write(' '+str(i[1]))
file.write(' ' + str(i[2]))
file.write(' ' + str(i[3]))
file.write(' ' + str(i[4]))
if(i!=list[-1]):
file.write('\n')
file.close()
三、 模型训练
我们打开项目文件夹下的model文件夹,选择以pointnet2_part_seg_msg为名的python文件,双击进入:
接下来我们需要修改的地方为PointNetFeaturePropagation的in_channel,具体方法为128+4分割的总类个数,比如这里我们的分割采用的是两个物体,每个物体均为2分类,所以通道数为128+42=136:
接着我们需要修改独热编码部分,将view方法中的第二个参数修改为需要被分割的物体的种类数:
2.2.5 训练模型部分的修改
在训练模型的时候,我们需要修改要分类的对象seg_classes为我们自己的数据集对应的类别,如例子中的分类两个类别,每个类别有两个部件。(为了方便,我们保留了原来的’Airplane’: [0, 1], ‘Mug’: [2, 3]这两个名字,同时应该注意,编号应该从0开始依次编号,若不是这样则会报错),同时应该注意自己的电脑是否支持cuda加速,如果没有GPU,则可以把代码后面所有的".cuda()"删去,程序才能正确运行。
接下来我们需要修改分割的物体总数num_classes为自己的类别个数,总共的部件数为自己的总个数:num_part。
最后,右键运行程序,如果出现进度条则表明模型已经成功改进,可以跑通自己的数据集啦!
四、打印模型预测数据
我们在用自己的数据集训练完模型后,将利用名为test_partseg的python文件进行模型的测试,为了更好的理解模型以及测试模型效果,我们有时需要打印出模型预测后的点云坐标。这里给出test_partseg文件的修改方法以及运行结果。
4.1 测试模型代码修改
首先我们需要找到该python文件,接着与上面同样的修改如下图的两个地方:
接着我们需要编写代码打印出分类后的具有不同标签的坐标,本例子中要打印两个物体的四个类别的坐标点,代码如下(部分代码):
for j in aaa:
#print(points1[i,j])
res1= open(r'E:\03797390_0_'+str(i)+'.txt', 'a')
res1.write('\n' + str(points1[i,j]).strip('[]'))
res1.close()
xxxxxx=xxxxxx+1
bbb = numpy.argwhere(cur_pred_val[i] == 1)
for j in bbb:
#print(points1[i, j])
res2 = open(r'E:\03797390_1_' + str(i) + '.txt', 'a')
res2.write('\n' + str(points1[i,j]).strip('[]'))
res2.close()
xxxxxx = xxxxxx + 1
ccc = numpy.argwhere(cur_pred_val[i] == 2)
for j in ccc:
#print(points1[i, j])
res3 = open(r'E:\02691156_2_' + str(i) + '.txt', 'a')
res3.write('\n' + str(points1[i,j]).strip('[]'))
res3.close()
xxxxxx = xxxxxx + 1
ddd = numpy.argwhere(cur_pred_val[i] == 3)
for j in ddd:
#print(points1[i, j])
res4 = open(r'E:\02691156_3_' + str(i) + '.txt', 'a')
res4.write('\n' + str(points1[i,j]).strip('[]'))
res4.close()
xxxxxx = xxxxxx + 1
修改完成后运行程序发现可以显示结果,表明修改成功!
打印出的点云坐标格式如下:
参考文献:https://blog.csdn.net/weixin_44603934/article/details/123589948
边栏推荐
猜你喜欢
Use canal and rocketmq to listen to MySQL binlog logs
自由小兵儿
redis分布式锁的8大坑总结梳理
A method of using tree LSTM reinforcement learning for connection sequence selection
Lex and yacc based lexical analyzer + parser
Nebula Importer 数据导入实践
使用canal配合rocketmq监听mysql的binlog日志
Oracle with as ora-00903: invalid table name multi report error
读写关闭的channel是啥后果?
正则替换【JS,正则表达式】
随机推荐
redis分布式锁的8大坑总结梳理
Leetcode ransom letter C # answer
php伪原创api对接方法
Caché JSON 使用JSON适配器
Have you guys ever used CDC direct Mysql to Clickhouse
From automation to digital twins, what can Tupo do?
升级智能开关,“零火版”、“单火”接线方式差异有多大?
Is Guoyuan futures a regular platform? Is it safe to open an account in Guoyuan futures?
物联网应用技术的就业前景和现状
性能优化之关键渲染路径
[mathematical basis of machine learning] (I) linear algebra (Part 1 +)
C # implementation defines a set of SQL statements that can be executed across databases in the middle of SQL (detailed explanation of the case)
Use canal and rocketmq to listen to MySQL binlog logs
神经网络物联网应用技术就业前景【欢迎补充】
英特尔集成光电研究最新进展推动共封装光学和光互连技术进步
读写关闭的channel是啥后果?
Safer, smarter and more refined, Chang'an Lumin Wanmei Hongguang Mini EV?
FPGA时序约束分享01_四大步骤简述
技术分享 | 接口测试价值与体系
Detailed explanation of issues related to SSL certificate renewal