因为相机正面白摄物体时,相机的光轴方向可能发生变化,带来扭曲。而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检测出特征点数目差别较大。