基于体素的3D目标检测网络:VoxelNet
VoxelNet: End-to-End Learning for Point Cloud Based 3D Object Detection
簡介
本項目基于PaddlePaddle框架復現了基于體素的3D目標檢測算法VoxelNet,在KITTI據集上進行了實驗。
項目提供預訓練模型和AiStudio在線體驗NoteBook。
背景
3D檢測廣泛用于自主導航、家政機器人以及AR/VR。LIDAR提供可靠的深度信息用于準確定位目標并表征其形狀。
現有方法
- 將LIDAR投影到某個視角作為輸入;
- 采用3D體素,提取人工設計的體素特征;
- 雖然有PointNet和Pointnet++這類點云學習網絡,但還無法處理大規模點云數據。
這篇文章利用網絡學習體素點特征,只使用點云實現了快速高效的3D目標檢測。
算法解釋
VoxelNet由三個功能塊組成:特征學習網絡、卷積中間層和區域候選網絡。下面一一介紹:
- 特征學習網絡
首先將三維點云劃分為一定數量的Voxel(就是將空間劃分為一個一個柵格,用格子表示格子里的點云)并對這些voxel進行分組,再經過點的隨機采樣(每個格子的最大點云采樣數量這里是T=35)以及歸一化后,對每一個非空Voxel使用若干個VFE(Voxel Feature Encoding)層進行局部特征提取,得到Voxel-wise Feature。這里的VFE模型其實就是FC全連接模型。最后的輸出形狀為128×10×400×352.
- 卷積中間層
為了聚合周圍環境voxels的信息,使用3D卷積對4D tensor進行卷積,并進行reshape到3D tensor。每個卷積中間層順序應用3D卷積、BN層和ReLU層。舉例:輸入尺寸(4D tensor)是128 × 10 × 400 × 352,輸出尺寸(經過Convolutional Middle Layers之后)是64 × 2 × 400 × 352,然后reshape到 128 × 400 × 352變成3D tensor(注意到128 × 400 × 352正是BEV視圖上的柵格尺寸)。
- 區域候選網絡
在提取到特征后,利用RPN模塊預測候選檢測框。如圖所示,該網絡包含三個全卷積層塊(Block),每個塊的第一層通過步長為2的卷積將特征圖采樣為一半,之后是三個步長為1的卷積層,每個卷積層都包含BN層和ReLU操作。將每一個塊的輸出都上采樣到一個固定的尺寸并串聯構造高分辨率的特征圖。最后,該特征圖通過兩種二維卷積被輸出到期望的學習目標:概率評分圖(Probability Score Map)和回歸圖(Regression Map)
- 損失函數
Probability Score Map的輸出通道是2,分別對應positive和negative的分數,Regression map輸出通道為14維,對于每個回歸的Bounding box都用7維來表示,也就是中心位置 、候選框的長寬高和航向角,另外兩個旋轉軸默認為0,原因是地面水平。同理,假設預測的anchor用小標a表示,因此可定義如下的殘差:
其中,是anchor框底部的對角線長度,采用的目的是用對角線齊次歸一化和。然后定義可以最終的損失函數:
損失函數前面兩項是正則化分類損失,其中和分別表示softmax層對正錨和負錨的分數,采用的是交叉熵表示,和為正定平衡系數。最后一項是回歸損失,和是正錨的回歸輸出和ground truth,采用的是Smooth L1損失。
詳細的參數設定需要查看論文才能更好理解~
論文:
- [1] Yin Zhou, Oncel Tuzel.
Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 2018. VoxelNet: End-to-End Learning for Point Cloud Based 3D Object Detection
博客參考:
- VoxelNet: End-to-End Learning for Point Cloud Based 3D Object Detection
- 【3D目標檢測】VoxelNet:End-to-End Learning for Point Cloud Based 3D Object Detection解讀
項目參考:
-
https://github.com/qianguih/voxelnet
github repo實現精度 easy: 53.43 moderate:48.78 hard:48.06
-
https://github.com/traveller59/second.pytorch
由于該論文并未提供開源的代碼,目前也找不到能夠復現其論文中指標的項目。
因此本項目根據參考項目(voxelnet-tensorflow)和該論文后續的算法改進版本(second)進行了復現。
復現精度
指標解釋:>機器學習算法評估指標——3D目標檢測
評價3D目標檢測結果的指標主要是3D AP 和Bev AP。其含義是當預測框與真值框的交并比(IOU)大于一定閾值時,認為預測框正確的數量與所有真值框的比例。
IOU即兩個框的相交范圍與并集范圍的比例。
在KITTI val數據集(50/50 split as paper)的測試效果如下表。
| VoxelNet | 160 | SGD | 0.0015 | 2 * 1(V100 card) | KITTI | config |
預訓練權重和日志:百度網盤 | AiStudio存儲
2、當將分類損失改為FocalLoss以及加入針對aos的direction分類損失時(后續實驗表明direction損失只對aos起作用,可不用)
| VoxelNet | 160 | SGD | 0.005 | 2 * 4 (V100 card) | KITTI | configFix |
預訓練權重和訓練日志:百度網盤 | AiStudio存儲
-
另外,論文中沒提及的細節,本項目均參考Second項目的實施。
-
倉庫內的log文件夾下存放有兩個訓練日志和可視化曲線日志。
開始
數據集解壓
約15分鐘.
%cd /home/aistudio/ !rm -rf kitti/ !mkdir -p kitti/training/velodyne_reduced !mkdir -p kitti/testing/velodyne_reduced !unzip data/data50186/data_object_calib.zip -d kitti/ !unzip data/data50186/image_training.zip -d kitti/training/ !unzip data/data50186/data_object_label_2.zip -d kitti/training/ !unzip data/data50186/velodyne_training_1.zip -d kitti/training/ !unzip data/data50186/velodyne_training_2.zip -d kitti//training/ !unzip data/data50186/velodyne_training_3.zip -d kitti/training/ !unzip data/data50186/image_testing.zip -d kitti/testing/ !unzip data/data50186/velodyne_testing_1.zip -d kitti/testing/ !unzip data/data50186/velodyne_testing_2.zip -d kitti/testing/ !unzip data/data50186/velodyne_testing_3.zip -d kitti/testing/ !mv kitti/training/training/* kitti/training/ !rm -rf kitti/training/training/ !mv kitti/testing/testing/* kitti/testing/ !rm -rf kitti/testing/testing/ !mkdir kitti/training/velodyne !mv kitti/training/velodyne_training_1/* kitti/training/velodyne/ !mv kitti/training/velodyne_training_2/* kitti/training/velodyne/ !mv kitti/training/velodyne_training_3/* kitti/training/velodyne/ !rm -rf kitti/training/velodyne_training_1 !rm -rf kitti/training/velodyne_training_2 !rm -rf kitti/training/velodyne_training_3 !mkdir kitti/testing/velodyne !mv kitti/testing/velodyne_testing_1/* kitti/testing/velodyne !mv kitti/testing/velodyne_testing_2/* kitti/testing/velodyne !mv kitti/testing/velodyne_testing_3/* kitti/testing/velodyne !rm -rf kitti/testing/velodyne_testing_1 !rm -rf kitti/testing/velodyne_testing_2 !rm -rf kitti/testing/velodyne_testing_3 !mv kitti data/至此,數據集的結構:
└── KITTI_DATASET_ROOT├── training <-- 7481 train data| ├── image_2 <-- for visualization| ├── calib| ├── label_2| ├── velodyne| └── velodyne_reduced <-- empty directory└── testing <-- 7580 test data├── image_2 <-- for visualization├── calib├── velodyne└── velodyne_reduced <-- empty directory3,712 data samples fortraining and 3,769 data samples for validation
安裝依賴
最適合的環境配置:
- python版本:3.7.4
- PaddlePaddle框架版本:2.2.1
- CUDA 版本: NVIDIA-SMI 450.51.06 Driver Version: 450.51.06 CUDA Version: 11.0 cuDNN:7.6
注意:
由于PaddlePaddle/cuDNN本身的BUG,CUDA 10.1版本當batch size > 2時會報如下錯誤:
因此單卡如果環境不是CUDA 11.0以上,config文件中batch size設置為2即可,后續通過訓練的accum_step參數開啟梯度累加起到增大bs的效果。設置accum_step=8即表示bs=16,并做相應config文件的初始學習率調整。
!pip install distro shapely pybind11 pillow fire memory_profiler psutil scikit-image==0.14.2 !pip install numpy==1.17.0 !pip install numba==0.48.0(由于Notebook不支持導入當前整個項目到Python環境,以下操作在終端命令行執行)
準備部分
1. 為numba設置cuda環境
export NUMBAPRO_CUDA_DRIVER=/usr/lib/x86_64-linux-gnu/libcuda.so export NUMBAPRO_NVVM=/usr/local/cuda/nvvm/lib64/libnvvm.so export NUMBAPRO_LIBDEVICE=/usr/local/cuda/nvvm/libdevice2. 將當前項目加到環境中
export PYTHONPATH=$PYTHONPATH:/home/aistudio/VoxelNet3. 數據預處理
從label中分類別抽取真值信息以及對點云進行降采樣。(約7分鐘)
cd /home/aistudio/VoxelNet/voxelnet/ python create_data.py create_kitti_info_file --data_path=/home/aistudio/data/kitti # Create kitti infos python create_data.py create_reduced_point_cloud --data_path=/home/aistudio/data/kitti # Create kitti reduced point python create_data.py create_groundtruth_database --data_path=/home/aistudio/data/kitti # Create kitti gt打印信息如下:
Generate info. this may take several minutes. Kitti info train file is saved to /home/aistudio/data/kitti/kitti_infos_train.pkl Kitti info val file is saved to /home/aistudio/data/kitti/kitti_infos_val.pkl Kitti info trainval file is saved to /home/aistudio/data/kitti/kitti_infos_trainval.pkl Kitti info test file is saved to /home/aistudio/data/kitti/kitti_infos_test.pkl [100.0%][===================>][40.86it/s][01:44>00:00] [100.0%][===================>][35.31it/s][01:47>00:00] [100.0%][===================>][39.13it/s][03:49>00:00] [100.0%][===================>][28.71it/s][01:53>00:00] load 14357 Car database infos load 2207 Pedestrian database infos load 734 Cyclist database infos load 1297 Van database infos load 56 Person_sitting database infos load 488 Truck database infos load 224 Tram database infos load 337 Misc database infos4. 修改配置文件
voxelnet/configs/car.configs
train_input_reader: {...database_sampler {database_info_path: "/home/aistudio/data/kitti/kitti_dbinfos_train.pkl"...}kitti_info_path: "/home/aistudio/data/kitti/kitti_infos_train.pkl"kitti_root_path: "/home/aistudio/data/kitti" } ... eval_input_reader: {...kitti_info_path: "/home/aistudio/data/kitti/kitti_infos_val.pkl"kitti_root_path: "/home/aistudio/data/kitti" }設置注意事項:
1、若訓練要開啟梯度累加選項,則:
- 學習率的decay_steps按照梯度累加后的batch size對應的總steps來設置。
- train_config.steps則按未梯度累加時對應的初始batch size對應的總steps來設置
2、 配置文件需放置于voxelnet/configs/***.py
快速開始
1. 訓練
訓練一個epoch, V100 16G大約15分鐘。顯存占用11G左右。
python ./pypaddle/train.py train --config_path=./configs/config.py --model_dir=./output2. 評估
V100 16G 大約5分鐘
python ./pypaddle/train.py evaluate --config_path=./configs/config.py --model_dir=./output --ckpt_path=./output/voxelnet-278400.ckpt3. 可視化預測
3D可視化需要GUI,Notebook環境不支持動態GUI調用顯示。需在本地測試。
詳細查看README.md。
4. 一個簡單的BEV視角可視化例子
為了方便查看預測結果,下面的cell提供了一個在notebook中查看二維bev視角的可視化例子,可以在notebook執行。
由于只保留了相機視角范圍內的結果(Points that are projectedoutside of image boundaries are removed(in Paper Section 3.1)),所以車身后面沒有檢測框。
結語
復現心得:
這篇論文在第四屆論文復現賽的時候我就進行了復現,并未成功,相差甚遠。由于論文沒有開源代碼,網絡上也沒有達到論文精度的項目,很難從頭開始自己全部重寫。于是我換了一個思路,既然這篇論文是非常經典的論文,后續肯定有人基于這個思路進行改進。果然找到了second。second這篇論文幾乎重現了voxelnet的所有方法(但據作者說并沒有完全復現原始的voxelnet),不過加入了稀疏卷積使得速度和精度得到了巨大提升。于是我的思路就變成了從second中去掉它改進的部分內容,使其復原原始的voxelnet,來減少自己重寫代碼的工作量。
由于之前第四屆比賽時的經驗,這次遇到的問題都不多,或者說當時已經遇到了,直接拿我當時的代碼進行替換,一個函數一個函數輸入輸出對齊測試即可。并且只需要對照X2Paddle進行對齊即可。
第四屆和這一次遇到的主要問題都是內存泄漏問題。不過這一次,找到了問題所在。
1.這里總結一下幾個常犯的內存泄漏錯誤原因。
- loss在用于取值打印或者用于其他計算時,沒有.detach()或者.numpy()
- 如果model本身內部要存一些每一次前向計算后的指標,指標一定也要在前向計算后detach再賦值到model內的變量(這是我找了超級久的泄漏問題)。
2.enisum函數。這個函數雖然paddle2.2提供了,但是還有bug。用的時候報錯了。
我在paddlenlp(https://github.com/PaddlePaddle/PaddleNLP/blob/develop/paddlenlp/ops/einsum.py)
中找到了可以正常使用的版本。
3.mask賦值。問題如下:
寫了一個mask(bool類型)的賦值函數:
相關信息:
| 作者 | xbchen |
| 日期 | 2021年1月 |
| 框架版本 | PaddlePaddle>=2.2.1 |
| 應用場景 | 3D目標檢測 |
| 硬件支持 | GPU |
| 在線體驗 | Notebook |
| 多卡腳本 | Shell |
引用
- Thanks for yan yan’s second.pytorch project.
總結
以上是生活随笔為你收集整理的基于体素的3D目标检测网络:VoxelNet的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 商号权的取得方式是什么
- 下一篇: acwing3红与黑