PointNet

Introduction

  1. 输入为一帧的全部点云数据的集合,表示为一个nx3的2d tensor,其中n代表点云数量,3对应xyz坐标(3×n)。
  2. 输入数据先通过和一个T-Net学习到的转换矩阵相乘来对齐,保证了模型的对特定空间转换的不变性。(input transform)
  3. 通过多次mlp对各点云数据进行特征提取后,再用一个T-Net对特征进行对齐。
  4. 在特征的各个维度上执行maxpooling操作来得到最终的全局特征。
  5. 对分类任务,将全局特征通过mlp来预测最后的分类分数;对分割任务,将全局特征和之前学习到的各点云的局部特征进行串联,再通过mlp得到每个数据点的分类结果。
网络结构:

在这里插入图片描述
该网络根据任务(不管分类还是分割)可以看成两个网络,一是做分类任务的蓝色区域,二是做分割任务的浅黄色区域
mlp:https://blog.csdn.net/fg13821267836/article/details/93405572

网络输入: n × × × 3 的张量。其中n是点云数据包含的点的个数,3是空间位置坐标(x,y,z)。

input transform 和 feature transform: 为了保证输入点云的不变性(旋转平移等刚体变换),作者在进行特征提取前对点云数据进行了对齐操作(也就是input transform),对齐操作是通过训练一个小型的网络(T-Net)来得到转换矩阵,并将之和输入点云数据相乘来实现。
在这里插入图片描述

class STN3d(nn.Module):
    def __init__(self, channel):
        super(STN3d, self).__init__()
        self.conv1 = torch.nn.Conv1d(channel, 64, 1)
        self.conv2 = torch.nn.Conv1d(64, 128, 1)
        self.conv3 = torch.nn.Conv1d(128, 1024, 1)
        self.fc1 = nn.Linear(1024, 512)
        self.fc2 = nn.Linear(512, 256)
        self.fc3 = nn.Linear(256, 9)
        self.relu = nn.ReLU()

        self.bn1 = nn.BatchNorm1d(64)
        self.bn2 = nn.BatchNorm1d(128)
        self.bn3 = nn.BatchNorm1d(1024)
        self.bn4 = nn.BatchNorm1d(512)
        self.bn5 = nn.BatchNorm1d(256)

    def forward(self, x):
        batchsize = x.size()[0] # shape (batch_size,3,point_nums)
        x = F.relu(self.bn1(self.conv1(x))) # shape (batch_size,64,point_nums)
        x = F.relu(self.bn2(self.conv2(x))) # shape (batch_size,128,point_nums)
        x = F.relu(self.bn3(self.conv3(x))) # shape (batch_size,1024,point_nums)
        x = torch.max(x, 2, keepdim=True)[0] # shape (batch_size,1024,1)
        x = x.view(-1, 1024) # shape (batch_size,1024)

        x = F.relu(self.bn4(self.fc1(x))) # shape (batch_size,512)
        x = F.relu(self.bn5(self.fc2(x))) # shape (batch_size,256)
        x = self.fc3(x) # shape (batch_size,9)

        iden = Variable(torch.from_numpy(np.array([1, 0, 0, 0, 1, 0, 0, 0, 1]).astype(np.float32))).view(1, 9).repeat(
            batchsize, 1) # # shape (batch_size,9)
        if x.is_cuda:
            iden = iden.cuda()
        # that's the same thing as adding a diagonal matrix(full 1)
        x = x + iden # iden means that add the input-self
        x = x.view(-1, 3, 3) # shape (batch_size,3,3)
        return x

3 × × × 3 的input transform矩阵的获取还是比较简单,这么一套操作下来,这个input transform矩阵就不是固定的了,它会根据网络的输入动态调整矩阵的权重。
和上面的input transform矩阵的获取方式类似,feature transform的 64 × × × 64 矩阵获取代码实现如下:

class STNkd(nn.Module):
    def __init__(self, k=64):
        super(STNkd, self).__init__()
        self.conv1 = torch.nn.Conv1d(k, 64, 1)
        self.conv2 = torch.nn.Conv1d(64, 128, 1)
        self.conv3 = torch.nn.Conv1d(128, 1024, 1)
        self.fc1 = nn.Linear(1024, 512)
        self.fc2 = nn.Linear(512, 256)
        self.fc3 = nn.Linear(256, k * k)
        self.relu = nn.ReLU()

        self.bn1 = nn.BatchNorm1d(64)
        self.bn2 = nn.BatchNorm1d(128)
        self.bn3 = nn.BatchNorm1d(1024)
        self.bn4 = nn.BatchNorm1d(512)
        self.bn5 = nn.BatchNorm1d(256)

        self.k = k

    def forward(self, x):
        batchsize = x.size()[0]
        x = F.relu(self.bn1(self.conv1(x)))
        x = F.relu(self.bn2(self.conv2(x)))
        x = F.relu(self.bn3(self.conv3(x)))
        x = torch.max(x, 2, keepdim=True)[0]
        x = x.view(-1, 1024)

        x = F.relu(self.bn4(self.fc1(x)))
        x = F.relu(self.bn5(self.fc2(x)))
        x = self.fc3(x)

        iden = Variable(torch.from_numpy(np.eye(self.k).flatten().astype(np.float32))).view(1, self.k * self.k).repeat(
            batchsize, 1)
        if x.is_cuda:
            iden = iden.cuda()
        x = x + iden
        x = x.view(-1, self.k, self.k)
        return x

64 × × × 64 的feature transform矩阵很难优化,但是作者发现如果这个矩阵约等于一个正交矩阵,那么优化就方便很多,也稳定很多。为了实现这个矩阵约等于一个正交矩阵,根据正交矩阵的性质,即正交矩阵与其转置的乘积等于单位矩阵。那么作者额外增加了一个损失函数,定义如下:
在这里插入图片描述
作者在代码中的实现如下:

def feature_transform_reguliarzer(trans):
    """ make the transformation matrix of input akin to orthogonal matrix"""
    d = trans.size()[1]
    I = torch.eye(d)[None, :, :]
    if trans.is_cuda:
        I = I.cuda()
    loss = torch.mean(torch.norm(torch.bmm(trans, trans.transpose(2, 1) - I), dim=(1, 2)))
    return loss

为什么做分割任务的时候,输入到分割网络的特征为1088?
在这里插入图片描述
这个 n × × × 1088的张量由两部分组成,一个是特征提取网络的输出(大小为 n × × × 64 ),另一个是通过maxpooling后的global feature(大小为1024),在进行两者融合的时候,对global feature进行了广播,那么64+1024就是1088了。为什么要这么做呢?论文中这么提到

After computing the global point cloud feature vector, we feed it back to per point features by concatenating the global feature with each ofthe point features. Then we extract new per point features based on the combined point features - this time the per point feature is aware of both the local and global information

答案就是作者想要融合点的特征信息(来自特征提取网络的输出)与全局特征(来自global feature)。

问:这一套下来,作者一直在做点之间特征的单独提取,除了最后一层maxpool获取全局信息外,好像并没有将点与其周围点进行融合,提取局部特征呀?

的确,在PointNet这篇文章中确实没有做到像CNN那样逐层提取局部特征。我们知道在CNN中,一个点会与周围若干点进行加权求和(具体取决于卷积核大小),然后获取一个新的点,随着网络层数加深,深层网络的一个点对应原始图像的一个映射区域,这就是感受野的概念。但是本文做的特征提取都是点之间独立进行的,这势必会造成一些问题,至于具体的问题解决,作者在PointNet++展开了说明。

Matlab PointNet是一个基于Matlab编程语言的深度学习框架,主要用于处理点云数据PointNet是一个用于点云分类、分割和语义分析等任务的端到端架构。 Matlab PointNet框架具有以下特点和功能: 1. 网络结构:PointNet是一个全连接神经网络,并且具有旋转不变性。它可以处理任意数量的点,并将点云转换为固定大小的特征向量。 2. 特征学习:PointNet通过学习点云中每个点的局部特征来捕捉点云数据的整体结构和特性。它能够学习到点的位置、法线、颜色等信息,从而实现对点云的全局表示。 3. 点云分类:PointNet可以用于点云的分类任务,即将点云分为不同的类别。通过训练,网络可以学习到点云的特征表示,并最终判断点云所属的类别。 4. 点云分割:PointNet还可用于点云的分割任务,即将点云中的每个点分配给不同的物体或区域。通过训练,网络可以学习到点云的局部特征,从而实现对点云的细粒度分割。 5. 语义分析:PointNet可以用于点云的语义分析任务,即对点云中的每个点进行语义标签预测。通过训练,网络可以学习到点云中每个点的语义信息,从而实现对点云的语义分析和理解。 在使用Matlab PointNet框架时,可以从数据准备、模型定义、网络训练和评估等方面进行操作。Matlab提供了丰富的工具和函数,可以方便地进行点云数据的加载、处理和可视化。此外,Matlab还提供了各种深度学习工具箱,如Deep Learning Toolbox,用于构建和训练PointNet网络。 总而言之,Matlab PointNet是一个用于处理点云数据深度学习框架,它具有强大的特征学习能力和广泛的应用领域。在处理点云相关任务时,可以使用Matlab PointNet框架来实现高效的点云处理和分析。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值