# 1.簡介
- 近來資訊科技進步,電腦視覺應用在生活隨處可見,更是在3D技術上。相機校準、圖像特徵檢測等方面能力都已具備,現在二維的效果無法再滿足人類需求,因此,三維重建成為我們專題的重點。
- 本專題以實現3D水族箱為主軸,透過機器學習來重建3D魚影像,利用DeepLabCut深度學習訓練工具,追蹤魚的運動行為,找出特徵點相對應之座標,並映射出來使其3D化,透過計算機來再現魚隻模型,並利用kalman filter演算法優化結果,進而呈現水族箱的樣貌。
- 環境
* Hardware:
- i5-9600KF
- RAM 64G
- NVIDIA GeForce RTX 2080
* Sofware:
- Ubuntu 20.04 or Windows 10
- Anaconda 2021.05
- DeepLabCut 2.2
- Tensorflow 2.6
# 2.理論推導
### DeepLabCut深度學習訓練
#### DeepLabCut deep learning training process
- DeepLabCut是由美國哈佛大學的Mackenzie Mathis、Matthias Bethge及同事利用機器學習開發的一款開源運動追蹤工具。DeepLabCut 利用了 Insafutdinov 等人提出的一種最先進的人體姿勢估計算法的特徵檢測器(ResNets + 讀出層),稱為 DeeperCut,啟發了工具箱的名稱,並添加了速度更快、性能更高的變體,包括 MobileNetV2s、EfficientNets 和自己的 DLCRNet 主幹,提高了推理速度,並提供了額外的新的增強方法,增加了實時性和多動物支持。為動物姿態估計提供最先進的性能。
- 2D
- 輸入欲訓練的動物圖片+標點
- 輸出2D的標點影片
- 3D -- DLC直接支持基於 2-camera 的 3D 姿態估計
- 輸入2D專案訓練出來的 DeepLabCut network model
- 輸入校準圖像
- 輸入成對動物影片
- 輸出3D的標點影片
### DeepLabCut 已標點資料合併作業
#### DeepLabCut labeled data combination process
- 因應疫情與設備造成的遠端協作模式,並考量標記資料的效率,隔一段時間就會將所有組員的2D標點影片合併成為一份資料集training dataset,完成後並接續後面作業。
### DeepLabCut 已訓練模組續訓練作業
#### DeepLabCut trained model retraining process
- 考量到視訊記憶體等硬體的限制,以1080p的影片而言,每次訓練的極限約在3000張標點資料左右。為了突破該限制,須沿用前一次訓練的結果到下一次的訓練當中,以達到接續訓練的效用。
### DeepLabCut 3D空間建構
#### DeepLabCut 3D process
- 固定兩攝影機間距,以多個不同角度與距離拍攝棋盤方格,對這些相片進行校準:計算每個相機的內在和外在參數,使用這些參數計算重投影誤差,估計兩個相機之間的轉換,並對相機進行立體校準。通過計算立體校正將兩相機圖像(棋盤方格)平面帶到同一平面。
使用相機矩陣對校準圖像(棋盤方格)和角點(方格角點)進行去畸變(undistortion),並將這些去畸變的點投影到去畸變的圖像上以檢查它們是否正確對齊,以檢查立體校正的效果。
如果沒有錯誤,便可以對來自兩個相機的姿勢進行三角測量以獲得 3D DeepLabCut 坐標。
## 魚眼估計
#### Fish Eye Estimation
- 用途
由於青萬隆體型結構上並不圓潤,若非正面面對鏡頭,通常取得的影像僅能包含一隻眼睛,而魚隻的行為難以控制,僅有少數片段能夠同時偵測到雙眼,此演算法便是為了改善此現象以利於實現3D化。
- 演算法 algotherm
已知a,b,c點位於同一平面A上,可得該平面A之點斜式及法向量。又一不在平面A上之點d,可得d對A之對稱點。基於上述概念,加上由於青萬隆脊椎的結構限制了擺動方向,使其水平方向擺動大於垂直方向,取魚嘴、魚腹鰭前緣、魚背鰭前緣分別可視為a,b,c點,由該三點可大致估量出魚頭的縱切面,並透過該平面可大致推導出另一側魚眼的位置。
## Kalman Filter
- 用途
因訓練部分可能有空值,或可能有偏離理想值太多的個別點,因此用kalman filter將極端雜訊平滑化,同時估計未測量/計算到的空值
- 演算法 algotherm
對某個時段k的估計值(k>=2),可以依時段k-1的濾波結果經線性運算得出,然後可依設定的比例,由時段k的估計值和時段k的測量值權衡,得出時段k的濾波結果。並以該結果進入下一循環。
若測量值為空(未測得),則取估計值為濾波結果。
# 3.架構與演算法則
## [Installation Config File](https://github.com/Yukimi27043816/DeepLabCut_files/tree/master/installation_config)
## 流程圖

# 4.模組設計描述 (Module Description)
## 檔案架構
- Labeling/Training Project
- *project Folder*/
- dlc-models/
: 模組/訓練參數存放區
- ...
- train/
- pose_cfg.yaml
~ 訓練參數檔案
- snapshot-*
~ 已訓練模組檔案
- evaluation-results/
: 模組誤差結果存放區
- labeled-data/
: 標點資料存放區
- *video_name*/
~ 從影片擷取出的frame
- *video_name*_labeled/
~ 標點結果預覽
- training-datasets/
: 訓練資料存放區
- videos/
: 訓練影片存放區
- *video_name*
~ 訓練影片
- config.yaml
: 全域設定檔案
- 3D Project
- *project Folder*/
- calibration_images/
: 3D建構用棋盤格圖片存放區
- corners/
: 棋盤格點資料圖片存放區
- undistortion/
: 3D失真估計資料存放區
- config.yaml
: 全域設定檔案
- *video folder*
: 待標點影片、標點資料、結果影片存放區
## 重要設定參數
- config.yaml(2D)
- Project path `專案路徑`
- video_sets `影片路徑及切割資料`
:::info
影片路徑包含 *video name/影片名稱*
:::
- bodyparts `座標點名稱`
- numframes2pick `切割幀數`
- skeleton `骨架`
- default_net_type `預設網路模型`
- pose_cfg.yaml
- batch_size `tensorflow資料集分割大小`
:::info
大幅度影響training速度,但依硬體、影片大小、資料集大小影響最大值
:::
- dataset `訓練/測試資料集路徑`
- init_weights `初始訓練權重路徑`
:::info
retraining的重點
:::
- net_type `網路模型種類`
- config.yaml(3D)
- Project path `專案路徑`
- skeleton `自定義骨架顯示資料`
- num_cameras `攝影機數目`
- camera_names `自定義攝影機名稱`
- scorername_3d `3D專案負責人`
- trainingsetindex_***camera_names*** `訓練資料集編號`
:::info
***camera_names***部分需與上述camera_names同步
:::
- config_file_***camera_names***
`訓練用專案(training project)全域設定檔案路徑`
:::info
***camera_names***部分需與上述camera_names同步
:::
## 函式說明
- 2D
- create_new_project(project,experimenter,videos,working_directory=None,copy_videos=False,videotype=".avi",multianimal=False)
- important parameter
project : string `專案名稱`
experimenter : string `專案負責人`
videos : list `標點影片的路徑集合`
videotype : string `標點影片的副檔名`
working_directory : string, optional `專案路徑(可選)`
copy_videos : bool, optional `複製影片or創建捷徑(可選)`
- 用途
創建一個新的2D專案,自動創造專案架構及全域設定檔案
- extract_frames(config_path)
- important parameter
config_path : string `全域設定檔案路徑`
- 用途
用設定檔案的參數切割標點用的frames
- label_frames(config_path)
- important parameter
config_path : string `全域設定檔案路徑`
- 用途
開啟標點用的GUI
- check_labels(config_path, visualizeindividuals=True)
- important parameter
config_path : string `全域設定檔案路徑`
visualizeindividuals : bool `預覽標點`
- 用途
確認標點資料的正確性+預覽已標的點
- create_training_dataset(config_path)
- important parameter
config_path : string `全域設定檔案路徑`
- 用途
用已標的點資料作出train/test的資料集
- train_network(config_path, displayiters=100, saveiters=15000, maxiters=30000)
- important parameter
config_path : string `全域設定檔案路徑`
displayiters : integer `Terminal顯示的訓練週期`
saveiters : integer `snapshot存檔的訓練週期`
maxiters : integer `最大訓練週期值`
- 用途
將資料集以機器學習之方式訓練出模組
- evaluate_network(config_path, plotting=True)
- important parameter
config_path : string `全域設定檔案路徑`
plotting : bool `是否以圖像顯示誤差`
- 用途
估量現有模組的成效(誤差值)
- 3D
- create_new_project_3d(project, experimenter, num_cameras=2, working_directory=None)
- important parameter
project : string `專案名稱`
experimenter : string `專案負責人`
num_cameras : integer `攝影機數量`
working_directory : string, optional `專案路徑(可選)`
- 用途
創建一個新的3D專案,自動創造專案架構及全域設定檔案
- calibrate_cameras(config, cbrow=8, cbcol=6, calibrate=False, alpha=0.4)
- important parameter
config : string `全域設定檔案路徑`
cbrow, cbcol : int `棋盤格的行列數`
calibrate : bool `是否執行校正`
- 用途
執行3D校正,若calibrate為False,則將辨識出的棋盤格點描繪在corner資料夾內以調整校正建構用圖片;若為True則產出校正檔案
- check_undistortion(config, cbrow=8, cbcol=6, plot=True)
- important parameter
config : string `全域設定檔案路徑`
cbrow, cbcol : int `棋盤格的行列數`
plot : bool `是否描繪失真結果`
- 用途
確認上一步建構空間的失真程度
- triangulate(config,video_path,videotype="avi",destfolder=None,save_as_csv=False)
- important parameter
config : string `全域設定檔案路徑`
video_path : list of list or string `辨識影片的資料夾或全路徑`
videotype : string `標點影片的副檔名`
destfolder : string, optional `儲放結果的資料夾(可選)`
save_as_csv : bool, optional `是否將結果以csv檔案儲存(可選)`
- 用途
使用全域設定檔案中所定義的2D專案,對影片進行辨識,並建立三維的辨識結果
- create_labeled_video_3d(config,path,videofolder=None,start=0,end=None,videotype="avi",view=[-113, -270],xlim=[None, None],ylim=[None, None],zlim=[None, None])
- important parameter
config : string `全域設定檔案路徑`
path : list `辨識結果的資料夾路徑`
videofolder : string `儲放3D影片的位置`
videotype : string `標點影片的副檔名`
view : list `觀看結果的角度`
xlim, ylim, zlim : list `三維邊界值`
- 用途
將三維辨識結果以轉換成影片並輸出
- extend tools
- apply_kalman_filter(h5_file_path)
- important parameter
h5_file_path : string `h5辨識點檔案路徑`
- 用途
在辨識點的資料當中套用Kalman Filter
- estimate_opposite_eyes(h5_file_path)
- important parameter
h5_file_path : string `h5辨識點檔案路徑`
- 用途
估量未辨識的魚眼
# 5.實驗結果(Experimental, Simulation Results)
客觀描述實驗結果觀察
# 6.討論(Discussions)
主觀提出結果的看法
# 7.結論(Conclusions)
摘要與未來展望?
我們專題以3D水族箱來發想,透過各種的演算法及工具,來完成這次主題,這次內容接觸到了3D技術上的一些技術,像是相機校準、圖像特徵檢測等等..............(一些最終作品的??????),通過這些我們了解到3D一些基礎的做法,有機會的話,再更進一步研究3D投影相關技術來延伸創作,是不是又能達到不同的效果,間接再學習3D列印技術,把成果化為實品,未來可發展性非常廣,結合不同類型的技術,打造不同的成果。
附件 (Appendices): Source Codes
參考書籍 (References)
-----------
---------
### DeepLabCut 已標點資料合併作業
#### DeepLabCut labeled data combination process
1. 複製labeling project的labeled-data資料夾與videos資料夾至training project的專案目錄。
2. 將labeling project中,config.yaml的video_sets部分複製至training project的config.yaml。
3. 使用check_labels(config_path, visualizeindividuals)確認是否成功。
4. 執行training project的create_training_dataset(config_path)建立訓練資料集。
- 例外狀況
重新命名影片排除影片重名問題,使用convertcsv2h5(config,scorer)重建h5檔案。
### DeepLabCut 已訓練模組續訓練作業
#### DeepLabCut trained model retraining process
1. 從已訓練專案的project Folder/dlc-models/.../train/路徑找到以下檔案:
- snapshot-*XXX*.data *???*-of-*???*
- snapshot-*XXX*.index
- snapshot-*XXX*.meta
- *XXX* 是最後一次model快照的iteration,*???*為不特定數字。
1. 從待訓練專案的project Folder/dlc-models/.../train/路徑找到pose_cfg.yaml
1. 以步驟一檔案的絕對路徑,刪去附檔名後替換待訓練project中pose_cfg.yaml的init_weight值
- ex:
如果已訓練專案中有iteration 50000的快照,存在於
*/home/user/A-test-2021-01-01/dlc-models/iteration-0/AJan1-trainset95shuffle1/train/*,其名稱應類似於
- snapshot-50000.data-00000-of-00001
- snapshot-50000.index
- snapshot-50000.meta
則待訓練專案之init_weights應被替換成
/home/user/A-test-2021-01-01/dlc-models/iteration-0/AJan1-trainset95shuffle1/train/snapshot-50000
1. 將待訓練專案重新執行train_network(config_path, displayiters=100, saveiters=15000, maxiters=30000)訓練。
- convertcsv2h5(config,scorer)
- important parameter
config_path : string `全域設定檔案路徑`
scorer : string `新專案負責人`
- 用途
以csv檔案重新建立h5檔