Pointnet++中各任务模型的预测

        在这里分享一下点云分类模型、部件分割模型以及语义分割模型的预测脚本,均根据GitHub - yanx27/Pointnet_Pointnet2_pytorch: PointNet and PointNet++ implemented by pytorch (pure python) and on ModelNet, ShapeNet and S3DIS.icon-default.png?t=N7T8https://github.com/yanx27/Pointnet_Pointnet2_pytorch中的test_classification.py、test_partseg.py和test_semseg.py改写的,pointnet++训练可以参考我的这篇博客

1.classifacation 

        主要了解网络的输入和输出就行了,输入是(batch_size,channel,npoints),分别表示批处理大小(这里都是设置为1,即一次预测一张图),通道数(即xyz共3维),输入点数。输出是(batch_size,num_class)指的是该点云num_class个类别的得分,对他取最大值即可得到最后的预测的类别。

import os
import sys
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT_DIR = BASE_DIR
sys.path.append(os.path.join(ROOT_DIR, 'models'))
import numpy as np
from models import pointnet2_cls_ssg as net
import torch


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

def test(points):
    points=points[None,:,:]
    points = points.transpose(0,2, 1)
    #将numpy格式转换为tensor格式
    tensor_data=torch.tensor(points)
    #放进gpu中
    torch.cuda.set_device(0)
    tensor_data.cuda()
    #预测
    with torch.no_grad():
        pred, _ =  model(tensor_data)
    pred=np.argmax(pred.detach().cpu().numpy())
    return pred

def main():
    data_path=r"data\modelnet40_normal_resampled\airplane"

    weight_path=r"\Pointnet_Pointnet2_pytorch-master\log\classification\pointnet2_cls_ssg\checkpoints\best_model.pth"

    num_class=10
    npoints=2048
    
    global model
    model=net.get_model(num_class, normal_channel=False)
    checkpoint = torch.load(weight_path)
    model.load_state_dict(checkpoint['model_state_dict'])

    for file in os.listdir(data_path):
        if file.endswith(".txt"):
            point_set=np.genfromtxt(os.path.join(data_path,file), delimiter=',').astype(np.float32)
            point_set[:, 0:3] = pc_normalize(point_set[:, 0:3])

            choice = np.random.choice(len(point_set.shape[0]),npoints, replace=True)
            point_set = point_set[choice, :3]

            #预测类别的下标
            pred=test( point_set)
            
            print(f"{file}的类别是{pred}")


if  __name__=="__main__":
    main()

         其中会遇到一个bug,大概意思就是说取batchsize为1时无法做BN,参考博客,注释了两行源码,如下所示。 

2.PartSegmantation

        输入依旧是(batch_size,channel,npoints),输出变成了(batch,npoints,num_classes),从预测一个点云类别,变成了预测点云上所有点的类别,废话不多说,直接上代码。

import os
import sys
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT_DIR = BASE_DIR
sys.path.append(os.path.join(ROOT_DIR, 'models'))
import numpy as np
from models import pointnet2_part_seg_msg as net
import torch


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

def to_categorical(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_y

def test(points,matrix):
    points=points[None,:,:]
    points = points.transpose(0,2,1)
    #将numpy格式转换为tensor格式
    tensor_data=torch.tensor(points)
    #放进gpu中
    torch.cuda.set_device(0)
    tensor_data.cuda()
    #预测
    with torch.no_grad():
        seg_pred, _ = model(tensor_data, matrix)
    
    seg_pred=seg_pred.detach().cpu().numpy().squeeze()

    seg_pred=np.argmax(seg_pred[:, seg_classes[cls]], 1) + seg_classes[cls][0]

    return seg_pred


seg_classes = {'Earphone': [16, 17, 18], 'Motorbike': [30, 31, 32, 33, 34, 35], 'Rocket': [41, 42, 43],
               'Car': [8, 9, 10, 11], 'Laptop': [28, 29], 'Cap': [6, 7], 'Skateboard': [44, 45, 46], 'Mug': [36, 37],
               'Guitar': [19, 20, 21], 'Bag': [4, 5], 'Lamp': [24, 25, 26, 27], 'Table': [47, 48, 49],
               'Airplane': [0, 1, 2, 3], 'Pistol': [38, 39, 40], 'Chair': [12, 13, 14, 15], 'Knife': [22, 23]}

def main():
    path=r"data\shapenetcore_partanno_segmentation_benchmark_v0_normal\02691156"
    weight_path=r"Pointnet_Pointnet2_pytorch-master\log\part_seg\pointnet2_part_seg_msg\checkpoints\best_model.pth"

    npoints=2048
    num_class = 16
    num_part = 50
    global cls 
    cls="Earphone"
    classes={'Airplane': 0, 'Bag': 1, 'Cap': 2, 'Car': 3, 'Chair': 4, 'Earphone': 5, 'Guitar': 6, 'Knife': 7, 'Lamp': 8, 'Laptop': 9, 'Motorbike': 10, 'Mug': 11, 'Pistol': 12, 'Rocket': 13, 'Skateboard':14,'Table':15}

    global model
    model=net.get_model(num_part, normal_channel=True)
    checkpoint = torch.load(weight_path)
    model.load_state_dict(checkpoint['model_state_dict'])

    for file in os.listdir(path):
        if file.endswith(".txt"):
            point_set=np.loadtxt(os.path.join(path,file)).astype(np.float32)
            point_set[:, 0:6] = pc_normalize(point_set[:, 0:6])
            
            choice = np.random.choice(point_set.shape[0],npoints, replace=True)
            
            point_set = point_set[choice, :6]

            #预测类别的下标
            pred=test(point_set,to_categorical(torch.tensor(classes[cls]),len(classes)))

            result=np.concatenate([point_set,pred[:,None]],axis=1)
            np.savetxt(f"pre_{file}",result)


if  __name__=="__main__":
    main()

3.Segmantation

        这个其实和部件分割差不多,差别就在于部件分割的点数很少,不需要额外的预处理就可以通过网络直接预测,而语义分割要预测的场景一般比较大,比如S3DIS,一个Area有上千万个点很正常。如果你是要预测小规模的点云,完全可以按照上面部件分割的代码来修改。如果是要预测大场景点云,后面有时间我再整理一下代码,预测S3DIS数据集如何进行预处理,预测和拼接。

        未完待续。。。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃鱼不卡次

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值