8.2. 哈里斯角点检测¶
8.2.2. 理论¶
在最后一章中,我们看到角是图像中各个方向强度变化较大的区域。一个早期的寻找这些角落的尝试是由 克里斯哈里斯和迈克斯蒂芬斯 在他们的报纸上 一种组合式角边缘检测器 1988年,现在它被称为哈里斯角探测器。他把这个简单的想法变成了数学形式。它基本上发现了 \((u,v)\) 四面八方。具体表现为:
窗口函数可以是矩形窗口,也可以是高斯窗口,它为下面的像素赋予权重。
我们必须最大化这个功能 \(E(u,v)\) 用于拐角检测。也就是说,我们必须使第二项最大化。将泰勒展开式应用于上述方程,并使用一些数学步骤(请参考您喜欢的任何标准教科书进行完整推导),我们得到最终方程如下:
在哪里?
在这里, \(I_x\) 和 \(I_y\) 分别是x和y方向的图像导数。(使用 第二节索贝尔() )
接下来是主要部分。在这之后,他们创建了一个分数,基本上是一个等式,它将决定一个窗口是否可以包含一个角。
因此,这些特征值的值决定了区域是角点、边还是平面。
什么时候? \(|R|\) 很小,当 \(\lambda_1\) 和 \(\lambda_2\) 很小,区域很平坦。
什么时候? \(R<0\) ,当 \(\lambda_1 >> \lambda_2\) 反之亦然,区域是边缘。
什么时候? \(R\) 很大,当 \(\lambda_1\) 和 \(\lambda_2\) 很大而且 \(\lambda_1 \sim \lambda_2\) ,区域是一个角。
它可以用一幅很好的图画来表示,如下所示:
因此Harris角点检测的结果是一幅灰度图像。一个合适的阈值给你在图像的角落。我们将用一个简单的图像来做。
8.2.3. OpenCV中的Harris角点检测器¶
OpenCV具有 柯纳哈里斯2号() 为此目的。其论点是:
img -输入图像,应为灰度和浮点32型。
块大小 -它是用于角点检测的邻域大小
大小 -使用索贝尔导数的孔径参数。
k -方程中的Harris检测器自由参数。
请参见下面的示例:
>>> %matplotlib inline
>>>
>>> import cv2
>>> import numpy as np
>>>
>>> filename = '/cvdata/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()
>>>
>>> import matplotlib.pyplot as plt
>>> plt.imshow(img)
<matplotlib.image.AxesImage at 0x7fa834f29f28>

>>> plt.imshow(dst)
<matplotlib.image.AxesImage at 0x7fa834e97080>

以下是三个结果:
8.2.4. 亚像素精度角点¶
有时,您可能需要以最大的精度找到拐角。OpenCV带有一个函数 cv2.角点组件() 它进一步细化了亚像素精度检测到的角点。下面是一个例子。像往常一样,我们需要先找到哈里斯角。然后我们通过这些角的质心(一个角上可能有一堆像素,我们取它们的质心)来细化它们。Harris角点用红色像素标记,精制角点用绿色像素标记。对于这个函数,我们必须定义停止迭代的条件。我们在指定的迭代次数或达到一定的精度后停止它,以先发生的为准。我们还需要定义它将搜索角落的邻居的大小。
>>> import cv2
>>> import numpy as np
>>>
>>> filename = '/cvdata/chessboard.jpg'
>>> img = cv2.imread(filename)
>>> gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
>>>
>>> # find Harris corners
>>> gray = np.float32(gray)
>>> dst = cv2.cornerHarris(gray,2,3,0.04)
>>> dst = cv2.dilate(dst,None)
>>> ret, dst = cv2.threshold(dst,0.01*dst.max(),255,0)
>>> dst = np.uint8(dst)
>>>
>>> # find centroids
>>> ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst)
>>>
>>> # define the criteria to stop and refine the corners
>>> criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001)
>>> corners = cv2.cornerSubPix(gray,np.float32(centroids),(5,5),(-1,-1),criteria)
>>>
>>> # Now draw them
>>> res = np.hstack((centroids,corners))
>>> res = np.int0(res)
>>> img[res[:,1],res[:,0]]=[0,0,255]
>>> img[res[:,3],res[:,2]] = [0,255,0]
>>>
>>> cv2.imwrite('subpixel5.png',img)
True
下面是结果,其中一些重要位置显示在缩放窗口中以进行可视化: