这是opencv3.0.0的python版官方文档,原文在这里
目标
这一章节,将
- 理解Harris角点检测算法背后的原理
- 学习两个函数:
cv2.cornerHarris()
、cv2.cornerSubPix()
理论
上一章,我们知道了角点是图像中各个方向亮度(intensity,0~255)变化都很大的区域。最早尝试做角点检测的是Chris Harris和Mike Stephens,1988年,记录在文献《A Combined Corner and Edge Detector》中,因此现在叫做Harris角点检测。他把这个简单的想法用数学形式表达了出来。它基本找到了(u, v)
在各个方向上位移后明亮度(Intensity)的差异,公式为:
window function是一个矩形窗口或者高斯窗口,是像素的权重。
为了检测角点,我们必须让E(u, v)
最大化。也就是说,我们要让第二项最大。将Taylor Expansion应用于上述方程并使用一些数学步骤(请参考您喜欢的任何标准教科书进行完全推导),我们得到最终的等式:
其中
这里,Ix和Iy分别是x和y方向的导数。(可以很容易的通过
cv2.Sobel()
得到)。
接下来就是重点部分。上述操作结束后,会得到一个分数,基于一个用来决定窗口内是否包含角点的等式。
其中
所以这些特征值决定了这个区域是角点,还是边缘,还是flat。
- 当|R|比较小时,也就是lambda 1和lambda 2比较小,区域是flat
- 当R<0时, 也就是lambda 1远大于lambda 2或反之亦然,区域是边缘
- 当R比较大时,也就是lambda 1和lambda2都大且相似,区域是角点
可以用下面的图来表示
所以Harris角点检测的结果是一个带着这些分数的灰度图。图像角点检测需要一个合适的阈值。我们将用一个简单的图来实现
Opencv中的Harris角点检测
Opencv中有一个函数cv2.cornerHarris()
用来实现这个算法,参数是:
- img - 输入图片,需要灰度图且类型float32
- blockSize - 是角点检测考虑的邻域大小
- ksize - sobel所用参数
- k - Harris检测器中的自由参数
看下面的例子:
import cv2
import numpy as np
filename = 'chessboard.jpg'
img = cv2.imread(filename)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst = cv2.cornerHarris(gray,2,3,0.04)
#result is dilated for marking the corners, not important
dst = cv2.dilate(dst,None)
# Threshold for an optimal value, it may vary depending on the image.
img[dst>0.01*dst.max()]=[0,0,255]
cv2.imshow('dst',img)
if cv2.waitKey(0) & 0xff == 27:
cv2.destroyAllWindows()
下面是三个结果图: