由於相機正面白攝物體時,相機的光軸方向可能發生變化,帶來扭曲。而SIFT演算法雖具有完全的尺度不變性,但不具有完全的仿射不變性,對拍攝角度發生大角度空間變化的影象特徵提取有一定的侷限性。ASift通過模擬經度與緯度實現完全的仿射不變,然後用SIFT演算法把模擬影象進行比較,最後實現特徵匹配。
ASIFT演算法的具體步驟如下:
1.選取取樣引數,模擬不同經度與緯度的影象。
2.計算模擬影象的特徵。
3.結合所有的模擬影象的特徵,進行特徵匹配。
注意:ASIFT提供的一種框架,其核心思想是模擬不同的經度與緯度的影象,具體模擬影象的特徵提取和匹配,可選擇SIFT、SURF等特徵。
ASIFT演算法程式碼資源:
http://www.ipol.im/pub/art/2011/my-asift/
https://github.com/Itseez/opencv/blob/master/samples/python2/asift.py
OpenCV只提供python實現的asift,如果需要在C++中使用asift,主要有兩種方法可參考。
1.利用作者提供的C++程式碼,具體使用方法可參考作者提供的文件。
2.將asift.py翻譯成C++程式碼。
asift.py程式碼相對清晰,轉換成基於OpenCV的C++程式碼比較容易,我主要參用方法2,實現ASIFT演算法。
遇到的問題:
1.處理解析度較大圖片時,出現OpenCV Error: Insufficient memory的錯誤。
經分析,計算過程需要儲存多張模擬圖片的特徵點和特徵描述子,需要大量記憶體,導致OpenCV分配記憶體時,沒有連續可用的記憶體塊,從而出現OpenCV Error: Insufficient memory的錯誤。
解決方法:降低待處理圖片的解析度,並計算高解析度到低解析度轉換的單應性矩陣scaleH。利用ASift演算法計算低解析度圖片的匹配的單應性矩陣matchH。最終待處理圖片的單應矩陣H=matchH*scaleH。
2.計算複雜度問題。
由於需要處理多幅模擬圖片的特徵點檢測,計算複雜度高。目前,主要有兩種思路:1).降低解析度,減少計算量。2).利用硬體特性進行硬體計算。
ASift作者在文中提到的Two-Resolution Procedure.
(1).採用係數K*K二次取樣查詢圖片u和待搜尋圖片v。u = SkGku,v=SkGkv,Gk是反走樣高斯離散濾波器,SK為K*K二次取樣。
(2).低解析度下的ASIFT演算法:對查詢圖片u和搜尋圖片應用ASIFT演算法;
(3).確定u和v中可能產最多匹配對的M種仿射變換;
(4).高解析度下的ASIFT演算法:在原始影象u和v上使用ASIFT演算法,但模擬傾科時只使用這M種仿射變換。
經實驗測試,發現Two-Resolution Procedure雖然可以在一定降低複雜度,但其對匹配精度會有一定的影響,對於匹配精度要求高的應用不太合適。
Asift.py中,利用執行緒池加速多幅影象的特徵點檢測,使得多幅影象的特徵點檢測同時進行。
結合多執行緒的思想,我利用每個執行緒,計算每幅影象的特徵點的檢測,結果遇到記憶體不足的問題。
主要原因:特徵點檢測過程需要記憶體空間儲存部分中間結果,當多執行緒同時計算時,所需記憶體增大,出現記憶體不足的問題。
解決方法:可以根據待處理圖片的解析度大小和系統提供記憶體資源的多少,自適應確定多執行緒的數目。
利用GPU加速ASIFT計算,具體步驟如下:
(1).將待處理圖片傳輸到GPU端。
(2).將待處理圖片模擬變換,得到模擬圖片,AffineImage_Kernel。
(3).計算模擬圖片的特徵點,KeyPointsDetect_Kernel。
(4).將計算所得的特徵點資料傳輸到CPU端。
(5).迴圈處理(2)、(3)、(4)步驟,直到所有模擬變換處理完。
(6).在CPU端完成特徵點匹配計算。
注意:(4)與(5)可以非同步執行,重疊計算與特徵點資料傳輸的時間。
基於GPU特徵點計算主要參考:
SiftGPU: http://cs.unc.edu/~ccwu/siftgpu/
CudaSift: https://github.com/Celebrandil/CudaSift
注意:經測試,發現SiftGPU和CudaSift檢測出的特徵點數目與OpenCV的SiftFeatureDetector檢測出特徵點數目差異較大。