(四) 三维点云课程---PointNet-Pytorch运行

三维点云课程—PointNet-Pytorch运行


PointNet 源码下载地址:https://github.com/fxia22/pointnet.pytorch

源代码存在一些问题,喜欢折腾的小伙伴可以继续往下看,不喜欢的话,我也会在文章的最后给出我调试好的PointNet_Pytorch的包,直接运行即可。

Windows10的环境

python==3.7.4

torch==1.6.0

cuda=10.1

cudnn=8.0

PointNet包安装

cd pointnet.pytorch-master
pip install -e .

再通过pip list查看终端有没有PointNet包

数据集为shapenet类型


1.分类—Classification

1.1训练

在 pointnet.pytorch-master/utils文件夹下,通过快捷键打开终端:按住Ctrl+L,输入cmd回车,就会快速打开cmd窗口,且定位到该文件夹下。在终端输入

python train_classification.py --dataset=E:\PointNet\pointnet.pytorch-master\pointnet.pytorch-master\shapenetcore_partanno_segmentation_benchmark_v0\ --nepoch=4 --dataset_type=shapenet

不出问题的话,终端开始进行训练,在10个train进行test。出现以下的情况表示训练结束了
在这里插入图片描述

此时在该文件夹下会产生分类模型文件夹cls


1.2 分类训练可能出现的问题

报错1: Detected call oflr_scheduler.step()beforeoptimizer.step()`

参考:https://blog.csdn.net/zfjBIT/article/details/105114526

解决方案: 将train_classification.py下的代码 scheduler.step()(在for epoch in range(opt.nepoch)下方)放在每次epoch训练完成之后。更改代码如下

  for epoch in range(opt.nepoch):
        #scheduler.step()
        for i, data in enumerate(dataloader, 0):
            points, target = data
            target = target[:, 0]
            points = points.transpose(2, 1)
            points, target = points.cuda(), target.cuda()
            optimizer.zero_grad()
            classifier = classifier.train()
            pred, trans, trans_feat = classifier(points)
            loss = F.nll_loss(pred, target)
            if opt.feature_transform:
                loss += feature_transform_regularizer(trans_feat) * 0.001
            loss.backward()
            optimizer.step()
            pred_choice = pred.data.max(1)[1]
            correct = pred_choice.eq(target.data).cpu().sum()
            print('[%d: %d/%d] train loss: %f accuracy: %f' % (epoch, i, num_batch, loss.item(), correct.item() / float(opt.batchSize)))

            if i % 10 == 0:
                j, data = next(enumerate(testdataloader, 0))
                points, target = data
                target = target[:, 0]
                points = points.transpose(2, 1)
                points, target = points.cuda(), target.cuda()
                classifier = classifier.eval()
                pred, _, _ = classifier(points)
                loss = F.nll_loss(pred, target)
                pred_choice = pred.data.max(1)[1]
                correct = pred_choice.eq(target.data).cpu().sum()
                print('[%d: %d/%d] %s loss: %f accuracy: %f' % (epoch, i, num_batch, blue('test'), loss.item(), correct.item()/float(opt.batchSize)))
        
        scheduler.step()
        torch.save(classifier.state_dict(), '%s/cls_model_%d.pth' % (opt.outf, epoch))

报错2:The "freeze_support()" line can be omitted if the program is not going to be frozen to produce an executable.

参考:https://blog.csdn.net/zfjBIT/article/details/105117206

解决方案:将你要运行的代码放到main函数中运行即可,train_classification.py代码更改如下

if __name__=='__main__':

    optimizer = optim.Adam(classifier.parameters(), lr=0.001, betas=(0.9, 0.999))
    scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=20, gamma=0.5)
    classifier.cuda()

    num_batch = len(dataset) / opt.batchSize

    for epoch in range(opt.nepoch):
        #scheduler.step()
        for i, data in enumerate(dataloader, 0):
            points, target = data
            target = target[:, 0]
            points = points.transpose(2, 1)
            points, target = points.cuda(), target.cuda()
            optimizer.zero_grad()
            classifier = classifier.train()
            pred, trans, trans_feat = classifier(points)
            loss = F.nll_loss(pred, target)
            if opt.feature_transform:
                loss += feature_transform_regularizer(trans_feat) * 0.001
            loss.backward()
            optimizer.step()
            pred_choice = pred.data.max(1)[1]
            correct = pred_choice.eq(target.data).cpu().sum()
            print('[%d: %d/%d] train loss: %f accuracy: %f' % (epoch, i, num_batch, loss.item(), correct.item() / float(opt.batchSize)))

            if i % 10 == 0:
                j, data = next(enumerate(testdataloader, 0))
                points, target = data
                target = target[:, 0]
                points = points.transpose(2, 1)
                points, target = points.cuda(), target.cuda()
                classifier = classifier.eval()
                pred, _, _ = classifier(points)
                loss = F.nll_loss(pred, target)
                pred_choice = pred.data.max(1)[1]
                correct = pred_choice.eq(target.data).cpu().sum()
                print('[%d: %d/%d] %s loss: %f accuracy: %f' % (epoch, i, num_batch, blue('test'), loss.item(), correct.item()/float(opt.batchSize)))
        
        scheduler.step()
        torch.save(classifier.state_dict(), '%s/cls_model_%d.pth' % (opt.outf, epoch))

    total_correct = 0
    total_testset = 0
    for i,data in tqdm(enumerate(testdataloader, 0)):
        points, target = data
        target = target[:, 0]
        points = points.transpose(2, 1)
        points, target = points.cuda(), target.cuda()
        classifier = classifier.eval()
        pred, _, _ = classifier(points)
        pred_choice = pred.data.max(1)[1]
        correct = pred_choice.eq(target.data).cpu().sum()
        total_correct += correct.item()
        total_testset += points.size()[0]

    print("final accuracy {}".format(total_correct / float(total_testset)))

报错3:PermissionError: [WinError 5] 拒绝访问

解决方案:将训练的workers改为0(默认为4),师妹说这是关于线程的,windows10下改为0没有影响,起作用是在linux下的(我深度学习纯小白),代码更改如下

parser.add_argument(
    '--workers', type=int, help='number of data loading workers', default=0) #4

报错4:如果在运行过程中,提示内存不够的问题

**解决方案:**将batchsize调小一点即可(默认是32,改为8即可),代码更改如下

parser.add_argument(
    '--batchSize', type=int, default=8 ,help='input batch size')  #32

报错5:输入指令后,程序没报错也没有任何响应,正常情况下确实有点慢,但是半天没反应,说明代码出现了问题,这是个隐藏的Bug,我当时也折腾了好几天才解决这个问题。

解决方案: 需要在pytorch引入入drop_last=True参数。代码更改如下。关于drop_last的作用,参考:https://www.jb51.net/article/178398.htm

dataloader = torch.utils.data.DataLoader(
    dataset,
    batch_size=opt.batchSize,
    shuffle=True,
    num_workers=int(opt.workers)
    ,drop_last=True)   ##很重要

以上就是我在分类时遇到的问题,可能你和我遇到的不一样,到时候多百度百度。


1.3测试分类后的模型文件

在pointnet.pytorch-master/utils文件夹下输入

python show_cls.py --model cls/cls_model_0.pth

正常情况下,终端开始打印
在这里插入图片描述

1.4测试分类时源码可能遇到的问题

1.出现FileNotFoundError: [Errno 2] No such file or directory: 'shapenetcore_partanno_segmentation_benchmark_v0/synsetoffset2category.txt'

解决方案

实际上是有这个文件的。查看show_cls.py,发现此处root位置为:
root='shapenetcore_partanno_segmentation_benchmark_v0',
需要将路径改为绝对路径:

root='E:\PointNet\pointnet.pytorch-master\pointnet.pytorch-master\shapenetcore_partanno_segmentation_benchmark_v0',

参考:https://www.it610.com/article/1279162735334014976.htm这个博主解决了我大部分问题,嘻嘻。


2.但此时的accuracy都是0。需要修改show_cls.py中的代码:

#correct = pred_choice.eq(target.data).cpu().sum()
 correct = target.eq(pred_choice.data).cpu().sum().data.numpy()

此处参考:https://github.com/fxia22/pointnet.pytorch/issues/29


2.分割—Segmentation

2.1训练

在pointnet.pytorch-master/utils文件夹下输入

python train_segmentation.py --dataset=E:\PointNet\pointnet.pytorch-master\pointnet.pytorch-master\shapenetcore_partanno_segmentation_benchmark_v0 --nepoch=5 --class_choice=Chair

正常情况下,终端开始进行训练了,出现下图,表示训练结束了,且在utils文件夹下参数seg模型文件夹
在这里插入图片描述

2.2分割训练可能出现的问题

代码的修改"参考1.2的分类训练可能出现的问题",这里就不赘述了。


2.3测试分类后的模型文件

在pointnet.pytorch-master/utils文件夹下输入

python show_seg.py --model seg/seg_model_Chair_3.pth --class_choice Airplane

正常情况下,会显示如下
在这里插入图片描述

在该指令下,Airplane可以替换成训练好的其他类别。在该图片下也有一些人机交互的快捷键。

q:退出程序,程序是死循环的,强制是关不掉的

t+q:变换颜色

n:放大

m:缩小

r:恢复原状

s:保存图片

具体的快捷键的设置查看show3d_balls.py


2.4测试分类时源码可能遇到的问题

1.出现FileNotFoundError: [Errno 2] 没有那个文件或目录: '~/dengjie/Paper/PointNet/pointnet.pytorch/shapenetcore_partanno_segmentation_benchmark_v0/synsetoffset2category.txt'

解决方案

#root=opt.dataset,   
root='/home/dengjie/dengjie/Paper/PointNet/pointnet.pytorch/shapenetcore_partanno_segmentation_benchmark_v0',

2.如果执行以上的指令出现
在这里插入图片描述
在这里插入图片描述

因为show_seg.py调用show3d_balls.py,而show3d_balls.py使用render_balls_so的库

dll = np.ctypeslib.load_library('render_balls_so', '.'),需要重新生成dll,替换原文件的dll。

参考:https://blog.csdn.net/weixin_43978293/article/details/116175134

具体操作如下

用VS新建一个dll动态链接库工程,头文件为dlltest.h,源文件为dllmain.cpp,编译成功后在\x64\Debug文件夹下有一个render_balls_so.dll,替换即可。

dlltest.h

#include <cstdio>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;

struct PointInfo {
	int x, y, z;
	float r, g, b;
};

extern "C" __declspec(dllexport) void render_ball(int h, int w, unsigned char * show, int n, int * xyzs, float * c0, float * c1, float * c2, int r) {
		/*r = max(r, 1);
		vector<int> depth(h*w, -2100000000);
		vector<PointInfo> pattern;
		for (int dx = -r; dx <= r; dx++)
			for (int dy = -r; dy <= r; dy++)
				if (dx*dx + dy*dy<r*r) {
					double dz = sqrt(double(r*r - dx*dx - dy*dy));
					PointInfo pinfo;
					pinfo.x = dx;
					pinfo.y = dy;
					pinfo.z = dz;
					pinfo.r = dz / r;
					pinfo.g = dz / r;
					pinfo.b = dz / r;
					pattern.push_back(pinfo);
				}
		double zmin = 0, zmax = 0;
		for (int i = 0; i<n; i++) {
			if (i == 0) {
				zmin = xyzs[i * 3 + 2] - r;
				zmax = xyzs[i * 3 + 2] + r;
			}
			else {
				zmin = min(zmin, double(xyzs[i * 3 + 2] - r));
				zmax = max(zmax, double(xyzs[i * 3 + 2] + r));
			}
		}
		for (int i = 0; i<n; i++) {
			int x = xyzs[i * 3 + 0], y = xyzs[i * 3 + 1], z = xyzs[i * 3 + 2];
			for (int j = 0; j<int(pattern.size()); j++) {
				int x2 = x + pattern[j].x;
				int y2 = y + pattern[j].y;
				int z2 = z + pattern[j].z;
				if (!(x2<0 || x2 >= h || y2<0 || y2 >= w) && depth[x2*w + y2]<z2) {
					depth[x2*w + y2] = z2;
					double intensity = min(1.0, (z2 - zmin) / (zmax - zmin)*0.7 + 0.3);
					show[(x2*w + y2) * 3 + 0] = pattern[j].b*c2[i] * intensity;
					show[(x2*w + y2) * 3 + 1] = pattern[j].g*c0[i] * intensity;
					show[(x2*w + y2) * 3 + 2] = pattern[j].r*c1[i] * intensity;
				}
			}
		}*/
	}

//extern "C"

dllmain.cpp

#include <cstdio>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;

struct PointInfo {
	int x, y, z;
	float r, g, b;
};

extern "C" {

	__declspec(dllexport) void render_ball(int h, int w, unsigned char * show, int n, int * xyzs, float * c0, float * c1, float * c2, int r) {
		r = max(r, 1);
		vector<int> depth(h*w, -2100000000);
		vector<PointInfo> pattern;
		for (int dx = -r; dx <= r; dx++)
			for (int dy = -r; dy <= r; dy++)
				if (dx*dx + dy*dy<r*r) {
					double dz = sqrt(double(r*r - dx*dx - dy*dy));
					PointInfo pinfo;
					pinfo.x = dx;
					pinfo.y = dy;
					pinfo.z = dz;
					pinfo.r = dz / r;
					pinfo.g = dz / r;
					pinfo.b = dz / r;
					pattern.push_back(pinfo);
				}
		double zmin = 0, zmax = 0;
		for (int i = 0; i<n; i++) {
			if (i == 0) {
				zmin = xyzs[i * 3 + 2] - r;
				zmax = xyzs[i * 3 + 2] + r;
			}
			else {
				zmin = min(zmin, double(xyzs[i * 3 + 2] - r));
				zmax = max(zmax, double(xyzs[i * 3 + 2] + r));
			}
		}
		for (int i = 0; i<n; i++) {
			int x = xyzs[i * 3 + 0], y = xyzs[i * 3 + 1], z = xyzs[i * 3 + 2];
			for (int j = 0; j<int(pattern.size()); j++) {
				int x2 = x + pattern[j].x;
				int y2 = y + pattern[j].y;
				int z2 = z + pattern[j].z;
				if (!(x2<0 || x2 >= h || y2<0 || y2 >= w) && depth[x2*w + y2]<z2) {
					depth[x2*w + y2] = z2;
					double intensity = min(1.0, (z2 - zmin) / (zmax - zmin)*0.7 + 0.3);
					show[(x2*w + y2) * 3 + 0] = pattern[j].b*c2[i] * intensity;
					show[(x2*w + y2) * 3 + 1] = pattern[j].g*c0[i] * intensity;
					show[(x2*w + y2) * 3 + 2] = pattern[j].r*c1[i] * intensity;
				}
			}
		}
	}

}//extern "C"

调试好的PointNet包:https://url23.ctfile.com/f/22628623-519017610-1d8c9e 密码:7875

render_balls_so.dll源文件下载:https://url23.ctfile.com/f/22628623-519017617-ce1cd2 密码7875

shapenet数据集下载:https://shapenet.cs.stanford.edu/ericyi/shapenetcore_partanno_segmentation_benchmark_v0.zip

  • 8
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
引用提到了点云深度卷积神经网络(PointConv),该网络通过点云空间卷积核编码器进行点云形状补全。网络由上下两部分组成,上半部分用于获取权重W,这些权重将与下半部分得到的特征进行卷积。引用中介绍了上采样网络PU-Net,它用于解决生成的点云具有数据稀疏性的问题,以生成更密集且均匀分布的点云。引用提到了TreeGCN(树形卷积),它是TreeGAN中引入的一种树状结构的卷积操作,用于增强传统的卷积网络。 要从入门到精通PyTorch中的三维点云处理,您可以按照以下步骤进行: 1. 了解点云数据:掌握点云数据的基本概念和结构,包括点的坐标、法向量等。 2. 学习PyTorch:熟悉PyTorch的基本操作,包括张量操作、数据加载和模型训练等。 3. 学习点云处理库:掌握使用PyTorch的点云处理库,例如Open3D或PointCloudLib,这些库提供了许多用于点云预处理和可视化的功能。 4. 点云数据预处理:学习如何对点云数据进行预处理,包括数据清洗、去噪、采样等操作。 5. 点云特征提取:了解如何使用PyTorch实现点云特征提取算法,例如PointNet、PointNet++或PointConv。 6. 点云分割和分类:学习如何使用PyTorch实现点云分割和分类任务的网络模型,例如PointCNN或PointSIFT。 7. 点云生成和重建:掌握如何使用PyTorch实现点云生成和重建算法,例如TreeGAN或PU-Net。 8. 模型优化和性能评估:学习如何使用PyTorch进行模型优化和性能评估,包括损失函数的定义、优化器的选择以及模型性能的评估指标。
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值