PointNet++分类与分割详解

article/2025/9/14 5:12:50

前言

       PointNet++是一个用于对不规则形状的点云数据进行分类和分割任务的深度神经网络。相对于传统的基于网格的3D数据表示方法,点云数据更易于获取和处理。PointNet++的另一个优势是它引入了多尺度层次结构,可以处理更为复杂的点云数据。相比于第一版的PointNet网络作者提出了许多新的想法,也取得了很不错的效果。

PointNet算法存在的问题

(1)一幅点云图像点数量太多,这会造成计算量过大从降低算法速度,如何解决?

(2)如何将点云划分为不同的区域,并且获取不同区域的局部特征?

(3)点云不均匀的时候应该如何解决这个问题?

带着这些问题我们接下来开始通过论文与源码来解决这些问题。

分类任务

8a4d9f3376a45c32f22c60ad476248c8.jpeg

分层抽取特征 set abstraction

该模块主要由3个部分组成:

1.采样层(sample layer):在稠密的点云中抽取出一些相对重要的点作为中心点,即FPS(farthest point sampling)最远点采样法,也为了解决本文中的第一个问题。

2.分组层(group layer):找距离中心点附近最近的K个点,组成local points region。这操作有点像图像卷积,形成卷积图像,方便提取特征。解决第二个问题。

3.特征提取层(pointnet layer):特征提取层。对每个local points region提取特征。

FPS流程如下:

(1)随机选择一个点作为初始择采样点;

(2)计算未选择采样点集中每个点与已选择采样点集之间的距离distance,将距离最大的那个点加入已选择采样点集,

(3)根据新的采样点计算distance,一直循环迭代下去,直至获得了目标数量的采样点。

如下图在所有的点当中选出了5个点。

da1a282f9e73683da21c50df354f1151.png

代码实现如下

def farthest_point_sample(xyz, npoint):     """Input:xyz: pointcloud data, [B, N, 3]npoint: number of samplesReturn:centroids: sampled pointcloud index, [B, npoint]"""device = xyz.deviceB, N, C = xyz.shapecentroids = torch.zeros(B, npoint, dtype=torch.long).to(device)         #[b,npoint]    #npoint是要从很多的点中筛选出那么多distance = torch.ones(B, N).to(device) * 1e10                           #[b,N]         #N指原来有N个点farthest = torch.randint(0, N, (B,), dtype=torch.long).to(device)       #[b]           在0-N中随机生成了B个点(随机选了个点作为初始点,并且用的索引batch_indices = torch.arange(B, dtype=torch.long).to(device)            #[b]            0-bfor i in range(npoint):centroids[:, i] = farthestcentroid = xyz[batch_indices, farthest, :].view(B, 1, 3)           #获得索引对应的位置的坐标dist = torch.sum((xyz - centroid) ** 2, -1)                        #计算所有坐标和目前这个点的距离mask = dist < distance                                             #距离符合要求的distance[mask] = dist[mask]                                        #将符合要求的距离都放入farthest = torch.max(distance, -1)[1]                              #最远距离对应的索引  [b]return centroids                                                       #最终输出筛选的[n,npoint]个点的位置

分组层流程如下:

(1)根据FPS筛选后获得相应的中心点

(2)将每一个中心点在原点集中根据距离筛选出附近需要的点数,以每个FPS点为中心形成一个个新的点集

(3)新的点集会做一个类似坐标归一化的操作形成3个新特征然后与原先每个点自带的特征结合形成特征提取前的新特征。

简图如下所示:

c44b141189eccb1afe7c9682cd5ef7a2.png

   图一  

3346b3e3963e5708250d5134402e3d21.png

图二

       图一中红点为FPS结果的中心点,黑点为初始的一些点。图二绿点是根据距离筛选后的点,这些点与红点将会组成一系列的点集。

       在分组层中作者提出了3种方案:SSG(single scale grouping)、MSG(multi-scale grouping)多尺度、MRG(multi-resolution grouping)多分辨率。实际上就是采用不同的半径或不同的分辨率进行了多次采样分组。也是为了解决本文中的第三个问题。

SSG:就相当于只有一种半径做了分组采样

9f36152f36d59afa2788301404fd4c5a.png

MSG:相当于在同分辨率下做了多个半径分组采样,然后再将点集结合起来。

aa5ae0262f303f506022443365ce5abf.pngccc4a6e3d0932305999fc9383e037850.pngaa4484154577d1dd1e946f27ac613522.png

MRG

0e7daba91bfd9d4b254cc5b2d26d4526.png

代码实现如下

def query_ball_point(radius, nsample, xyz, new_xyz):"""Input:radius: local region radiusnsample: max sample number in local region   xyz: all points, [B, N, 3]new_xyz: query points, [B, S, 3]Return:group_idx: grouped points index, [B, S, nsample]""""""1.预设搜索区域的半径R与子区域的点数K2.上面提取出来了 s 个点,作为 s个centriods。以这 s个点为球心,画半径为R的球体(叫做query ball,也就是搜索区域)。3.在每个以centriods的球心的球体内搜索离centriods最近的的点(按照距离从小到大排序,找到K个点)。如果query ball的点数量大于规模nsample,那么直接取前nsample个作为子区域;如果小于,那么直接对某个点重采样(此处直接复制了第一个点),凑够规模nsample"""device = xyz.deviceB, N, C = xyz.shape_, S, _ = new_xyz.shapegroup_idx = torch.arange(N, dtype=torch.long).to(device).view(1, 1, N).repeat([B, S, 1])    #[2,512,1024]sqrdists = square_distance(new_xyz, xyz)    #获得采样后点集与原先点集的距离[2,512,1024]group_idx[sqrdists > radius ** 2] = N       #将距离比半径大的,将此处置为1024group_idx = group_idx.sort(dim=-1)[0][:, :, :nsample]  #因为是0-1023的索引,不符合要求的变味了1024,再对索引排序,获得前nsample个  [b,s,nsample]group_first = group_idx[:, :, 0].view(B, S, 1).repeat([1, 1, nsample])  #拿了符合要求的第一个索引点索引,也就是中心点,并且复制了nsample次     [b,s,nsample]mask = group_idx == N                #查看那前nsample中有没有不符合要求的group_idx[mask] = group_first[mask]   #其中将不符合要求的点,全部换成符合要求的第一个点return group_idx   def sample_and_group(npoint, radius, nsample, xyz, points, returnfps=False):"""Input:npoint:radius:nsample:xyz: input points position data, [B, N, 3]points: input points data, [B, N, D]Return:new_xyz: sampled points position data, [B, npoint, nsample, 3]new_points: sampled points data, [B, npoint, nsample, 3+D]"""B, N, C = xyz.shapeS = npointfps_idx = farthest_point_sample(xyz, npoint) # [B, npoint]        #FPS最远点采样算法  获得需要点的索引new_xyz = index_points(xyz, fps_idx)          # [B, npoint,c]                        #将对应索引的点拿出来idx = query_ball_point(radius, nsample, xyz, new_xyz)       #[b,npoint,nsample]         #进行query_ball处理,类似于卷积操作,找到new_xyz附近原xyz的nsample个点,返回对应的索引[b,npoint,nsample]grouped_xyz = index_points(xyz, idx) # [B, npoint, nsample, C]       #将对应索引的点拿出来grouped_xyz_norm = grouped_xyz - new_xyz.view(B, S, 1, C)   #每个点减去自己半径内中心的那个点进行归一化[B, npoint, nsample, C]if points is not None:   #points即原来点就存才的一些特征grouped_points = index_points(points, idx)       #将每个区域原先的特征拿出来   [b,npoint,nsample,D]new_points = torch.cat([grouped_xyz_norm, grouped_points], dim=-1) # [B, npoint, nsample, C+D]   #将归一化数据和原先的特征结合else:new_points = grouped_xyz_norm                    #如果原先没有特征的,那么数据就是归一化后的点if returnfps:return new_xyz, new_points, grouped_xyz, fps_idxelse:return new_xyz, new_points

特征提取层

       该层就是一些基本卷积池化操作。最后FPS选中的那些点特征就会变多。

e1e2cabd55575cc3a06a62d25bf6685a.png45843d2325cec2c04e0775a6c64bbbfd.png

       如此重复几次set abstraction层,在最后接一些全连接网络对点云进行分类。

分割任务

4b41ac3b32c82a46e2671fbf669cebaf.png

       分割任务的特征提取器与分类任务是一样的,接下来就主要讲下上采样的环节。作者提出了一种基于距离插值的分层特征传播(Feature Propagation)策略。

大体流程如下:

(1)计算反向距离加权平均的权重,如下图所示:红点即FPS特征提取后的点,实际上红点的特征数量也会比黑点要多。而上采样就是让这些黑点也产生符合的特征。

2251d7ded991ae40f9bae7824f5ac153.png

权重计算:每个黑点寻找出附近最近的3个红点,然后在每个红点根据距离权重为黑点分配特征。那么每个黑点都会产生新的特征。红点也是要进行如此的操作。即上图的所有点都会产生新特征。

7af870025b17fa75334da7b853eed9ae.pngbc119e8b1403fadf124ec834ca6b05b2.png718fc4bece948c7ea45bb123e7bd9bca.pngd361bd6ea005831c92ee017c4135b41c.png

(2)产生的新特征与上一层的特征进行cat操作,再通过卷积等完成特征融合。一步上采样结束。

代码实现如下

class PointNetFeaturePropagation(nn.Module):  #上采样def __init__(self, in_channel, mlp):super(PointNetFeaturePropagation, self).__init__()self.mlp_convs = nn.ModuleList()self.mlp_bns = nn.ModuleList()last_channel = in_channelfor out_channel in mlp:self.mlp_convs.append(nn.Conv1d(last_channel, out_channel, 1))self.mlp_bns.append(nn.BatchNorm1d(out_channel))last_channel = out_channeldef forward(self, xyz1, xyz2, points1, points2):"""Input:xyz1: input points position data, [B, C, N]      上一层的xyz2: sampled input points position data, [B, C, S]  现在层的points1: input points data, [B, D1, N]            上一层的points2: input points data, [B, D2, S]            现在层的Return:new_points: upsampled points data, [B, D', N]"""xyz1 = xyz1.permute(0, 2, 1)xyz2 = xyz2.permute(0, 2, 1)points2 = points2.permute(0, 2, 1)B, N, C = xyz1.shape_, S, _ = xyz2.shapeif S == 1:interpolated_points = points2.repeat(1, N, 1)else:dists = square_distance(xyz1, xyz2)    #计算两点集各点之间距离[b,N,S]dists, idx = dists.sort(dim=-1)        #排序dists, idx = dists[:, :, :3], idx[:, :, :3]  # [B, N, 3]  获得距离最近的3点dist_recip = 1.0 / (dists + 1e-8)norm = torch.sum(dist_recip, dim=2, keepdim=True)weight = dist_recip / norm              #根据距离设置权重interpolated_points = torch.sum(index_points(points2, idx) * weight.view(B, N, 3, 1), dim=2)   #[B,N,D2]if points1 is not None:points1 = points1.permute(0, 2, 1)new_points = torch.cat([points1, interpolated_points], dim=-1)   #上采样cat  [B,N,D1+D2]else:new_points = interpolated_pointsnew_points = new_points.permute(0, 2, 1)                             #[B,D1+D2,N]for i, conv in enumerate(self.mlp_convs):bn = self.mlp_bns[i]new_points = F.relu(bn(conv(new_points)))return new_points         #[B, D', N]

       至此,有关PointNet++的文章解析就完毕了!如有错误解读的地方,欢迎批评指正,我们共同进步!


http://chatgpt.dhexx.cn/article/w0hEHR7S.shtml

相关文章

【点云分类和分割】简述PointNet和PointNet++的理解

Hello大家好&#xff0c;最近阅读了PointNet和PointNet两篇论文&#xff0c;本人觉得这是点云方向入手的比较简单的入门论文&#xff0c;下面阐述一下自己对这两篇论文的理解 一、首先点云是非常重要的三维数据结构&#xff0c;但是其有着非常特殊的性质&#xff0c;不规则性和…

PointNet解读

PointNet解决的问题&#xff1a; 如上图所示&#xff1a; 1.点云图像的分类&#xff08;整片点云是什么物体&#xff09; 2.点云图像的部件分割&#xff08;整片点云所代表的物体能拆分的结构&#xff09; 3.点云图像的语义分割&#xff08;将三维点云环境中不同的物体用不同…

基于深度学习方法的点云算法3——PointNet++(点云分类分割)

基于深度学习方法的点云算法3——PointNet&#xff08;点云分类分割&#xff09; 请点点赞&#xff0c;会持续更新&#xff01;&#xff01;&#xff01; 基于深度学习方法的点云算法1——PointNetLK&#xff08;点云配准&#xff09; 基于深度学习方法的点云算法2——PointNet…

论文解读PointNet(用于点云处理的深度学习框架)

随着最近几年神经网络在CV、NPL等领域取得重大的成果&#xff0c;因此就有学者希望将神经网络应用于3D任务中。在这篇文章&#xff08;PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation&#xff09;出现之前&#xff0c;一般在3D任务中用的最多的…

最全PointNet和PointNet++要点梳理总结

一、基本简介 本篇博文主要是对 PointNet&#xff0c;PointNet 论文的要点进行梳理和总结。认真阅读本博文后&#xff0c;不仅能够深刻理解论文的核心算法思想&#xff0c;而且对模型训练数据、模型的训练流程也能了然于胸。如果想阅读原论文以及翻译&#xff0c;参考下面的链接…

苹果将强制开发人员启用双因素认证提高安全

苹果的开发人员在近期应该都收到了公司的电子邮件通知&#xff0c;知会他们在今年2月27日之后&#xff0c;都必须启用双因素认证才能登入开发人员账号。苹果在邮件中指出&#xff0c;为了让开发人员的账号更为安全&#xff0c;从2月27日起&#xff0c;不管是要登入苹果的开发人…

关闭appleid双重认证_Apple ID 被停用如何解决?

苹果帐户被停用一般是因为输错密码次数过多&#xff0c;或者登录的设备数过多。账户被停用后&#xff0c;iPhone 就会弹出“您的帐户已在 App Store 和 iTunes 中被禁用”等提示。 如果看到一条内容为 " 您的帐户已在 App Store 和 iTunes 中被禁用 " 的信息&#xf…

苹果规定开发人员得使用双认证登入 以确保帐号安全

苹果的开发人员在近期应该都收到了公司的电子邮件通知&#xff0c;知会他们在今年2月27日之后&#xff0c;都必须启用双因素认证才能登入开发人员账号。 苹果在邮件中指出&#xff0c;为了让开发人员的账号更为安全&#xff0c;从2月27日起&#xff0c;不管是要登入苹果的开发人…

苹果怎么解ID锁?苹果ID锁解锁办法汇总

苹果ID锁很多人了解都不是很清楚&#xff0c;而且很多人认为用爱思助手刷机可以刷掉ID锁&#xff0c;如果你的手机出现ID锁后&#xff0c;那你就必须输入Apple ID账号密码才能激活后&#xff0c;无论之后你再怎么刷机都是需要账号密码才能激活的。 苹果解ID锁的办法在网上也是五…

苹果手机账号验证失败连接不上服务器,苹果手机让检查Apple ID 电话号码点击后验证失败,连接服务器失败出错...

这个问题应该是信号或者网络连接的问题&#xff0c;也可能是该时段服务器连接量过大。 建议换个时间段尝试&#xff0c;或者关掉wifi使用数据连接尝试验证。 双重认证是一种相对较新的安全保护机制&#xff0c;直接内建于 iOS、macOS、Apple tvOS、watchOS 和 Apple 网站中。它…

苹果开发者账号:忘记AppleID的安全提示问题怎么办?

方法一&#xff1a;通过iPhone重设安全问题 1、使用账号密码在设置里登录任意一台iOS 9及以上系统的手机 2、登录一段时间&#xff08;大概一个月&#xff09;之后&#xff0c;点击开启双重认证 3、 刚登陆的时候开启双重认证的话还需要回答安全提示问题。所以等一段时间再开启…

最近发现有很多人一直在问苹果ID双重认证怎么关闭。

最近发现有很多人一直在问苹果ID双重认证怎么关闭&#xff1f; 其实我想说大家都粗心了&#xff0c;双重认证是和ios版本没有关系的&#xff0c;无论什么IOS版本开通的双重认证都是可以关闭的。https://support.apple.com/zh-cn/HT204915 最后一段有说明哦。 其实苹果在官网上已…

苹果手机iCloud钥匙串的加密缺陷

什么是iCloud钥匙串 苹果钥匙串是苹果电脑&#xff0c;手机&#xff0c;平板上的密码管理器&#xff0c;帮助用户保存管理账号密码。开启iCloud云同步后&#xff0c;可以在用户的所有设备间同步账号密码&#xff0c;同时也会备份一份在iCloud上。 由于苹果默认会开启iCloud云同…

苹果激活锁怎么解除?手把手教你关闭激活锁

苹果激活锁怎么解除?苹果手机上的激活锁可以确保我们的设备和信息安全,在设备丢失或者被窃的时候,开启的激活锁可以帮助我们减少损失。很多人不太了解苹果手机的激活锁,今天就教大家关闭激活锁的方法。 情景一:抹掉设备 有些时候我们会抹掉自己的设备,如果在抹掉设备之前…

苹果icloud文件服务器,你真的会用苹果iCloud吗?这7个隐藏功能,你未必全知道...

苹果的iCloud&#xff0c;可能只有当手机弹出“你的iPhone云储存空间不足时”&#xff0c;你才会感知到它的存在&#xff0c;在很多人的印象当中&#xff0c;它只是一个照片自动备份的工具 其实除了储存照片&#xff0c;它还有其它的作用&#xff0c;这些作用将有利于你的工作效…

苹果免密支付怎么关闭_有人苹果手机被盗刷了!那是设置有问题...

最近在家憋的实在难受&#xff0c;唯一能出门的理由也就是下楼买菜了... 付款的时候&#xff0c;意外的发现自己开启了「免密支付」&#xff0c;虽说很方便&#xff0c;但总觉得有一丝不安全。 这不我刚在网上看到一个新闻&#xff0c;某位 iPhone 用户的 Apple ID 突然不能登陆…

ios重签工具避免双重认证

由于苹果发布的新规定&#xff0c;从 2019 年 2 月 27 日开始&#xff0c;开发者要开启双重身份验证才可以登录账户、查看证书&#xff0c;有了双重认证&#xff0c;只能通过用户信任的设备才能访问 Apple ID。例如&#xff0c;你有一台 iPhone 并且要在未授权的 Mac 上登录&am…

apple 关闭双重认证_这次Apple可以关闭工作吗?

apple 关闭双重认证 A recent poll in The Register asked who is more closed, Microsoft or Apple? A whopping 55% of respondents thought that dubious honor belongs to Apple (21% said Microsoft, and 24% said they were both equals in the matter). 《 The Registe…

关闭appleid双重认证_iPhone 丢失怎么办?开启双重认证就能解决!

现在很多同学手里都不止一台苹果设备。 像我一台 iPhone11 Pro 主力机&#xff0c;一台 iPhoneSE 备用机&#xff0c;再加上 iPad Pro 和MacBook Pro...别问为啥&#xff0c;因为我家里有矿&#xff01; 但是 Apple ID 只有一个&#xff0c;所以我通常会选择设置「双重认证」来…

关闭appleid双重认证_如何查看并移除登陆过Apple ID的设备

在iOS设备上依次打开“设置 - Apple ID”&#xff0c;然后下滑至页面底端&#xff0c;可以看到一些设备名称&#xff0c;这些设备表示曾登陆过该 Apple ID。 点击任意一台设备可以查看具体的设备型号、系统版本、电话号码等信息。 如果不再使用列表中的设备&#xff0c;或者不认…