作者:手机用户2602879695 | 来源:互联网 | 2024-11-28 12:13
角点检测
- 一、cornerHarris() 函数
- 二、Shi-Tomasi 角点检测 goodFeaturesToTrack()
- 三、FAST() 特征检测
- cv2.drawKeypoints() 函数讲解
- 关于FAST()函数示例,参数如下
一、cornerHarris() 函数
cornerHarris() 角点检测具有旋转不变特性。关于角点检测用一幅图来讲解:
- 对红框进行移动:无论是往哪个方向进行偏移,都会对框框内的像素值造成很大的变动。那么红框 框住的区域的边角点,就是检测到的角点。
- 对黑框进行移动:水平方向上移动像素值的变化不大,垂直方向上移动那么就会变化很大;或者相反,则这种一般称为边缘区域。
- 对蓝框进行移动:无论是水平还是垂直的方向移动,框内像素值的变化不大。这种是内部区域。
1988 年的文章《A CombinedCorner and Edge Detector》中就已经提出了焦点检测的方法,被称为Harris 角点检测。他把这个简单的想法转换成了数学形式。将窗口向各个方向移动 (u,v) 然后计算所有差异的总和。表达式如下:
E(u,v)=x,y∑window functionw(x,y)shifted intensity[I(x+u,y+v)−intensityI(x,y)]2
窗口函数(Sobel求导中使用的窗口) :可以是正常的矩形窗口,也可以是对每一个像素给予不同权重的高斯窗口
角点检测中要使 E(μ,ν) 的值最大。这就是说必须使方程右侧的第二项的取值最大。对上面的等式进行泰勒级数展开然后再通过几步数学换算(可以参考其他标准教材),我们得到下面的等式:
E(u,v)=[uv]≈M[uv]
其中:
E(u,v)=x,y∑w(x,y)[Ix2IxIyIxIyIy2]
这里 Ix 和 Iy 是图像在 x 和 y 方向的导数。(可以使用函数 cv2.Sobel(),计算得到)详情请点击。
他们根据一个用来判定窗口内是否包含角点的等式进行打分。
R=det(M)−k(trace(M))2
其中:
det(M)=λ1λ2
trace(M)=λ1+λ2
λ1 和 λ2 是矩阵 M 的特征值:我们可以判断一个区域是否是角点,边界或者是平面。
cv2.cornerHarris(src=gray, blockSize, ksize, k, dst=None, borderType=None)
"""
cornerHarris参数:
src - 数据类型为 float32 的输入图像。(输入单通道图)
blockSize - 角点检测中要考虑的领域大小。也就是计算协方差矩阵时的窗口大小
ksize - Sobel求导中使用的窗口大小
k - Harris 角点检测方程中的自由参数,取值参数为 [0.04,0.06].
dst - 输出图像
borderType - 边界的类型
"""
示例一:
import cv2
import numpy as np
filename = 'D:\image_person\00001.png'
img = cv2.imread(filename)
img = cv2.resize(img, (640, 480))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
cv2.imshow('dst', dst)
dst = cv2.dilate(dst, None)
img[dst > 0.01 * dst.max()] = [0, 0, 255]
cv2.imshow('img', img)
cv2.imshow('dst2', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
左侧为原图,右侧为检测之后的图像。
参数测试:(我写了两组数据测试,使大家一目了然,BlockSize ,Ksize 这两个参数的含义)
import cv2
import numpy as np
img = cv2.imread('D:\image_person\06_01.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
BlockSize =(2,3,4,5,7,9)
Ksize =(3,5,5,9,11,23)
for i,j in zip(BlockSize,Ksize):
dst = cv2.cornerHarris(src=gray, blockSize=i, ksize=j, k=0.04)
a = dst>0.01 * dst.max()
img[a] = [0, 0, 255]
cv2.imshow('corners_' + str(i) + '_' + str(j), img)
cv2.waitKey(0)
cv2.waitKey(0)
cv2.destroyAllWindows()
有时候我们检验时有很多角点都是粘连在一起的,通过加入非极大值抑制来进一步去除一些粘在一起的角点。也就是在一个窗口内,如果有多个角点则用值最大的那个角点,其他的角点都删除。
请看如下示例:
import cv2
import numpy as np
img = cv2.imread('./lou.png')
cv2.imshow('raw_img', img)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
J = (0.05,0.01,0.005)
for j in J:
dst = cv2.cornerHarris(src=gray, blockSize=5, ksize=7, k=0.04)
a = dst>j * dst.max()
img[a] = [0, 0, 255]
cv2.imshow('corners_'+ str(j), img)
cv2.waitKey(0)
cv2.waitKey(0)
cv2.destroyAllWindows()
二、Shi-Tomasi 角点检测 goodFeaturesToTrack()
goodFeaturesToTrack()是cornerHarris() 函数升级版。该函数的角点检测效果与cornerHarris()函数效果差不多。
Harris 角点检测的打分公式为:
R=λ1λ2−k(λ1+λ