日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Pointnet网络结构与代码解读

發布時間:2023/12/16 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Pointnet网络结构与代码解读 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

Pointnet開創性地將深度學習直接用于三維點云任務。由于點云數據的無序性,無法直接對原始點云使用卷積等操作。Pointnet提出對稱函數來解決點的無序性問題,設計了能夠進行分類和分割任務的網絡結構,本文結合源碼與個人的理解對于T-net網絡和對稱函數進行分析。

點的無序性

針對點的無序性問題實際上是文章提出了三個方案:

  • 對于無序點集進行排序(Pointcnn)。
  • 把點集當做序列進行處理,但是這種方法需要對輸入點集做所有的排列變換進行數據增強。
  • 使用對稱函數,Pointnet使用的就是這種方法。

Pointnet網絡主要使用對稱函數解決點的無序性問題,對稱函數就是指對輸入順序不敏感的函數。如加法、點乘、max pooling等操作。假設輸入特征為NxD,NNN表示點數,DDD表示維度數,在max pooling作用下,取出每個維度上最大值的1xD的向量,每一維特征都與其順序無關,這樣便保證了對于點云輸入順序的魯棒性。

點云的旋轉不變性

Pointnet的解決方法是學習一個變換矩陣TTT,即T?NetT-NetT?Net結構。由于loss的約束,使得TTT矩陣訓練會學習到最有利于最終分類的變換,如把點云旋轉到正面。論文的架構中,分別在輸入數據后和第一層特征中使用了TTT矩陣,大小為3x3和64x64。其中第二個T矩陣由于參數過多,考慮添加正則項,使其接近于正交矩陣,減少點云的信息丟失。

1. T-Net網絡結構

將輸入的點云數據作為nx3x1單通道圖像,接三次卷積和一次池化后,再reshape為1024個節點,然后接兩層全連接,網絡除最后一層外都使用了ReLU激活函數和批標準化(batch normalization)。

論文中的T-net網絡的實際結構并不復雜,我根據個人理解畫出T-net的結構。

實際訓練過程中,T矩陣的參數初始化使用單位矩陣(np.eye(K)), 參數會隨著整個網絡的訓練進行更新,并不是提前單獨訓練的。很多文章提到T-Net對特征進行對齊,保證了模型的對特定空間轉換的不變性,我其實不太理解這種說法。

實際上通過網絡結構看出T-net結構是一個mini的Pointnet做特征提取,是個弱監督學習設計,我理解為需要訓練一個矩陣對輸入點(或者深層特征)進行坐標變換,個人認為這樣的設計實際上是可以保留原始點云的部分特征,為后面的concat操作提供更多特征。源碼中在點云分類部分使用到了T?netT-netT?net,點云分割部分可以不用,對結果并沒有太大的提升,原因在于pointnet結構自身不能學到點云點的局部聯系,因此即使加入類似結構的T-net也是一樣。

  • models/transform_nets.py中的網絡實現
def input_transform_net(point_cloud, is_training, bn_decay=None, K=3):""" Input: BxNx3 B=batch size;N=number of pointcloudOutput: 3x3 matrix"""batch_size = point_cloud.get_shape()[0].valuenum_point = point_cloud.get_shape()[1].valueinput_image = tf.expand_dims(point_cloud, -1) # 擴展一維表示通道C,BxNx3x1# 輸入BxNx3x1# 64個1x3卷積核 (參數[1,3]定義)# 移動步長 1x1 (stride=[1,1]定義)# 輸出 BxNx1x64net = tf_util.conv2d(input_image, 64, [1,3],padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='tconv1', bn_decay=bn_decay)# 輸入 BxNx1x64# 128個 1x1 卷積核# 步長 1x1# 輸出 BxNx1x128net = tf_util.conv2d(net, 128, [1,1],padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='tconv2', bn_decay=bn_decay)# 輸入 BxNx1x128# 1024個 1x1卷積核# 輸出 BxNx1x1024net = tf_util.conv2d(net, 1024, [1,1],padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='tconv3', bn_decay=bn_decay)# 池化操作# 輸入 BxNx1x1024# 輸出 Bx1x1x1024net = tf_util.max_pool2d(net, [num_point,1],padding='VALID', scope='tmaxpool')# 輸出 Bx1024net = tf.reshape(net, [batch_size, -1])# 全連接層# 輸入 Bx1024# 權重矩陣 1024x512# 偏置 512x1# 輸出 Bx512net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training,scope='tfc1', bn_decay=bn_decay)# 全連接# 輸出 Bx256net = tf_util.fully_connected(net, 256, bn=True, is_training=is_training,scope='tfc2', bn_decay=bn_decay)# 再次使用全連接,不加ReLU和BN# 輸出 Bx9with tf.variable_scope('transform_XYZ') as sc:assert(K==3)weights = tf.get_variable('weights', [256, 3*K],initializer=tf.constant_initializer(0.0),dtype=tf.float32)biases = tf.get_variable('biases', [3*K],initializer=tf.constant_initializer(0.0),dtype=tf.float32)#初始化為3x3單位矩陣biases += tf.constant([1,0,0,0,1,0,0,0,1], dtype=tf.float32)transform = tf.matmul(net, weights)transform = tf.nn.bias_add(transform, biases)# reshape# 輸出 Bx3x3transform = tf.reshape(transform, [batch_size, 3, K])return transform

針對64x64的網絡設計與3x3的一樣,只是改變了K值,對于文章提到讓特征轉化矩陣接近正交化,這樣特征損失更小,這部分的實現是在分類任務對損失函數加入正則項,及添加權重reg_weight=0.001,下文分析中會標出。

2. 點云分類部分

這部分主要分析訓練代碼和點云分類模型的設計

  • train.py
# 參數輸入處理 parser = argparse.ArgumentParser() parser.add_argument('--gpu', type=int, default=0,help='GPU to use [default: GPU 0]') parser.add_argument('--model', default='pointnet_cls',help='Model name: pointnet_cls or pointnet_cls_basic [default: pointnet_cls]') parser.add_argument('--log_dir', default='log', help='Log dir [default: log]') parser.add_argument('--num_point', type=int, default=1024,help='Point Number [256/512/1024/2048] [default: 1024]') parser.add_argument('--max_epoch', type=int, default=250,help='Epoch to run [default: 250]') parser.add_argument('--batch_size', type=int, default=32,help='Batch Size during training [default: 32]') parser.add_argument('--learning_rate', type=float, default=0.001,help='Initial learning rate [default: 0.001]') parser.add_argument('--momentum', type=float, default=0.9,help='Initial learning rate [default: 0.9]') parser.add_argument('--optimizer', default='adam',help='adam or momentum [default: adam]') parser.add_argument('--decay_step', type=int, default=200000,help='Decay step for lr decay [default: 200000]') parser.add_argument('--decay_rate', type=float, default=0.7,help='Decay rate for lr decay [default: 0.8]') FLAGS = parser.parse_args() BATCH_SIZE = FLAGS.batch_size # 訓練批次大小 NUM_POINT = FLAGS.num_point # 訓練點云點個數 MAX_EPOCH = FLAGS.max_epoch # 最大訓練次數 BASE_LEARNING_RATE = FLAGS.learning_rate # 初始學習率 GPU_INDEX = FLAGS.gpu # 默認GPU使用數量 MOMENTUM = FLAGS.momentum # 初始學習率 OPTIMIZER = FLAGS.optimizer # 優化器 DECAY_STEP = FLAGS.decay_step # 衰變步長 DECAY_RATE = FLAGS.decay_rate # 衰變率# some code ... # 獲取模型 pred, end_points = MODEL.get_model(pointclouds_pl, is_training_pl, bn_decay=bn_decay)

原始點云nx3與T-Net訓練后得到的3x3旋轉矩陣相乘后,可以理解為變換為一組新的坐標下的點云數據。

  • models/pointnet_cls.py中的代碼
# 1.原始點云與3x3的T變換矩陣 with tf.variable_scope('transform_net1') as sc:transform = input_transform_net(point_cloud, is_training, bn_decay, K=3) point_cloud_transformed = tf.matmul(point_cloud, transform) input_image = tf.expand_dims(point_cloud_transformed, -1)# 2.mlp(64,64):使用2次卷積 # 輸入 Bxnx3x1 # 64個1x3卷積核 # 輸出 Bxnx1x64 net = tf_util.conv2d(input_image, 64, [1,3],padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='conv1', bn_decay=bn_decay) # 輸入 Bxnx1x64 # 輸出 Bxnx1x64 net = tf_util.conv2d(net, 64, [1,1],padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='conv2', bn_decay=bn_decay)# 3.接64x64特征轉換矩陣 with tf.variable_scope('transform_net2') as sc:transform = feature_transform_net(net, is_training, bn_decay, K=64) end_points['transform'] = transform # 將上一步的net Bxnx1x64壓縮為 Bxnx64 和 T-Net的Bx64x64 相乘 net_transformed = tf.matmul(tf.squeeze(net, axis=[2]), transform)# 4.接3次卷積和1次池化,對應圖中的mlp(64,128,1024)+maxpool pointnet_cls.py # Bxnx64 擴展為 Bxnx1x64 net_transformed = tf.expand_dims(net_transformed, [2])# 輸入 Bxnx1x64 # 使用64個1x1卷積核 # 輸出 Bxnx1x64 net = tf_util.conv2d(net_transformed, 64, [1,1],padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='conv3', bn_decay=bn_decay) # 輸入 Bxnx1x64 # 使用128個1x1卷積核 # 輸出 Bxnx1x128 net = tf_util.conv2d(net, 128, [1,1],padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='conv4', bn_decay=bn_decay) # 輸入 Bxnx1x128 # 使用1024個1x1卷積核 # 輸出 Bxnx1x1024 net = tf_util.conv2d(net, 1024, [1,1],padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='conv5', bn_decay=bn_decay)# Symmetric function: max pooling # 輸入 Bxnx1x1024 # 輸出 Bx1x1x1024 net = tf_util.max_pool2d(net, [num_point,1],padding='VALID', scope='maxpool') # 輸出 Bx1024 net = tf.reshape(net, [batch_size, -1]) # 5.全連接1 + dropout # 輸出 batch_size x 512 net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training,scope='fc1', bn_decay=bn_decay) net = tf_util.dropout(net, keep_prob=0.7, is_training=is_training,scope='dp1') # 全連接2 + dropout # 輸出 batch_size x 256 net = tf_util.fully_connected(net, 256, bn=True, is_training=is_training,scope='fc2', bn_decay=bn_decay) net = tf_util.dropout(net, keep_prob=0.7, is_training=is_training,scope='dp2') # 全連接3 # 輸出 batch_size x 40,因為ModelNet數據集有40個類別的模型 net = tf_util.fully_connected(net, 40, activation_fn=None, scope='fc3') return net, end_points# 6.使用交叉熵損失函數計算loss,對網絡結構進行訓練。 def get_loss(pred, label, end_points, reg_weight=0.001):""" 預測值pred: B*NUM_CLASSES,標簽值label: B, """loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=pred, labels=label)classify_loss = tf.reduce_mean(loss)tf.summary.scalar('classify loss', classify_loss)# Enforce the transformation as orthogonal matrixtransform = end_points['transform'] # BxKxKK = transform.get_shape()[1].valuemat_diff = tf.matmul(transform, tf.transpose(transform, perm=[0,2,1]))mat_diff -= tf.constant(np.eye(K), dtype=tf.float32)mat_diff_loss = tf.nn.l2_loss(mat_diff) tf.summary.scalar('mat loss', mat_diff_loss)#這里加入了reg_weight正則項,使得T-net部分獲得的特征轉移矩陣更接近與正交化return classify_loss + mat_diff_loss * reg_weight# 模型優化器選擇:adam # 學習率初始值:0.001 # 動量=0.9 # batch_size =32 # 學習率每訓練20個epochs后減半 # GTX1080 ModelNet 需要3-6小時

對于pointnet_cls_basic.py沒有使用T-net的點云分類,網絡結構更容易理解,比加入T-net的結構性能略低。

3. 點云分割部分

  • 點之間的相關性問題

針對與分割物體上的問題與分類任務不同,分類任務中特征經過max pooling得到一維特征向量,它包含了全局信息,再經過全連接網絡,得到1*K的k個類別預測得分即為分類結果。而分割任務中,需要對每一個點輸出所屬類別,使用類似二維圖像分割的上采樣過程(跳步連接skip-links)。Pointnet針對分割任務也使用了類似圖像分割任務的,高層全局信息與底層局部特征結合的思想。

針對Pointnet論文作者提供的版本(Tensorflow)的源碼如下:https://github.com/charlesq34/pointnet

對于pointnet源碼其余部分的介紹不詳細展開,根據個人理解將源碼的結構與功能設計展示如下:

分割部分的代碼實現主要在part_seg/(部件分割)和sem_seg/(場景分割)下。其中part_seg中底層局部特征與高層全局特征的連接**(concat)使用到了各層特征**。

sem_seg/model.py場景分割中需要注意論文使用的S3DIS數據維度不再是3維而是更高的9維度(XYZ+RGB+相對于房間的標準化后的位置信息),針對特征連接部分使用高層全局特征(B*1024)接全連接降維到128,然后與高維特征自身做concat,不是采用論文中提到的方式。

而論文中提到的分割結構實際是在models/pointnet_seg.py中實現,即max pooling后的1D特征向量,使用tf.tile()復制n份(n個特征點),與之前網絡得到的 n * 64特征矩陣分別concat。得到一個n(64+D)的特征矩陣,再經一系列的特征變換操作,得到每個點的分類結果。

結語

本文主要結合代碼層面總結了pointnet網絡的分類和分割任務的實現。主要是理解pointnet是如何做到直接從原始點云數據中提取高維特征,并且解決好點云的特性。實際上基于pointnet結構可以進行很多任務,比如點云配準,物體檢測,3D重建,法向量估計等,只需要根據具體任務合理修改網絡后幾層的結構,利用好網絡提取的高維特征。

針對pointnet存在的點與點之間相關性的缺失,在pointnet++中使用局部采樣+分組+pointnet的結構進行解決,并考慮到了點云的稀疏性解決方案,之后很多深度學習的研究在此基礎上展開,習慣上稱為pointnet家族(point-wise MLP),比如Frustum,flowNet 3D,LSAnet,PAT等等。個人認為更高的準確度需要點云等3D數據與圖像結合進行深度學習訓練,將圖像的高分辨率優勢借鑒進來會有更好的效果。

源碼地址:
1.原論文實現代碼
https://github.com/charlesq34/pointnet
2.基于pytorch實現:
https://github.com/fxia22/pointnet.pytorch
https://github.com/yanx27/Pointnet_Pointnet2_pytorch

放上自己在谷歌的Colab上的gpu實現:在Colab上實現分類和Part_seg,選擇GPU版本的Notebook,
掛載好自己的谷歌云盤(方便保存和加載訓練數據),batch_size設置為32,數據集使用別人共享的Shapenet的數據集。
對于語義分割部分colab上的免費gpu滿足不了,需要購買更高版本的配置。

總結

以上是生活随笔為你收集整理的Pointnet网络结构与代码解读的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国模小丫大尺度啪啪人体 | 久久精品视频91 | 69精品久久久久久久 | jizzjizz日本免费视频 | 色爱av| 特级黄毛片 | 久久久久久9999 | 黄视频在线免费看 | 精品无码成人久久久久久免费 | 亚洲熟伦熟女新五十路熟妇 | 日批视频免费在线观看 | 免费av看 | 欧美福利片在线观看 | 成人av免费在线播放 | 肥臀浪妇太爽了快点再快点 | 日本黄色成人 | 黄色大片免费观看视频 | 黑人爱爱视频 | 久久国产这里只有精品 | 91亚洲精品乱码久久久久久蜜桃 | 成人黄色在线看 | 天堂а√在线最新版中文在线 | а天堂中文在线官网 | 午夜av毛片 | 日韩中文字幕一区二区三区四区 | 青青草欧美 | 999国产视频 | 伊人视频| 最新免费黄色网址 | 秋霞一区二区三区 | 日韩aaaaa| 欧美日韩久久 | 欧美人与动牲交xxxxbbbb | 台湾av在线 | 最新地址在线观看 | 华人在线视频 | 亚洲AV无码成人精品区先锋 | 亚洲无吗av | 日本人的性生活视频 | 91精品综合久久久久久五月天 | 日本国产在线 | 青青成人网| 亚洲a级精品| 国产一区二区三区免费播放 | 欧美精品性视频 | 91在线免费观看网站 | 不卡的av网站 | 性视频久久 | 欧美与黑人午夜性猛交久久久 | 国产精品久久久久一区二区 | 妺妺窝人体色www在线小说 | 国产校园春色 | 在线中文字幕网站 | 欧美熟妇激情一区二区三区 | 亚洲国产中文字幕 | 久久久午夜 | 国产www免费观看 | 九月婷婷色| 黄色大片黄色大片 | 超碰2025 | 国产精品久久久久久久一区二区 | 久久这里只有精品首页 | 精品电影在线观看 | 精品国产网 | 亚洲国产丝袜 | 亚洲第一国产 | 久久久ww| 久久精品黄aa片一区二区三区 | 亚洲国产精品久久人人爱 | 永久免费在线观看视频 | 午夜视频在线网站 | 另类在线视频 | 97人妻人人揉人人躁人人 | 久久久久久视 | 青娱乐在线播放 | 国产美女av在线 | 强迫凌虐淫辱の牝奴在线观看 | 亚洲成人麻豆 | 美女性生活视频 | 337p亚洲精品色噜噜狠狠 | 五月天校园春色 | 大尺度网站在线观看 | 国产视频一区二区三区在线播放 | 久久精品99国产精品日本 | 日本在线视频免费 | aaaa毛片| 成人av综合网 | 亚洲青春草 | 天堂网站 | 日韩精品一区二区三区网站 | 蜜臀99久久精品久久久久小说 | 情欲超| 男人天堂伊人 | 国产乱码精品一区二区三区亚洲人 | 天天综合国产 | 国产白浆在线 | 麻豆小视频 | av88av| 在线观看黄色片 |