基于深度学习的点云处理模型PointNet++学习记录

news2024/12/26 13:52:22

前面我们已经学习了Open3D,并掌握了其相关应用,但我们也发现对于一些点云分割任务,我们采用聚类等方法的效果似乎并不理想,这时,我们可以想到在深度学习领域是否有相关的算法呢,今天,我们便来学习一个在点云处理领域具有代表性的算法:PointNet++

PointNet

在学习PointNet++前,我们需要学习以下它的前身:PointNet
我们知道,点云数据具有以下特点:

  • 无序性:点云的位置可以随意调换没有影响(点与点之间可以换)
  • 近密远疏:扫描视角不同导致点云的稀疏性不同
  • 非结构化数据:处理困难,如NLP的处理就要比图像复杂
    那么针对这种问题,该如何解决呢,其实最主要的是我们要去提取特征。

思路:对于无序性的数据,我们要考虑能否利用置换不变性来解决问题,PointNet便是采用这个思路,即对于点云数据求最值(无论是maxmin还是sum,它都与点的位置没有关系)。
同时,由于点云一般只有三维(xyz),其维度太少,因此可以利用神经网络(多层感知机、全连接网络等)来升维,进而再进行处理。
下图为PointNet网络结构,其中里面的input_transform我们无需太过在意,可以看到,其输入的是所有点云,随后进行维度变换,最终输出分类或分割结果。

在这里插入图片描述

PointNet++网络介绍

根据其论文中给出的介绍,Point++是用于点云分割与分类的深度学习模型,由下图可知,该模型主要分为三部分,分别是点空间特征提取、分割模型以及分类模块。其中,Hierarchical Point set feature learning 由一系列点集抽象层(set abstraction)组成,而每一个set abstraction 又由三个关键层组成:sampling layerGrouping layerPointNet Layer

在这里插入图片描述

  1. Sampling layer:Sampling layer的作用是从点云中选择很多个质点和围绕在这些质点的局部区域。作为输入,通过使用FPS算法(farthest point sampling,最远点采样法)选出一系列点作为质点,与随机选取相比,这样可以更好的覆盖整个点集空间。
  2. Grouping layer:这一层使用Ball query方法生成N’个局部区域,根据论文中的意思,这里有两个变量 ,一个是每个区域中点的数量K,另一个是球的半径。这里半径应该是占主导的,会在某个半径的球内找点,上限是K。球的半径和每个区域中点的数量都是人指定的。这一步也可以使用KNN来进行,而且两者的对于结果的影响并不大。
  3. PointNet layer:输入为N’xKx(d+C),输出为N’x(d+C’),这里C’为局部特征的长度,应该是大于C的。这一步主要是将K个局部区域内的点的坐标转换为相对该区域中心点的坐标,并作为PointNet的输入,得到局部特征。

事实上,PointNet++相较于PointNet的创新便是在于数据的处理,其采用了分簇、分组的方式进行处理,这可以大幅减少计算量(PointNet是将所有点云输入PointNet网络,PointNet++是将数据分簇分组后输入PointNet网络)

分簇与分组

在这里,分簇是为了采样,即Sampling layer,而分组则是将每个簇的数据量统一,这样才能够输入卷积网络中运算,具体的,对于分组(Grouping layer)时,如果簇中数量多,那么就按照距离中心点距离进行排序,挑选近的留下(即删除远的点),对于簇中数量少,则将复制该簇内里离中心点最近的点,缺几个则复制几次)

PointNet++项目部署

源码下载

了解了PointNet++的基本原理后,接下来我们便要部署该项目来完成我们的任务,这里,应领导要求,博主并没有使用PointNet++的官方代码(官方代码是基于Tensflow框架开发的),而是使用了Pytorch的版本。

源码下载地址

环境部署

将源码下载后,便是部署环境,PointNet++所使用的包并不多且比较通用,博主直接使用了先前的conda环境,发现可以完美运行,也就没有重新创建conda环境。

S3Dis数据集介绍

在本次实验中,由于我们要做的任务是点云分割任务,因此我们使用的数据集为S3Dis,该数据集是一个室内点云分割数据集, 共有6个区域,13个类别,共计217个小区域(办公室、会议室等)其内容如下:
13个类别

在这里插入图片描述

6个大区域

在这里插入图片描述

我们以Area_1(区域1为例),其内有会议室、走廊等多个场所

在这里插入图片描述

再以office_9为例,office_9.txt是整个办公室点云,Annotations内的是office_9的分割点云,如里面的桌子,椅子等

在这里插入图片描述

我们使用CloudCompare打开可以看到其内容,数据格式为xyzrgb格式

在这里插入图片描述

数据格式转换

为何要进行数据格式转换呢,因为S3DIS数据集只是存储一些点,并没有标签(标签是存储在文件名上的),而collect_indoor3d_data脚本所做的事情就是将每一个Area下的每一个场景的点和标签进行合并,并且保存为.npy格式,加速读取的速度。
生成的.npy格式的数据也有217个。

在这里插入图片描述

.npy文件的内容如下,其实就是转成numpy的格式,从而方便运算,其相比于原本的txt多了一个维度,即第7个维度,用于表示所属类别。

import numpy as np
data=np.load("stanford_indoor3d/Area_1_WC_1.npy")
print(data)

在这里插入图片描述

collect_indoor3d_data代码如下,该部分主要是完成读取点云数据,并设置点云数据的保存路径,名称等

import os
import sys
from indoor3d_util import DATA_PATH, collect_point_label

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT_DIR = os.path.dirname(BASE_DIR)
sys.path.append(BASE_DIR)

anno_paths = [line.rstrip() for line in open(os.path.join(BASE_DIR, 'meta/anno_paths.txt'))]
anno_paths = [os.path.join(DATA_PATH, p) for p in anno_paths]

output_folder = os.path.join(ROOT_DIR, 'data/stanford_indoor3d/')
if not os.path.exists(output_folder):
    os.mkdir(output_folder)

# Note: there is an extra character in the v1.2 data in Area_5/hallway_6. It's fixed manually.
for anno_path in anno_paths:
    print(anno_path)
    try:
        elements = anno_path.split('/')
        out_filename = elements[-3]+'_'+elements[-2]+'.npy' # Area_1_hallway_1.npy
        collect_point_label(anno_path, os.path.join(output_folder, out_filename), 'numpy')
    except:
        print(anno_path, 'ERROR!!')

具体的,划分点云中的标签是通过collect_point_label方法实现的,事实上,我们并不需要读懂这部分代码,要想完成数据转换,只需要将我们的数据格式转换成与S3Dis数据集一样即可。

def collect_point_label(anno_path, out_filename, file_format='txt'):
    """ Convert original dataset files to data_label file (each line is XYZRGBL).
        We aggregated all the points from each instance in the room.

    Args:
        anno_path: path to annotations. e.g. Area_1/office_2/Annotations/
        out_filename: path to save collected points and labels (each line is XYZRGBL)
        file_format: txt or numpy, determines what file format to save.
    Returns:
        None
    Note:
        the points are shifted before save, the most negative point is now at origin.
    """
    points_list = []
    for f in glob.glob(os.path.join(anno_path, '*.txt')):
        cls = os.path.basename(f).split('_')[0]
        print(f)
        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]
        points_list.append(np.concatenate([points, labels], 1)) # Nx7
    
    data_label = np.concatenate(points_list, 0)
    xyz_min = np.amin(data_label, axis=0)[0:3]
    data_label[:, 0:3] -= xyz_min
    
    if file_format=='txt':
        fout = open(out_filename, 'w')
        for i in range(data_label.shape[0]):
            fout.write('%f %f %f %d %d %d %d\n' % \
                          (data_label[i,0], data_label[i,1], data_label[i,2],
                           data_label[i,3], data_label[i,4], data_label[i,5],
                           data_label[i,6]))
        fout.close()
    elif file_format=='numpy':
        np.save(out_filename, data_label)
    else:
        print('ERROR!! Unknown file format: %s, please use txt or numpy.' % \
            (file_format))
        exit()

训练PointNet++网络

首先是模型选择,我们这里可以看到model中可供我们选择的模型,其中加了msg的代表使用了多尺度特征,其效果要比不加的好,当然,其网络也会更复杂一些,我们使用的是pointnet2_sem_seg_msg

parser.add_argument('--model', type=str, default='pointnet2_sem_seg_msg', help='model name [default: pointnet_sem_seg]')

在这里插入图片描述
选择使用的测试集,这里默认为Area_5

parser.add_argument('--test_area', type=int, default=5, help='Which area to use for test, option: 1-6 [default: 5]')

随后一些batch-size设置,epoch设置我们就不再赘述了(博主设置batch=16),同时需要注意的是需要修改以下num_workers的值,博主设置为0,这个看你服务器的性能,博主由于是在本地测试,因此也就设为0了,否则会报错:

UnpicklingError: pickle data was truncated

开启训练

加载数据集(训练集与验证集)

在这里插入图片描述

开启训练,输出最终的训练平均损失,以及训练平均准确度

在这里插入图片描述

测试模型

在测试模型时,我们指定加载的模型权重即可,即我们在训练时保存的log文件的地址:

parser.add_argument('--log_dir', type=str,default="pointnet2_sem_seg_msg", help='experiment root')

可以看到,测试数据集为Area_5

在这里插入图片描述

训练时的模型显卡使用情况如下:

在这里插入图片描述

最终的评估结果如下:

在这里插入图片描述

结语

本章主要介绍了PointNet++模型的结构以及部署问题,接下来便要进行模型的应用,我们需要使用自己的数据集来完成相应的任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2180955.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在树莓派上部署开源监控系统 ZoneMinder

原文:https://blog.iyatt.com/?p17425 前言 自己搭建,可以用手里已有的设备,不需要额外买。这套系统的源码是公开的,录像数据也掌握在自己手里,不经过不可控的三方。 支持设置访问账号 可以保存录像,启…

ST-GCN模型实现花样滑冰动作分类

加入深度实战社区:www.zzgcz.com,免费学习所有深度学习实战项目。 1. 项目简介 本项目实现了A042-ST-GCN模型,用于对花样滑冰动作进行分类。花样滑冰作为一项融合了舞蹈与竞技的运动,其复杂的动作结构和多变的运动轨迹使得动作识别成为一个具…

redis-数据类型

十大数据类型 学习 redis 操作手册 英文 Commands 中文 Redis命令中心(Redis commands) – Redis中国用户组(CRUG) 学习方法 举出一个数据结构的应用场景(理解数据结构特点),并操作&…

深度学习模型可视化工具 Netron 使用教程

Netron 介绍 Netron 是一个用于可视化机器学习模型、深度学习模型、神经网络、图模型(例如用于计算机视觉的 ONNX、Caffe、TensorFlow Lite、TensorFlow.js、Keras、Darknet、TVM、PyTorch、TorchScript、Core ML、ML.NET、NNEF、PaddlePaddle、OpenVINO、Arm NN等…

C++STL--------string

文章目录 一、STL介绍二、string1、constructor构造函数2、operator[]方括号运算符重载3、iterator迭代器4、reverse_iterator反向迭代器5、size和length6、capacity7、clear8、shrink_to_fit9、at10、push_back11、append 二、auto类型(C11)1、使用2、真正的价值 三、范围for(…

基于大数据技术的宠物商品信息比价及推荐系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…

自己做个国庆75周年头像生成器

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 下载相关代码:【免费】《自己做个国庆75周年头像生成器》代码资源-CSDN文库 又是一年国庆节,今年使用国旗做…

MFU简介

1、缩写 MFU - Mask Field Utilization(光刻掩膜版有效利用比例) GDPW - Gross Die Per Wafer,每张wafer上die的数量 2、什么是MASK 在光刻机中,光源(紫外光、极紫外光)透过mask曝光在晶圆上形成图…

华大HC32F448的FreeRTOS移植

为什么要移植FreeRTOS? 目前的程序只是前后台查询方式的架构,有些场合更适用FreeRTOS(免费使用)。 下载地址: 下载 FreeRTOS - FreeRTOS™ 相关知识入门: FreeRTOS™ - FreeRTOS™ (网址) FreeRTOSv9.0.0文件夹…

总结C/C++中内存区域划分

目录 1.C/C程序内存分配主要的几个区域: 2.内存分布图 1.C/C程序内存分配主要的几个区域: 1、栈区 2、堆区 3、数据段(静态区) 4.代码段 2.内存分布图 如图: static修饰静态变量成员——放在静态区 int globalVar 是…

ESXI识别服务器磁盘,虚拟机显示无效

ESXI识别服务器磁盘,虚拟机显示无效 系统意外断电识别不到磁盘的情况下可以管理-》硬件-》搜索磁盘名称,选择切换直通,则虚拟机正常。

COMP 6714-Info Retrieval and Web Search笔记week2

tokenizer:分词器 右半部分:倒排索引 Westlaw AND(&): 要搜索必须同时出现在文档中的两个或多个词语,请使用 AND(&)。例如,输入 narcotics & warrant&#x…

DialMAT:跨模态特征提取与对抗训练的结合

目录 一、背景介绍二、技术路线2.1 DialMAT的总体架构2.2 基于矩的对抗训练(MAT)2.3 跨模态并行特征提取参考文献 一、背景介绍 在智能体研究领域,一个重要的挑战是如何让智能体有效理解人类的语言指令并在实际环境中完成任务。尤其是在复杂环…

光通信——PON技术

PON网络结构 PON(Passive Optical Network,无源光网络)系统的基本组成包括OLT(Optical Line Terminal,光线路终端)、ODN(Optical Distribution Network,光分配单元)和ON…

机器学习基本上就是特征工程——《特征工程训练营》

作为机器学习流程的一部分,特征工程是对数据进行转化以提高机器学习性能的艺术。 当前有关机器学习的讨论主要以模型为中心。更应该关注以数据为中心的机器学习方法。 本书旨在介绍流行的特征工程技术,讨论何时以及如何运用这些技术的框架。我发现&…

Linux C 编程

Linux C 编程 在此推荐一个非常好的学习资料 统计文件单词数量 统计一个文件中的单词数量,可以将文件中的所有字符分为字母和分隔符。分隔符不属于单词内部,故定义一个状态机,来记录当前读取字符的状态。用 OUT 表示此字符不属于一个单词&…

【解决】Mac 上 M系列芯片用 Vmware Fusion安装 win11 遇到的主要的问题汇总

此文很短,没闲话,干活满满 Mac 版本最干净版本的 win11 免费下载链接 :链接:https://pan.quark.cn/s/4e8e8bb93564 本文实验电脑为:Macbook Air M3 第一个问题:如何解决安装Windows11时出现“这台电脑无…

Acwing 扩展欧几里得算法

1.扩展欧几里得算法 回忆:求最大公约数中学过欧几里得算法(辗转相除法):gcd(a,b) gcd(b, a % b); 裴蜀定理:对于任意正整数a,b,那么一定存在非零整数x,y,使得axbygcd(a,b); 扩展欧几里得算法:…

锁相环PLL 学习笔记(一)

锁相环(Phase-Locked Loop, PLL) 一、基本概念及原理 是一个能够比较输出与输入相位差的反馈系统,利用外部输入的参考信号控制环路内部振荡信号的频率和相位,使振荡信号同步至参考信号。 下图为简单锁相环的结构示意图&#xf…

【工欲善其事】巧用 Sublime Text 生成带格式的 HTML 片段

文章目录 【工欲善其事】巧用 Sublime Text 生成带格式的 HTML 片段1 问题由来2 操作流程步骤1:打开代码片段定制页步骤2:在新标签页输入定制 XML步骤3:保存定义内容步骤4:功能测试 3 拓展 【工欲善其事】巧用 Sublime Text 生成带…