点云分类和点云分割

点云分类概念

点云的分类是将点云分类到不同的点云集。同一个点云集具有相似或相同的属性,例如地面、树木、人等;点云分割是根据空间、几何和纹理等特征点进行划分,同一划分内的点云拥有相似的特征。
基于半径选择局部区域,针对得到的每个区域进行特征提取,关键核心原理:

最远点采样法

  • 最远点采样法(farthest point sampling):尽可能覆盖到原始点云数据,例如输入1024个点,要选择128个中心点
    pointnet++最远采样法
    farthest point sampling代码实现如下:
def farthest_point_sample(xyz, npoint):
    """
    Input:
        xyz: pointcloud data, [B, N, 3]
        npoint: number of samples
    Return:
        centroids: sampled pointcloud index, [B, npoint]
    """
    device = xyz.device
    B, N, C = xyz.shape
    centroids = torch.zeros(B, npoint, dtype=torch.long).to(device)#8*512
    distance = torch.ones(B, N).to(device) * 1e10 #8*1024
    farthest = torch.randint(0, N, (B,), dtype=torch.long).to(device)#batch里每个样本随机初始化一个最远点的索引
    batch_indices = torch.arange(B, dtype=torch.long).to(device)
    for i in range(npoint):
        centroids[:, i] = farthest #第一个采样点选随机初始化的索引
        centroid = xyz[batch_indices, farthest, :].view(B, 1, 3)#得到当前采样点的坐标 B*3
        dist = torch.sum((xyz - centroid) ** 2, -1)#计算当前采样点与其他点的距离
        mask = dist < distance#选择距离最近的来更新距离(更新维护这个表)
        distance[mask] = dist[mask]#
        farthest = torch.max(distance, -1)[1]#重新计算得到最远点索引(在更新的表中选择距离最大的那个点)
    return centroids

分组

  • 分组(gouping):输入为batch10246(1024个点,每个点对应3个坐标3个法向量信息), 分组后输出为:batch12816*6(128个中心点,每个簇16个样本)
    gouping代码实现如下:
def query_ball_point(radius, nsample, xyz, new_xyz):
    """
    Input:
        radius: local region radius
        nsample: 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]
    """
    device = xyz.device
    B, N, C = xyz.shape
    _, S, _ = new_xyz.shape
    group_idx = torch.arange(N, dtype=torch.long).to(device).view(1, 1, N).repeat([B, S, 1])
    sqrdists = square_distance(new_xyz, xyz)#得到B N M (就是N个点中每一个和M中每一个的欧氏距离)
    group_idx[sqrdists > radius ** 2] = N #找到距离大于给定半径的设置成一个N值(1024)索引
    group_idx = group_idx.sort(dim=-1)[0][:, :, :nsample]#做升序排序,后面的都是大的值(1024)
    group_first = group_idx[:, :, 0].view(B, S, 1).repeat([1, 1, nsample])#如果半径内的点没那么多,就直接用第一个点来代替了。。。
    mask = group_idx == N
    group_idx[mask] = group_first[mask]
    return group_idx
  • 维度变换(bnpointsnsamplefeatures,8128166->8616*128)
  • 卷积操作(例如:in=6,out=64)(86416*128)
  • MAX操作,得到(864128)
  • 多次采样,分组,卷积 ,采样中心点(1024->512->128)半径为0.1,0.2,0.4;以及簇采样点个数,每一次操作时,都要进行特征拼接,得到batch中心点个数特征,执行拼接操作(b512128,b512256,b512512)->(b512896)

特征提取

特征提取代码实现如下:

def forward(self, xyz, points):
        """
        Input:
            xyz: input points position data, [B, C, N]
            points: input points data, [B, D, N]
        Return:
            new_xyz: sampled points position data, [B, C, S]
            new_points_concat: sample points feature data, [B, D', S]
        """
        xyz = xyz.permute(0, 2, 1) #就是坐标点位置特征
        print(xyz.shape)
        if points is not None:
            points = points.permute(0, 2, 1) ##就是额外提取的特征,第一次的时候就是那个法向量特征
        print(points.shape)
        B, N, C = xyz.shape
        S = self.npoint
        new_xyz = index_points(xyz, farthest_point_sample(xyz, S))
        print(new_xyz.shape)
        new_points_list = []
        for i, radius in enumerate(self.radius_list):
            K = self.nsample_list[i]
            group_idx = query_ball_point(radius, K, xyz, new_xyz)#返回的是索引
            grouped_xyz = index_points(xyz, group_idx)#得到各个组中实际点
            grouped_xyz -= new_xyz.view(B, S, 1, C)#去mean new_xyz相当于簇的中心点
            if points is not None:
                grouped_points = index_points(points, group_idx)
                grouped_points = torch.cat([grouped_points, grouped_xyz], dim=-1)
                print(grouped_points.shape)
            else:
                grouped_points = grouped_xyz

            grouped_points = grouped_points.permute(0, 3, 2, 1)  # [B, D, K, S]
            print(grouped_points.shape)
            for j in range(len(self.conv_blocks[i])):
                conv = self.conv_blocks[i][j]
                bn = self.bn_blocks[i][j]
                grouped_points =  F.relu(bn(conv(grouped_points)))
            print(grouped_points.shape)
            new_points = torch.max(grouped_points, 2)[0]  # [B, D', S] 就是pointnet里的maxpool操作
            print(new_points.shape)
            new_points_list.append(new_points)

        new_xyz = new_xyz.permute(0, 2, 1)
        new_points_concat = torch.cat(new_points_list, dim=1)
        print(new_points_concat.shape)
        return new_xyz, new_points_concat
  • pointnet得到最终整体特征,再进行分类
    pointnet++分类模型pointnet++点云分类

点云分割概念

点云分割算法主要基于从几何约束和统计规则出发制定的严格的人工设计的特征。点云分割的主要过程是将原始3D点云分组为非重叠区域。

点云分割整体流程

pointnet得到最终整体特征,再进行分割
pointnet++分割模型
点云分割

点云项目应用

如果需要本文完整项目代码,以上算法论文或者点云数据集的小伙伴可以私信我哦!

  • 6
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
点云分类和分割是点云处理中的两个重要任务。点云分类是将点云中的每个点分为不同的类别,如地面、建筑、树木等。而点云分割则是将点云分为不同的部分,如建筑的墙、屋顶等。 基于深度学习点云分类和分割方法主要是利用卷积神经网络(CNN)进行特征提取和分类。具体方法包括: 1. PointNet:PointNet是一种基于点集的深度学习架构,能够对不同的点云进行分类、分割和语义分析。它使用了局部特征和全局特征来描述点云,同时利用了多层感知机(MLP)和池化操作来提取特征。 2. PointNet++:PointNet++ 是 PointNet 的改进版,主要改进了点云的采样和聚合方法,通过自适应采样和聚合来处理不同密度的点云。这种方法能够有效地处理不同复杂度的点云任务。 3. PointCNN:PointCNN是一种基于卷积的点云分类和分割方法,主要利用了点云的局部结构和全局特征来进行特征提取。它使用了基于卷积的滤波器来对点云进行卷积操作,从而提取局部特征。 4. KPConv:KPConv是一种基于卷积的点云分类和分割方法,主要利用了点云的局部结构和密度信息来进行特征提取。它使用了核点卷积来对点云进行卷积操作,从而提取局部特征和密度信息。 这些方法都能够有效地处理点云分类和分割任务,并且已经在许多实际应用中得到了广泛的应用。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值