这篇文章主要介绍了PointCNN原理是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇PointCNN原理是什么文章都会有所收获,下面我们一起来看看吧。
成都创新互联专业为企业提供衡东网站建设、衡东做网站、衡东网站设计、衡东网站制作等企业网站建设、网页设计与制作、衡东企业网站模板建站服务,十余年衡东做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。
PointCNN的动机是这样的:
图中,小写字母f表示该点的特征,脚标相同的f表示对应点的特征也相同,作者告诉我们,图里有两个问题存在:
首先,假设一种情形,图ii和图iii是两种物体,但是,我们按照一定顺序排列,得到特征序列(fa,fb,fc,fd),碰巧这两个物体的特征还都一样,所以,这两种原本不同的物体,就被判定为同一种物体了。其次,另一种情形,图iii和图iv,从形状来看,本来是同一种物体,但是由于顺序选取不恰当,图iii的特征序列是(fa,fb,fc,fd),而图iv是(fc,fa,fb,fd),这就不好意思了,你俩不一样。
作者就觉得,这两种问题不解决,点云识别就做不好。所以,他想了个办法,训练一种变换,经过变换之后,让ii和iii的特征不同,让iii和iv的特征相同。这种变换怎么得到呢?用深度网络训练。作者将其命名为X-transformation。
接着,作者又再想了,图像处理领域的卷积操作,是对领域进行的,那在点云里,也可以使用这种思路啊,只要先找好领域就行了。最后就是这么实现的。
下面是代码部分:
P.S.作者的Github维护的很好,经常更新,而且对读者的答疑也很及时,大赞。
看过代码的同学都知道,作者的核心思想X变换在代码pointcnn.py的xconv中,根据算法流程,可以把这部分代码划分成‘特征提取’和‘X矩阵训练’两块。下面分开来说。
用于提取邻域特征的只有两个dense层(也叫fc层/MLP),很简单地将尺度为(P,K,C)的邻域结构升维到了(P,K,C’)。
# Prepare featuresto be transformed
nn_fts_from_pts_0 =pf.dense(nn_pts_local_bn, C_pts_fts, tag + 'nn_fts_from_pts_0',is_training)#fc1, (N, P, K, C_pts_fts) nn_fts_from_pts =pf.dense(nn_fts_from_pts_0, C_pts_fts, tag + 'nn_fts_from_pt',is_training)#fc2, features, f_delta if fts isNone:
nn_fts_input = nn_fts_from_pts else:
nn_fts_from_prev = tf.gather_nd(fts,indices, name=tag + 'nn_fts_from_prev')
nn_fts_input = tf.concat([nn_fts_from_pts,nn_fts_from_prev], axis=-1, name=tag + 'nn_fts_input')
接下来作者没有使用pointnet中的maxpooling,这一点论文中也提到了,因为作者认为训练出一个X变换来能达到更好的效果。
而关于X变换,居然有三层,第一层是卷积层,让人很吃惊,卷积核是1*k的,也就是在邻域维度上,直接把k个邻域点汇聚到一个点上,且用了K×K个卷积层,把特征维度升高到k*k,维度从(P,K,C)变成了(P,1,K×K);
if with_X_transformation: ######################## X-transformation ######################### X_0 = pf.conv2d(nn_pts_local, K * K, tag + 'X_0', is_training, (1, K)) X_0_KK = tf.reshape(X_0, (N, P, K, K), name=tag + 'X_0_KK') X_1 = pf.depthwise_conv2d(X_0_KK, K, tag + 'X_1', is_training, (1, K)) X_1_KK = tf.reshape(X_1, (N, P, K, K), name=tag + 'X_1_KK') X_2 = pf.depthwise_conv2d(X_1_KK, K, tag + 'X_2', is_training, (1, K), activation=None) X_2_KK = tf.reshape(X_2, (N, P, K, K), name=tag + 'X_2_KK') fts_X = tf.matmul(X_2_KK, nn_fts_input, name=tag + 'fts_X')
紧接着,作者用了两个dense层,保持了这个结构
X_1 = pf.dense(X_0,K * K, tag + 'X_1', is_training, with_bn=False)#in the center point dimensional,P decrease to 1.
X_2 = pf.dense(X_1,K * K, tag + 'X_2', is_training, with_bn=False, activation=None)#(N, P, 1,K*K)
然后reshape成(P,K,K),这就得到了X-transporm矩阵。
X = tf.reshape(X_2,(N, P, K, K), name=tag + 'X')
与上文得到的特征图进行卷积相乘。
fts_X =tf.matmul(X, nn_fts_input, name=tag + 'fts_X')
最后是卷积操作,输出通道数为C,(1, K)尺度的卷积核用来把K邻域融合,此处有别于Pointnet++中的池化操作。
fts =pf.separable_conv2d(fts_X, C, tag + 'fts', is_training, (1, K),depth_multiplier=depth_multiplier)#输出(N, P, 1, C)
returntf.squeeze(fts, axis=2, name=tag + 'fts_3d')#输出(N, P, C)
注意这里用的不是普通卷积,而是可分卷积separable_conv2d。
关于“PointCNN原理是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“PointCNN原理是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注创新互联行业资讯频道。