希望有能力的朋友还是拿C++做。
本节讨论特征检测,主要是Harris,shi-tomasi,sift三种方法和对比,以及原理简介,还有关键点和描述子的概念介绍。
一、特征检测
特征检测包括边缘检测,角检测,区域检测和脊检测。
- 应用场景:图像搜索(如以图搜图),拼图游戏,图像拼接
- 寻找特征:
- 唯一的
- 可追踪的
- 能比较的
- 角点:
- 灰度梯度的最大值对应的像素
- 两条线的交点
- 极值点(一阶导数最大,二阶导数为0)
1.Harris角点检测
- 直观理解就是用一个矩形框,去在图像中移动,当图像(x,y)(x,y),在点(x,y)(x,y)处平移(Δx,Δy)(Δx,Δy)后的自相似性(就是两个图像做差)
- 细节处理是对矩形框的权重
- 在平坦区域,任意移动衡量系统变换都不大
- 在边缘区域,垂直边缘移动,衡量系统变换剧烈
- 在角点处,往哪个方向移动,衡量系统都变化剧烈
- cornerHarris(src, blockSize, ksize, k[, dst[, borderType]])
- blockSize:检测窗口大小
- ksize:卷积核
- k:权重系数,是个经验值,一般取0.04~0.06之间,一般默认0.04
- 它的返回值是一个无通道数据的,尺寸与原图相同的ndarray数组,数据为TRUE证明是角点
import cv2
import numpy as np
img = cv2.imread('homework.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
dst = cv2.cornerHarris(gray, blockSize=2, ksize=3, k=0.04)
#返回的东西叫做角点响应,每一个像素点都能计算出一个角点响应
#print(dst.shape)
#显示角点
#我们认为角点响应大于0.01倍的dst.max()就可以认为是角点了
#print(dst>(0.01 * dst.max()))
#print(img.shape)
img[(dst>(0.05 * dst.max()))] = [0,0,255]
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
2. shi-tomasi角点检测
- 改进了harris算法,harris角点检测计算的稳定性与k有关,而K是一个经验值,不太好设定最佳K值
- shi-tomasi发现,角点稳定性与矩阵M的较小特征值有关,对算法做了调整,就不用调整K值了
- goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance[, corners[, mask[, blockSize[, useHarrisDetector[, k]]]]])
- maxCorners:角点的最大值
- qualityLevel:角点质量
- minDistance:角之间最小欧氏距离,忽略小于此距离的点
- mask:感兴趣的区域
- blockSize:检测窗口的大小
- useHarrisDetector:是否使用Harris算法
- k:默认是0.04
import cv2
import numpy as np
maxCorners = 100
q1 = 0.01
minDistance = 10
img = cv2.imread('homework.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
corners = cv2.goodFeaturesToTrack(gray, maxCorners, q1, minDistance)
corners = np.int0(corners)
#Shi-Tomasi绘制角点
for i in corners:
x,y = i.ravel() #二维变一维
cv2.circle(img, (x,y), 3, (255,255,0), -1)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
3. SIFT关键点检测
希望在图片不同尺寸(图像金字塔),不同分辨率(高斯滤波)下,都能找到角点。
sift关键点检测原理说明
- 高斯差分金字塔(DOG),金字塔间不同层级之间图像做差
- DOG空间极值检测:为寻找尺度空间极值点,每个像素点要和(图像域)同一尺度空间、(相邻域)相邻尺度空间的所有点进行比较。
- 关键点的精确定位:对比出来的DOG空间的极值点都是离散的点,精确定位的一种方法是,对尺度空间的DOG函数进行拟合,计算其极值点,从而实现关键点的精确定位。
- 使用SIFT:
- 创建SIFT对象 sift=cv2.xfeatures2d.SIFT_create()
- 进行检测 kp = sift, detect(img, …)
- 绘制关键点 drawKeypoints(gray, kp, img)
import cv2
import numpy as np
img = cv2.imread('homework.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
#创建sift对象
#注意:xfretures2d是opencv的扩展包中的内容,需要安装opencv扩展包:opencv-contrib-python
sift = cv2.xfeatures2d.SIFT_create()
#进行检测
kp = sift.detect(gray)
print(kp)
#绘制关键点
cv2.drawKeypoints(gray, kp, img)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
4. 关键点和描述子
- 关键点:返回的keypoints, 只包含位置大小方向
- 关键点描述子:记录了关键点周围对其又共享像素点的一组向量值,其不受仿射变换,光照变换等的影响,作用是进行特征匹配,在后面进行特征匹配会用上
import cv2
import numpy as np
img = cv2.imread('homework.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
#创建sift对象
sift = cv2.xfeatures2d.SIFT_create()
#进行检测
kp = sift.detect(gray)
#检测关键点,并计算描述子
kp,des = sift.compute(img, kp)
#或者一步到位,一起检测,none是掩膜
#kp, des = sift.detectAndCompute(img, None)
#print(kp, des)
# #绘制关键点
cv2.drawKeypoints(gray, kp, img)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
二、几种角点特性
- Harris角点具有旋转不变的特性,但是缩放之后,原来的角点就可能不是角点了
- SIFT,具有尺度不变性,可在图像中检测出关键点