opencv-python Harris角点检测笔记
内部区域的方框无论往哪个方向进行偏移,像素值都不会有很大变化。(蓝色框)
边缘处的方框在一个方向上进行偏移像素值变化很大,另一个方向变化很小。(黑色框)
角点处的方框无论往哪个方向进行偏移,都会对框内像素值造成很大的变动。(红色框)(1)将窗口向各个方向移动(u,v)然后计算所有差异的总和。窗口函数可以是正常的矩形,也可以对每一个像素给予不同权重的高斯窗口。
(2)角点检测中要使 E(u,v)的值最大。这就是说必须使方程右侧的第二项的取值最大。对上面的等式进行泰勒级数展开然后再通过几步数学换算(可以参考其他标准教材),我们得到下面的等式:
其中
Ix和Iy是图像在x和y方向的导数。(可以使用函数 cv2.Sobel() 计算得到)(3)根据一个用来判定窗口内是否包含角点的等式进行打分。
当λ1和λ2都小时,|R|也小,这个区域就是一个平坦区域。
当λ1>>λ2或者λ2>>λ1时,R<0,此时是边缘。
当λ1和λ2都很大时,R也很大,(λ1和λ2中的最小值都大于阈值)说明这个区域是角点。
代码实现:
Open 中的函数 cv2.cornerHarris()可以用来进行角点检测。参数如下:
• img - 数据类型为float32的输入图像。
• blockSize -角点检测中要考虑的领域大小。
• ksize - Sobel求导中使用的窗口大小。
• k - Harris角点检测方程中的自由参数,取值参数为 [0,04,0.06]。
import cv2
import numpy as np
img = cv2.imread("img/chessboard.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
# 最重要的是第三个参数,该参数限定了Sobel算子的中孔。conerHarris函数会使用
# Sobel算子,并且第三个参数定义了Sobel算子的中孔,该参数定义了角点检测的敏感度
# 其取值必须介于3和31之间的奇数。
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
# 参数值越小,标记角点的记号越小。
img[dst > 0.01*dst.max()] = [0, 0, 255]
cv2.imshow("dst", img)
cv2.waitKey(0)
cv2.destroyAllWindows()