这几天想用深度学习做一下点云的分割试验,网上搜了一下相关标题的blog有很多,但大部分只是简单的介绍文章内容,说明具体操作流程的干货并不多。在缺乏相关资料和帮助的情况下,本人大致搞清楚了pointnet进行sem_seg的流程。可能步骤存在问题甚至是错的,因为也没有人交流,但从试验结果看来还行。欢迎大家批评指正。点云的标注用cloudcompare(下面简称cc)就可以,后面obj文件的可视化由于cc对其支持不太好,改用meshlab。
欢迎阅读我的其他文章:
windows下运行pointnet(全)
pointnet C++推理部署(一)
pointnet C++推理部署(二)

训练

首先准备自己的数据集。txt格式的点云文件就行,我随便找了个斯坦福兔子点云文件,里面是xyz三维点的坐标。把兔子用cc软件分割成头(head)和身子(body),并分别保存成两个txt文件。
因为我比较懒所以只标注了这一个兔子,将其随机平移和旋转变换得到100个兔子的头和身子的txt,将其分别保存在编号为i(i=0,1,2,…,99)的文件夹下分别命名为head_i.txt和body_i.txt(i=0,1,2,…,99)。
修改sem_seg\meta\class_name.txt内容为head和body。
修改sem_seg\meta\anno_path.txt内容为训练标注的路径。
修改indoor3d_util.py中的g_class2color如下

g_class2color = {'head':  [255,0,0],'body': [0,0,255]}

修改collect_point_label函数里面的内容,给点云数据增加rgb信息:

   for f in glob.glob(os.path.join(anno_path, '*.txt')):print(f)cls = os.path.basename(f).split('_')[0]#print(cls)if cls not in g_classes: # note: in some room there is 'staris' class..cls = 'clutter'points = np.loadtxt(f)labels = np.ones((points.shape[0], 1)) * g_class2label[cls]color = np.zeros((points.shape[0], 3))color[:, 0:3] = 255points_list.append(np.concatenate([points, color, labels], 1))  # Nx7

然后可以运行collect_indoor3d_data.py生成npy文件。再通过运行gen_indoor3d_h5.py生成h5文件,注意要修改sem_seg\meta\all_data_label.txt内容为上面生成的npy文件的路径。
得到h5文件后就可以进行训练了。train.py文件有几个地方要修改:NUM_CLASSES、train_idxs、test_idxs;还需要修改model.py文件中网络最后一个卷积层的通道数为要分类的数目。另外,输入参数num_point、max_epoch、batch_size可以根据自己情况修改。我的数据量较少,几分钟就能训练完毕。

预测

运行batch_inference.py程序即可。同理,需要修改NUM_CLASSES,以及修改sem_seg\meta\data_label.txt中的待预测模型的路径。运行需要提供的参数可以参考我的上一篇文章:windows下运行pointnet(全)。
随便做了一些npy文件用于测试,制作过程和训练部分相似。用于预测的数据集包括随机平移旋转的模型,添加噪声的模型,裁剪的模型以及混合前三种的模型。红色为预测出的兔子头部,蓝色为预测出的兔子身体,黑色为未识别出的部分。因为我自始至终只是用了一个原始模型进行不同变换进行的测试,所以正确率都在99%以上。
随机平移旋转的模型预测结果:

添加噪声的模型预测结果:

裁剪的模型预测结果:
混合平移旋转、添加噪声、裁剪的模型预测结果:
整个工程文件打包:链接: https://pan.baidu.com/s/1yZG_OigNQqbeC852N6SMXw?pwd=zjn1 提取码: zjn1 复制这段内容后打开百度网盘手机App,操作更方便哦
–来自百度网盘超级会员v4的分享

本文参考的文章如下:
PointNet学习+训练自己的模型并实际使用测试成功

附预处理程序(Python实现和C++实现):
随机位姿变换

import numpy as np
import random#文件名
old_file=r"rabbit.txt"
new_file=r"rabbit_change.txt"#偏移参数
x_offset=random.uniform(-10, 10)
y_offset=random.uniform(-10, 10)
z_offset=random.uniform(-10, 10)#缩放参数
scale=1.0#旋转角度
roate_x=random.uniform(-np.pi/10, np.pi/10)
roate_y=random.uniform(-np.pi/10, np.pi/10)
roate_z=random.uniform(-np.pi/10, np.pi/10)roate_x_matrix=np.array([[1,0,0,0],[0,np.cos(roate_x),-np.sin(roate_x),0],[0,np.sin(roate_x),np.cos(roate_x),0],[0,0,0,1]])
roate_y_matrix=np.array([[np.cos(roate_y),0,np.sin(roate_y),0],[0,1,0,0],[-np.sin(roate_y),0,np.cos(roate_y),0],[0,0,0,1]])
roate_z_matrix=np.array([[np.cos(roate_z),-np.sin(roate_z),0,0],[np.sin(roate_z),np.cos(roate_z),0,0],[0,0,1,0],[0,0,0,1]])#变换矩阵
transformation_matrix=np.array([[scale,0,0,x_offset],[0,scale,0,y_offset],[0,0,scale,z_offset],[0,0,0,1]]).dot(roate_z_matrix).dot(roate_y_matrix).dot(roate_x_matrix)#加载文件
old_array=np.loadtxt(old_file)
old_xyz=old_array[:,:3]#补充数据为齐次项
ones_data=np.ones(old_xyz.shape[0])
old_xyz=np.insert(old_xyz,3,values=ones_data,axis=1)#变换数据
new_xyz = np.dot(transformation_matrix,old_xyz.T)
new_array=np.concatenate((new_xyz.T[:,:3],old_array[:,3:]),axis=1)
np.savetxt(new_file,new_array,fmt='%.06f')
Eigen::Matrix4f random_transformation()
{//按三个欧拉角随机旋转:yaw和droll的范围是(- M_PI / 10, M_PI / 10),pitching的范围是(- M_PI / 20, M_PI / 20)float yaw = rand() * 2 /10.0 * M_PI / RAND_MAX - M_PI / 10.0;float pitching = rand() * M_PI / 10.0 / RAND_MAX - M_PI / 20.0;float droll = rand() * 2 * M_PI / 10.0 / RAND_MAX - M_PI / 10.0;Eigen::Vector3f ea0(yaw, pitching, droll);Eigen::Matrix3f R;R = Eigen::AngleAxisf(ea0[0], Eigen::Vector3f::UnitZ())*Eigen::AngleAxisf(ea0[1], Eigen::Vector3f::UnitY()) *Eigen::AngleAxisf(ea0[2], Eigen::Vector3f::UnitX());//按三坐标值平移,x、y、z平移范围均为(- 10, 10)float x = rand() * 20.0 / RAND_MAX - 10.0;float y = rand() * 20.0 / RAND_MAX - 10.0;float z = rand() * 20.0 / RAND_MAX - 10.0;Eigen::Vector3f T(x, y, z);Eigen::Matrix4f H;H << R, T, 0, 0, 0, 1;return H;
}

添加高斯噪声

import numpy as np#文件名
old_file=r"rabbit.txt"
new_file=r"rabbit_change.txt"def add_noise(point, sigma=0.1, clip=0.1):point = point.reshape(-1,3)Row, Col = point.shapenoisy_point = np.clip(sigma * np.random.randn(Row, Col), -1*clip, clip)noisy_point += pointreturn noisy_point#加载文件
old_array=np.loadtxt(old_file)
old_xyz=old_array[:,:3]new_xyz=add_noise(old_xyz)
new_array=np.concatenate((new_xyz,old_array[:,3:]),axis=1)
np.savetxt(new_file,new_array,fmt='%.06f')
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <boost/random.hpp>int main(int argc, char** argv)
{boost::mt19937 rng;rng.seed(static_cast<unsigned int>(time(0)));boost::normal_distribution<> nd(0, 0.01);boost::variate_generator<boost::mt19937&, boost::normal_distribution<>> var_nor(rng, nd);std::ifstream infile;std::fstream outfile;pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloudfiltered(new pcl::PointCloud<pcl::PointXYZ>());float x, y, z;infile.open("17/head_17.txt");outfile.open("19/head_19.txt", 'w');while (infile >> x >> y >> z){x += static_cast<float> (var_nor());y += static_cast<float> (var_nor());z += static_cast<float> (var_nor());outfile << x << " " << y << " " << z << std::endl;}infile.close();outfile.close();infile.open("17/body_17.txt");outfile.open("19/body_19.txt", 'w');while (infile >> x >> y >> z){x += static_cast<float> (var_nor());y += static_cast<float> (var_nor());z += static_cast<float> (var_nor());outfile << x << " " << y << " " << z << std::endl;}infile.close();outfile.close();return EXIT_SUCCESS;
}

常见报错更新

  1. File “h5py_objects.pyx”, line 54, in h5py._objects.with_phil.wrapper
    File “h5py_objects.pyx”, line 55, in h5py._objects.with_phil.wrapper
    File “h5py\h5f.pyx”, line 106, in h5py.h5f.open
    FileNotFoundError: [Errno 2] Unable to open file (unable to open file: name = ‘E:\ruanjianchengxuwenjian\py\pointnet-rabbit\sem_seg/data\ply_data_all_0.h5’, errno = 2, error message = ‘No such file or directory’, flags = 0, o_flags = 0)
    报错原因:h5py包的版本过高
    解决方法:降低h5py包的版本,例如pip install h5py==2.10

  2. Exception has occurred: ValueError
    need at least one array to concatenate
    位于gen_indoor3d_h5.py的return np.concatenate(block_data_list, 0), np.concatenate(block_label_list, 0)
    报错原因:网格划分尺度过小,导致某个网格中点的个数为0
    解决方法:将

    data, label = indoor3d_util.room2blocks_wrapper_normalized(data_label_filename, NUM_POINT, block_size=1, stride=0.5,random_sample=False, sample_num=None)

中的block_size和stride根据自己数据尺度进行调整,参数的含义见下图(从indoor3d_util.py中摘选)。

pointnet语义分割_训练并预测自己的数据相关推荐

  1. ps语义分割_图像语义分割训练经验总结--图像语义分割

    最近一直在学pytorch,copy了几个经典的入门问题.现在作一下总结. 首先,做的小项目主要有 分类问题:Mnist手写体识别.FashionMnist识别.猫狗大战 语义分割:Unet分割肝脏图 ...

  2. 检测和语义分割_分割和对象检测-第2部分

    检测和语义分割 有关深层学习的FAU讲义 (FAU LECTURE NOTES ON DEEP LEARNING) These are the lecture notes for FAU's YouT ...

  3. u-net语义分割_使用U-Net的语义分割

    u-net语义分割 Picture By Martei Macru On Unsplash 图片由Martei Macru On Unsplash拍摄 Semantic segmentation is ...

  4. Pointnet语义分割任务S3DIS数据集上的注意点

    前言 Pointnet的网络结构和源码解释,已在之前写了次总结,本次主要针对论文中的数据集以.h5为TensorFlow的输入格式进行解释,记录如何制作H5文件,以提供给TensorFlow,PyTo ...

  5. 检测和语义分割_分割和对象检测-第1部分

    检测和语义分割 有关深层学习的FAU讲义 (FAU LECTURE NOTES ON DEEP LEARNING) These are the lecture notes for FAU's YouT ...

  6. 检测和语义分割_分割和对象检测-第5部分

    检测和语义分割 有关深层学习的FAU讲义 (FAU LECTURE NOTES ON DEEP LEARNING) These are the lecture notes for FAU's YouT ...

  7. 图像语义分割_图像语义分割(9)-DeepLabV3: 再次思考用于图像语义分割的空洞卷积...

    论文地址 :Rethinking Atrous Convolution for Semantic Image Segmentation 论文代码:Github链接 1. 摘要 文章主要的工作: 使用空 ...

  8. gcn语义分割_另辟蹊径,中科院自动化所等首次用图卷积网络解决语义分割难题...

    选自arXiv 作者:Yi Lu等机器之心编译参与:魔王.杜伟 使用 CNN 处理图像问题已经是常规操作,但此类方法会造成局部位置信息的损失.如何解决这个问题呢?来自中科院自动化所和北京中医药大学的研 ...

  9. 准确度判断 语义分割_【语义分割】DeepLab v1/v2

    [语义分割][TPAMI2017]DeepLab: Semantic Image Segmentation with Deep Convolutional Nets, Atrous Convoluti ...

最新文章

  1. inux php pdo mysql 扩展
  2. 来来来,你可能没见过这么全的实战吧
  3. Vue自定义指令实现下拉加载:v-loadmore
  4. python电商项目源码_Python Django(WEB电商项目构建)
  5. java判断socket是否连接_java判断socket是否连接
  6. 存储如何做远程服务器数据备份_如何选择存储用的服务器?
  7. oracle归档文件管理
  8. ubuntu16.04 NFS 文件共享设置
  9. 持续改进----白狼族的故事(完结)
  10. JAVA的MySQL字符串拼接_MySQL字符串拼接、截取
  11. Android 手机做麦克风扩音器demo
  12. Java多线程和操作系统多线程关系
  13. 高清录播系统与流媒体服务器,来同品牌全高清录播系统方案
  14. python计算空间向量夹角——原理及代码详解
  15. 假币问题 (n枚硬币+未知轻重+DFS)
  16. vc6.0是c语言吗,vc6.0我二级报的是C语言,听说现在C语 – 手机爱问
  17. 网站被降权的6种处理方法
  18. 当程序员追求佛系,会发生什么……
  19. 项目三 管理文件和目录
  20. 正确使用AssetBundle加载和卸载

热门文章

  1. R语言绘图—“金字塔图”
  2. 数据分析 kaggle 天池 竞赛常用函数整理
  3. 微信小程序,使用canvas画图生成海报并保存手机相册
  4. 企业上云计划:上云前应该考虑哪些因素
  5. 如何区分apk游戏引擎
  6. 五分钟掌握计时器CountDownTimer,快速实现倒计时功能
  7. 从零开始制作STM32F103RCT6小车(一)
  8. 【阅读笔记】项亮前辈的《推荐系统实战》
  9. HNUST OJ 2293 贪吃蛇吃苹果
  10. 广东惠州港口吞吐量稳中有升