您好,登錄后才能下訂單哦!
這篇文章主要介紹了PointCNN原理是什么的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇PointCNN原理是什么文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。
PointCNN的動(dòng)機(jī)是這樣的:
圖中,小寫字母f表示該點(diǎn)的特征,腳標(biāo)相同的f表示對(duì)應(yīng)點(diǎn)的特征也相同,作者告訴我們,圖里有兩個(gè)問(wèn)題存在:
首先,假設(shè)一種情形,圖ii和圖iii是兩種物體,但是,我們按照一定順序排列,得到特征序列(fa,fb,fc,fd),碰巧這兩個(gè)物體的特征還都一樣,所以,這兩種原本不同的物體,就被判定為同一種物體了。其次,另一種情形,圖iii和圖iv,從形狀來(lái)看,本來(lái)是同一種物體,但是由于順序選取不恰當(dāng),圖iii的特征序列是(fa,fb,fc,fd),而圖iv是(fc,fa,fb,fd),這就不好意思了,你倆不一樣。
作者就覺(jué)得,這兩種問(wèn)題不解決,點(diǎn)云識(shí)別就做不好。所以,他想了個(gè)辦法,訓(xùn)練一種變換,經(jīng)過(guò)變換之后,讓ii和iii的特征不同,讓iii和iv的特征相同。這種變換怎么得到呢?用深度網(wǎng)絡(luò)訓(xùn)練。作者將其命名為X-transformation。
接著,作者又再想了,圖像處理領(lǐng)域的卷積操作,是對(duì)領(lǐng)域進(jìn)行的,那在點(diǎn)云里,也可以使用這種思路啊,只要先找好領(lǐng)域就行了。最后就是這么實(shí)現(xiàn)的。
下面是代碼部分:
P.S.作者的Github維護(hù)的很好,經(jīng)常更新,而且對(duì)讀者的答疑也很及時(shí),大贊。
看過(guò)代碼的同學(xué)都知道,作者的核心思想X變換在代碼pointcnn.py的xconv中,根據(jù)算法流程,可以把這部分代碼劃分成‘特征提取’和‘X矩陣訓(xùn)練’兩塊。下面分開(kāi)來(lái)說(shuō)。
用于提取鄰域特征的只有兩個(gè)dense層(也叫fc層/MLP),很簡(jiǎn)單地將尺度為(P,K,C)的鄰域結(jié)構(gòu)升維到了(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')
接下來(lái)作者沒(méi)有使用pointnet中的maxpooling,這一點(diǎn)論文中也提到了,因?yàn)樽髡哒J(rèn)為訓(xùn)練出一個(gè)X變換來(lái)能達(dá)到更好的效果。
而關(guān)于X變換,居然有三層,第一層是卷積層,讓人很吃驚,卷積核是1*k的,也就是在鄰域維度上,直接把k個(gè)鄰域點(diǎn)匯聚到一個(gè)點(diǎn)上,且用了K×K個(gè)卷積層,把特征維度升高到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')
緊接著,作者用了兩個(gè)dense層,保持了這個(gè)結(jié)構(gòu)
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')
與上文得到的特征圖進(jìn)行卷積相乘。
fts_X =tf.matmul(X, nn_fts_input, name=tag + 'fts_X')
最后是卷積操作,輸出通道數(shù)為C,(1, K)尺度的卷積核用來(lái)把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。
關(guān)于“PointCNN原理是什么”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“PointCNN原理是什么”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。