因爲相機正面白攝物體時,相機的光軸方向可能發生變化,帶來扭曲。而SIFT算法雖具備徹底的尺度不變性,但不具備徹底的仿射不變性,對拍攝角度發生大角度空間變化的圖像特徵提取有必定的侷限性。ASift經過模擬經度與緯度實現徹底的仿射不變,而後用SIFT算法把模擬圖像進行比較,最後實現特徵匹配。python
ASIFT算法的具體步驟以下:git
1.選取採樣參數,模擬不一樣經度與緯度的圖像。github
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.pyspa
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檢測出特徵點數目差別較大。