opencv python SIFT(尺度不变特征变换)
Introduction to SIFT (Scale-Invariant Feature Transform)
理论
前面讲的Harris角点检测器中的角点在旋转的图像中也是角点,但是缩放呢? 如果缩放图像,则角可能不是角.例如,检查下面的简单图像, 当在同一窗口中放大时,小窗口内的小图像中的角是平坦的.所以Harris角点检测器不是尺度不变的.
所以,在2004年,不列颠哥伦比亚大学的D.Lowe在他的论文中提出了一种新的算法,即尺度不变特征变换(SIFT).
SIFT特征是基于物体上的一些局部外观的兴趣点而与影像的大小和旋转无关。对于光线、噪声、微视角改变的容忍度也相当高.基于这些特性,它们是高度显著而且相对容易撷取,在母数庞大的特征数据库中,很容易辨识物体而且鲜有误认.使用SIFT特征描述对于部分物体遮蔽的侦测率也相当高,甚至只需要3个以上的SIFT物体特征就足以计算出位置与方位.在现今的电脑硬件速度下和小型的特征数据库条件下,辨识速度可接近即时运算.SIFT特征的信息量大,适合在海量数据库中快速准确匹配.
OpenCV中的SIFT
import numpy as np import cv2 img = cv2.imread('img.jpg') gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) sift = cv2.xfeatures2d.SIFT_create() kp = sift.detect(gray,None) img=cv2.drawKeypoints(gray,kp,img) cv2.imshow('img',img) cv2.waitKey()
NOTE:
lz直接运行上述代码时,程序报错:module 'cv2.cv2' has no attribute 'xfeatures2d'
,后面查询原因知道OpenCv3.x以后只包含部分内容,需要神经网络或者其他的函数需要导入opencv_contrib,所以需要pip install opencv-contrib-python
sift.detect()
函数在图像中查找关键点, 如果只想搜索图像的一部分,可以传递掩膜.
OpenCV还提供了cv2.drawKeyPoints()
函数,该函数在关键点的位置上绘制小圆圈.如果传递标志cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
,它将绘制一个大小为keypoint的圆圈并显示它的方向.
import numpy as np import cv2 img = cv2.imread('img.jpg') gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) sift = cv2.xfeatures2d.SIFT_create() kp = sift.detect(gray,None) img=cv2.drawKeypoints(gray,kp,img,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) cv2.imshow('img',img) cv2.waitKey()
计算描述符,OpenCV提供了两种方法:
- 如果已经找到了关键点,可以调用
sift.compute()
来计算找到的关键点的描述符, 例如:kp,des = sift.compute(gary,kp)
- 如果没有找到关键点,可以使用函数
sift.detectAndCompute()
在一个步骤中直接查找关键点和描述符
sift = cv2.xfeatures2d.SIFT_create() kp, des = sift.detectAndCompute(gray,None)
kp是关键点列表,des是形状为Number_of_Keypoints×128的numpy数组.