位置: IT常识 - 正文

Pytorch1.7复现PointNet++点云分割(含Open3D可视化)(文末有一个自己做的书缝识别项目代码)(pytorch复制模型)

编辑:rootadmin
Pytorch1.7复现PointNet++点云分割(含Open3D可视化)(文末有一个自己做的书缝识别项目代码)

推荐整理分享Pytorch1.7复现PointNet++点云分割(含Open3D可视化)(文末有一个自己做的书缝识别项目代码)(pytorch复制模型),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:pytorch checkpoint,pytorch支持复数吗,pytorch checkpoint,pytorch论文复现,pytorch中的f,pytorch复制模型,pytorch复制模型,pytorch论文复现,内容如对您有帮助,希望把文章链接给更多的朋友!

  毕设需要,复现一下PointNet++的对象分类、零件分割和场景分割,找点灵感和思路,做个踩坑记录。

下载代码

https://github.com/yanx27/Pointnet_Pointnet2_pytorch   我的运行环境是pytorch1.7+cuda11.0。

训练

  PointNet++代码能实现3D对象分类、对象零件分割和语义场景分割。

对象分类

  下载数据集ModelNet40,并存储在文件夹data/modelnet40_normal_resampled/。

## e.g., pointnet2_ssg without normal featurespython train_classification.py --model pointnet2_cls_ssg --log_dir pointnet2_cls_ssgpython test_classification.py --log_dir pointnet2_cls_ssg## e.g., pointnet2_ssg with normal featurespython train_classification.py --model pointnet2_cls_ssg --use_normals --log_dir pointnet2_cls_ssg_normalpython test_classification.py --use_normals --log_dir pointnet2_cls_ssg_normal## e.g., pointnet2_ssg with uniform samplingpython train_classification.py --model pointnet2_cls_ssg --use_uniform_sample --log_dir pointnet2_cls_ssg_fpspython test_classification.py --use_uniform_sample --log_dir pointnet2_cls_ssg_fps主文件夹下运行代码python train_classification.py --model pointnet2_cls_ssg --log_dir pointnet2_cls_ssg时可能会报错: ImportError: cannot import name 'PointNetSetAbstraction' 原因是pointnet2_cls_ssg.py文件import时的工作目录时models文件夹,但是实际运行的工作目录时models的上级目录,因此需要在pointnet2_cls_ssg.py里把from pointnet2_utils import PointNetSetAbstraction改成from models.pointnet2_utils import PointNetSetAbstraction。

  参考README.md文件,分类不是我的主攻点,这里就略过了。

零件分割

  零件分割是将一个物体的各个零件分割出来,比如把椅子的椅子腿分出来。   下载数据集ShapeNet,并存储在文件夹data/shapenetcore_partanno_segmentation_benchmark_v0_normal/。   运行也很简单:

## e.g., pointnet2_msgpython train_partseg.py --model pointnet2_part_seg_msg --normal --log_dir pointnet2_part_seg_msgpython test_partseg.py --normal --log_dir pointnet2_part_seg_msg

  shapenet数据集txt文件格式:前三个点是xyz,点云的位置坐标,后三个点是点云的法向信息,最后一个点是这个点所属的小类别,即1表示所属50个小类别中的第一个。

  写个代码用open3d可视化shapenet数据集的txt文件(随机配色):

import open3d as o3dimport numpy as np'''BASE_DIR = os.path.dirname(os.path.abspath(__file__))ROOT_DIR = os.path.dirname(BASE_DIR)sys.path.append(BASE_DIR)sys.path.append(os.path.join(ROOT_DIR, 'data_utils'))'''txt_path = '/home/lin/CV_AI_learning/Pointnet_Pointnet2_pytorch-master/data/shapenetcore_partanno_segmentation_benchmark_v0_normal/02691156/1b3c6b2fbcf834cf62b600da24e0965.txt'# 通过numpy读取txt点云pcd = np.genfromtxt(txt_path, delimiter=" ")pcd_vector = o3d.geometry.PointCloud()# 加载点坐标# txt点云前三个数值一般对应x、y、z坐标,可以通过open3d.geometry.PointCloud().points加载# 如果有法线或颜色,那么可以分别通过open3d.geometry.PointCloud().normals或open3d.geometry.PointCloud().colors加载pcd_vector.points = o3d.utility.Vector3dVector(pcd[:, :3])pcd_vector.colors = o3d.utility.Vector3dVector(pcd[:, 3:6])o3d.visualization.draw_geometries([pcd_vector])

  GPU内存不够减小一下batch_size。   我这里训练了一下,接着代码的best_model.pth继续训练150轮,RTX3080单显卡训练一轮得六七分钟,150轮花了半天多的时间。   网上的代码基本test一下分割的一些参数就结束了,没有做可视化,参考这篇blog做了一下结果的可视化:PointNet++分割预测结果可视化。这篇blog首先用网络将输入图像的预测结果存为txt文件,然后用Matplotlib做可视化,过程有点复杂了,用open3d做可视化比较简洁一点,代码如下:

import tqdmimport matplotlibimport torchimport osimport warningsimport numpy as npimport open3d as o3dfrom torch.utils.data import Datasetimport pybullet as pfrom models.pointnet2_part_seg_msg import get_model as pointnet2import timewarnings.filterwarnings('ignore')matplotlib.use("Agg")def pc_normalize(pc): centroid = np.mean(pc, axis=0) pc = pc - centroid m = np.max(np.sqrt(np.sum(pc ** 2, axis=1))) pc = pc / m return pc,centroid,mdef generate_pointcloud(color_image, depth_image,width=1280,height=720,fov=50,near=0.01,far=5): rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth(color_image, depth_image,convert_rgb_to_intensity=False) intrinsic = o3d.camera.PinholeCameraIntrinsic(o3d.camera.PinholeCameraIntrinsicParameters.Kinect2DepthCameraDefault ) aspect = width / height projection_matrix = p.computeProjectionMatrixFOV(fov, aspect, near, far) intrinsic.set_intrinsics(width=width, height=height, fx=projection_matrix[0]*width/2, fy=projection_matrix[5]*height/2, cx=width/2, cy=height/2) point_cloud = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image, intrinsic) point_cloud.estimate_normals( search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.01, max_nn=30)) return point_cloudclass PartNormalDataset(Dataset): def __init__(self, point_cloud, npoints=2500, normal_channel=False): self.npoints = npoints # 采样点数 self.cat = {} self.normal_channel = normal_channel # 是否使用法向信息 position_data = np.asarray(point_cloud.points) normal_data = np.asarray(point_cloud.normals) self.raw_pcd = np.hstack([position_data,normal_data]).astype(np.float32) self.cat = {'board':'12345678'} # 输出的是元组,('Airplane',123.txt) self.classes = {'board': 0} data = self.raw_pcd if not self.normal_channel: # 判断是否使用法向信息 self.point_set = data[:, 0:3] else: self.point_set = data[:, 0:6] self.point_set[:, 0:3],self.centroid,self.m = pc_normalize(self.point_set[:, 0:3]) # 做一个归一化 choice = np.random.choice(self.point_set.shape[0], self.npoints, replace=True) # 对一个类别中的数据进行随机采样 返回索引,允许重复采样 # resample self.point_set = self.point_set[choice, :] # 根据索引采样 def __getitem__(self, index): cat = list(self.cat.keys())[0] cls = self.classes[cat] # 将类名转换为索引 cls = np.array([cls]).astype(np.int32) return self.point_set, cls, self.centroid, self.m # pointset是点云数据,cls十六个大类别,seg是一个数据中,不同点对应的小类别 def __len__(self): return 1class Generate_txt_and_3d_img: def __init__(self,num_classes,testDataLoader,model,visualize = False): self.testDataLoader = testDataLoader self.num_classes = num_classes self.heat_map = False # 控制是否输出heatmap self.visualize = visualize # 是否open3d可视化 self.model = model self.generate_predict() self.o3d_draw_3d_img() def __getitem__(self, index): return self.predict_pcd_colored def generate_predict(self): for _, (points, label,centroid,m) in tqdm.tqdm(enumerate(self.testDataLoader), total=len(self.testDataLoader),smoothing=0.9): #点云数据、整个图像的标签、每个点的标签、 没有归一化的点云数据(带标签)torch.Size([1, 7, 2048]) points = points.transpose(2, 1) #print('1',target.shape) # 1 torch.Size([1, 2048]) xyz_feature_point = points[:, :6, :] model = self.model seg_pred, _ = model(points, self.to_categorical(label, 1)) seg_pred = seg_pred.cpu().data.numpy() if self.heat_map: out = np.asarray(np.sum(seg_pred,axis=2)) seg_pred = ((out - np.min(out) / (np.max(out) - np.min(out)))) else: seg_pred = np.argmax(seg_pred, axis=-1) # 获得网络的预测结果 b n c seg_pred = np.concatenate([np.asarray(xyz_feature_point), seg_pred[:, None, :]], axis=1).transpose((0, 2, 1)).squeeze(0) self.predict_pcd = seg_pred self.centroid = centroid self.m = m def o3d_draw_3d_img(self): pcd = self.predict_pcd pcd_vector = o3d.geometry.PointCloud() # 加载点坐标 pcd_vector.points = o3d.utility.Vector3dVector(self.m * pcd[:, :3] + self.centroid) # colors = np.random.randint(255, size=(2,3))/255 colors = np.array([[0.8, 0.8, 0.8],[1,0,0]]) pcd_vector.colors = o3d.utility.Vector3dVector(colors[list(map(int,pcd[:, 6])),:]) if self.visualize: coord_mesh = o3d.geometry.TriangleMesh.create_coordinate_frame(size = 0.1, origin = [0,0,0]) o3d.visualization.draw_geometries([pcd_vector,coord_mesh]) self.predict_pcd_colored = pcd_vector def to_categorical(self,y, num_classes): """ 1-hot encodes a tensor """ new_y = torch.eye(num_classes)[y.cpu().data.numpy(),] if (y.is_cuda): return new_y.cuda() return new_ydef load_models(model_dict={'PonintNet': [pointnet2(num_classes=2,normal_channel=True).eval(),r'./log/part_seg/pointnet2_part_seg_msg/checkpoints']}): model = list(model_dict.values())[0][0] checkpoints_dir = list(model_dict.values())[0][1] weight_dict = torch.load(os.path.join(checkpoints_dir,'best_model.pth')) model.load_state_dict(weight_dict['model_state_dict']) return modelclass Open3dVisualizer():def __init__(self):self.point_cloud = o3d.geometry.PointCloud()self.o3d_started = Falseself.vis = o3d.visualization.VisualizerWithKeyCallback()self.vis.create_window()def __call__(self, points, colors):self.update(points, colors)return Falsedef update(self, points, colors):coord_mesh = o3d.geometry.TriangleMesh.create_coordinate_frame(size = 0.15, origin = [0,0,0])self.point_cloud.points = pointsself.point_cloud.colors = colors# self.point_cloud.transform([[1,0,0,0],[0,-1,0,0],[0,0,-1,0],[0,0,0,1]])# self.vis.clear_geometries()# Add geometries if it is the first timeif not self.o3d_started:self.vis.add_geometry(self.point_cloud)self.vis.add_geometry(coord_mesh)self.o3d_started = Trueelse:self.vis.update_geometry(self.point_cloud)self.vis.update_geometry(coord_mesh)self.vis.poll_events()self.vis.update_renderer()if __name__ =='__main__': num_classes = 2 # 填写数据集的类别数 如果是s3dis这里就填13 shapenet这里就填50 color_image = o3d.io.read_image('image/rgb1.jpg') depth_image = o3d.io.read_image('image/depth1.png') point_cloud = generate_pointcloud(color_image=color_image, depth_image=depth_image) TEST_DATASET = PartNormalDataset(point_cloud,npoints=30000, normal_channel=True) testDataLoader = torch.utils.data.DataLoader(TEST_DATASET, batch_size=1, shuffle=False, num_workers=0,drop_last=True) predict_pcd = Generate_txt_and_3d_img(num_classes,testDataLoader,load_models(),visualize = True)Pytorch1.7复现PointNet++点云分割(含Open3D可视化)(文末有一个自己做的书缝识别项目代码)(pytorch复制模型)

  把之前的代码改成了针对单个点云预测的可视化,点云由GRB图像和深度图像生成,如果想直接输入点云自己稍微改下代码就可以了,目前仅针对shapenet数据集格式的数据。这里要注意如果训练的时候选择了--normal,那么normal_channel要改成True。   看下训练效果,用modelnet40里的一个chair文件进行预测。

   

  可以看到这个椅子大致是分成了四块,但是椅子靠背、腿分割地挺好的,就是扶手有一部分分割到了坐垫那里了,毕竟训练时间不长。modelnet40数据集只是用来分类,并没有分割的标注,所以这里可视化了一下shapenet里标注好的椅子点云,看看椅子各个部位的分割(并非上面的椅子)。

  这里就比较显而易见地看出椅子分为靠背、扶手、坐垫、腿四个部分。   初步观察到效果以后可以开始尝试自己制作数据集进行训练了,可以参考我写的这篇文章:《CloudCompare制作ShapeNet格式点云数据集》。

场景分割

  零件分割网络可以很容易地扩展到语义场景分割,点标记成为语义对象类而不是目标零件标记。   在 Stanford 3D语义分析数据集上进行实验。该数据集包含来自Matterport扫描仪的6个区域的3D扫描,包括271个房间。扫描中的每个点都用13个类别(椅子、桌子、地板、墙壁等加上杂物)中的一个语义标签进行注释。   先把文件下载过来: S3DIS ,存到文件夹data/s3dis/Stanford3dDataset_v1.2_Aligned_Version/.   处理数据,数据会存到data/stanford_indoor3d/。

cd data_utilspython collect_indoor3d_data.py

  运行:

## Check model in ./models## e.g., pointnet2_ssgpython train_semseg.py --model pointnet2_sem_seg --test_area 5 --log_dir pointnet2_sem_segpython test_semseg.py --log_dir pointnet2_sem_seg --test_area 5 --visual

  上面的操作走完以后会在log/sem_seg/pointnet2_sem_seg/visual/生成预测结果的obj文件,可以用open3d进行可视化,就是不能用o3d.io.read_triangle_mesh函数来可视化obj文件,因为这里生成的obj文件还带了颜色信息用来表示语义信息,所以得读取成列表数据然后定义成o3d.geometry.PointCloud()变量显示,代码如下:

import copyimport numpy as npimport open3d as o3dimport osobjFilePath = 'log/sem_seg/pointnet2_sem_seg/visual/Area_5_office_8_gt.obj'with open(objFilePath) as file: points = [] while 1: line = file.readline() if not line: break strs = line.split(" ") if strs[0] == "v": points.append(np.array(strs[1:7],dtype=float)) if strs[0] == "vt": break# points原本为列表,需要转变为矩阵,方便处理 pcd = np.array(points)pcd_vector = o3d.geometry.PointCloud()pcd_vector.points = o3d.utility.Vector3dVector(pcd[:, :3])pcd_vector.colors = o3d.utility.Vector3dVector(pcd[:,3:6])o3d.visualization.draw_geometries([pcd_vector])

  康康Area_5里office_8的效果:   原图:

   

  ground truth:   predict:

  OK,大致算是把这个PointNet++复现完了,着重做了下点云分割,给毕设做准备。总的来讲,训练和预测的过程并不难,为了康康效果,可视化的部分倒是花了挺长时间。零件分割和场景分割本质上讲其实是一回事,就是在代码里面这两个分割用了不同的模型来训练。之后打算自己制作数据集来训练一下,先拿零件分割的模型来做,毕竟场景分割做成S3DIS形式的数据集有点麻烦。总之跟着这篇blog走肯定是能跑通PointNet++的。

  添加一个自己做的用pointnet++做的书缝识别项目,GitHub里面有数据集和代码:https://github.com/struggler176393/Pointnet_book_seam。

本文链接地址:https://www.jiuchutong.com/zhishi/288813.html 转载请保留说明!

上一篇:yoloV5模型中,x,s,n,m,l分别有什么不同(yolov5模型中git的作用)

下一篇:超强功能WebSSH安装,解决Web远程SSH终端(webssh github)

  • 百度竞价推广的点击率受什么的影响(百度竞价推广的匹配模式及含义)

    百度竞价推广的点击率受什么的影响(百度竞价推广的匹配模式及含义)

  • 苹果交通卡移除后余额在哪里(苹果交通卡移除了余额没有了)

    苹果交通卡移除后余额在哪里(苹果交通卡移除了余额没有了)

  • 华为p40有没有4G版本呢(华为P40有没有无线充电)

    华为p40有没有4G版本呢(华为P40有没有无线充电)

  • miui11耗电快解决办法(miui11耗电量)

    miui11耗电快解决办法(miui11耗电量)

  • backspace和delete的区别(backspace和delete的删除文件的区别)

    backspace和delete的区别(backspace和delete的删除文件的区别)

  • 华为怎么看应用使用时长(华为怎么看应用使用时间)

    华为怎么看应用使用时长(华为怎么看应用使用时间)

  • 抖音里的商品橱窗在哪里找(抖音说的商品橱窗在哪)

    抖音里的商品橱窗在哪里找(抖音说的商品橱窗在哪)

  • 苹果8有红外线功能吗能开空调吗(苹果手机自带红外线吗)

    苹果8有红外线功能吗能开空调吗(苹果手机自带红外线吗)

  • 为什么我的u盘在我的电脑显示不出来(为什么我的u盘16g现在只有369m)

    为什么我的u盘在我的电脑显示不出来(为什么我的u盘16g现在只有369m)

  • cpu100度会坏吗(cpu温度100多度会不会烧坏了)

    cpu100度会坏吗(cpu温度100多度会不会烧坏了)

  • 荣耀路由器Hi灯一直闪烁怎么解决(荣耀路由器hi灯闪烁)

    荣耀路由器Hi灯一直闪烁怎么解决(荣耀路由器hi灯闪烁)

  • 怎么把lte改为4g(怎样把lte变成了4g)

    怎么把lte改为4g(怎样把lte变成了4g)

  • 苹果7亮度自动调节怎么关闭(苹果7亮度自动降低)

    苹果7亮度自动调节怎么关闭(苹果7亮度自动降低)

  • 板u套装是什么意思(什么叫板u套装)

    板u套装是什么意思(什么叫板u套装)

  • 电脑图标字体大小怎么设置(电脑图标字体大小怎么调整快捷键)

    电脑图标字体大小怎么设置(电脑图标字体大小怎么调整快捷键)

  • 荣耀20pro与nova5pro的区别(荣耀20pro与nova5pro游戏哪个好)

    荣耀20pro与nova5pro的区别(荣耀20pro与nova5pro游戏哪个好)

  • oppoa11x可以闪充吗(oppoa11x支持闪充吗?可以用闪充的插头吗?)

    oppoa11x可以闪充吗(oppoa11x支持闪充吗?可以用闪充的插头吗?)

  • 手机号前面86什么意思(手机号前面的86啥意思)

    手机号前面86什么意思(手机号前面的86啥意思)

  • 手写福字可以扫到敬业福吗(能扫出福字)

    手写福字可以扫到敬业福吗(能扫出福字)

  • iphone11屏幕校准怎么弄(苹果11手机屏幕校准)

    iphone11屏幕校准怎么弄(苹果11手机屏幕校准)

  • 苹果max第二张卡在哪插(苹果第二个卡怎么插)

    苹果max第二张卡在哪插(苹果第二个卡怎么插)

  • 手机qq怎么隐藏联系人(手机qq怎么隐藏图标)

    手机qq怎么隐藏联系人(手机qq怎么隐藏图标)

  • 华为nova10pro支持5G吗(华为nova10pro支持多少倍变焦)

    华为nova10pro支持5G吗(华为nova10pro支持多少倍变焦)

  • 把ChatGPT接入我的个人网站

    把ChatGPT接入我的个人网站

  • 谷歌浏览器无法使用翻译功能的解决方案,谷歌浏览器无法翻译怎么办?谷歌浏览器右键翻译失效了?(谷歌浏览器无法安装)

    谷歌浏览器无法使用翻译功能的解决方案,谷歌浏览器无法翻译怎么办?谷歌浏览器右键翻译失效了?(谷歌浏览器无法安装)

  • 哪些准备金支出可实现税前扣除?
  • 备案办税人员信息填本人的有风险吗
  • 足浴店装修费用多少
  • 环评费用怎么入账
  • 增值税加计扣除账务处理
  • 个体户三万以内免个税
  • 进项和销项必须在一个月吗
  • 临时聘用人员费用谁承担
  • 债务重组双方如何进行会计处理
  • 固定资产弃置费用计入什么科目
  • 房产税房产原值包括地价吗
  • 餐饮行业打折部门是什么
  • 建筑施工企业质量体系环境包括
  • 预付货款核销如何做会计摘要呢?
  • 免费送试用装的话术
  • 所得税清算时坏账怎么算
  • 房屋租赁税费征收的时间是多久
  • 什么情况下企业不能辞退员工
  • 售后回购的实质
  • 法人实名认证需要带什么
  • 商品进销差价如何结平
  • 预付租金是什么
  • 办公费差旅费属于
  • 押金收不回来了怎么处理
  • 应发工资包含罚款吗
  • 最新的小微企业平均寿命
  • 苹果14发布会时间
  • 如何把itunes的音乐导入ipod
  • 在建工程完工后结转会计分录
  • 个人所得税计提和发放分录
  • 房地产公司股权收购
  • 减免税款怎么做账务处理
  • 收到银行本票的账务处理
  • php常见设计模式和用途
  • 原材料的盘盈与盘亏的会计处理
  • 小企业会计准则2023电子版
  • 扣缴个人所得税报告表在哪里打印
  • 代订机票发票可以入账吗
  • 公司发放工作服账务处理
  • 新旧所得税法转换规定
  • 发票申请条件
  • 一般纳税人申请转为小规模纳税人
  • 预收货款尚未发货
  • mongodb中主键的默认格式是哪个?
  • 公司转账到个人账户可以撤销么
  • 小规模所得税怎么计算公式
  • 跨年度错账调整分录
  • 建筑业差额纳税申报
  • 新准则制度体系的核心变化
  • SQL server 2008中的数据库能否只包含数据文件
  • 招待费专票不可以抵扣
  • 多交增值税退税抵欠怎么处理
  • 出口退税后发生退货补缴怎么算增值税
  • 单位的车辆
  • 发行价格另支付发行费用
  • 税收优惠退回的税金怎么入账
  • 客观原因怎么写
  • 选择简易计税方法
  • 房地产企业预付账款会计分录
  • 可供出售金融资产和交易性金融资产
  • 建账是啥意思
  • sql语句错误提示
  • win7怎么设置桌面位置
  • WINDOWS SERVER 2008开启桌面主题具体步骤
  • linux带桌面
  • Mac如何使用Excel
  • win10资源管理器在哪里打开
  • Ext中下拉列表ComboBox组件store数据格式用法介绍
  • 基于socket的聊天程序
  • 如何制作批处理
  • 安卓开发过程中的问题
  • jquery序列化json
  • 工作笔记都写什么内容
  • python同一层次的语言必须对齐吗
  • Linux开发基于Qt的Android应用指定调试设备
  • 广州市地方税务局官网
  • 普通发票开具系统
  • 建筑企业外地施工预缴税款
  • 诺诺发票怎样上报汇总
  • 江苏电子税务电子发票怎么作废
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设