特征检测Task01-Harris角点检测

目录

    • 1、前言
    • 2、角点
    • 3、Harris角点检测
      • 3.1 原理
      • 3.2 Harris角点性质
    • 4、基于python-opencv的实现

1、前言

在图像处理与计算机视觉邻域,特征点(Feature points),也被称为关键点(Key points)、兴趣点(Interset points),是三大图像特征之一。在传统CV图像处理过程中,被大量用于物体识别、图像识别、视觉跟踪、三维重建等领域。利用提取的特征点不仅可以有效表现图像的属性和行为,而且减小了内存,提高了图像处理的效率。常用的特征点检测算子有Harris角点检测、SIFT特征点检测、SURF特征点检测等。其中Harris角点是最为基础的图像特征,本文通过python-opencv实现Harris角点检测来理解图像特征检测的相关知识。
图像三种特征类型:

  • 边缘
  • 角点(特征点、兴趣点)
  • 斑点(Blobs)(兴趣区域)

2、角点

概念:如果图像某一点在任意方向的一个微小变动都会引起灰度的较大变化,该店就被称为角点。

举个例子:

特征检测Task01-Harris角点检测_第1张图片
如上图所示,利用滑窗法上面三幅图中滑动,可以看出:

  • 左图是一个平坦区域,在各方向移动,窗口覆盖区域像素值均没有太大变化;
  • 中图表示一个边缘特征,如果沿着水平方向移动(梯度方向),窗口像素值会发生跳变;如果沿着边缘移动,像素值不会发生变化;
  • 右图表示一个角点(Corners),不管你把它朝哪个方向移动,窗口像素值都会发生变化。

由此可知,从直观视角上,角点是图像的锐点,其邻域在图像上代表图像独一无二的一个特征或模式(Pattern);从客观视角上,角点又是图像代表像素点,其邻域像素值在图像上沿各个方向均有不同变化。

根据角点的定义,可对角点做出如下具体描述:

  • 一阶导数(梯度)的局部最大所对应的的像素点
  • 两条及其以上边缘的交点
  • 图像中梯度值和梯度方向的变化速率较高的点

3、Harris角点检测

Chris_Harris 和 Mike_Stephens 在 1988 年的文章《A Combined Corner and Edge Detector》中就提出了Harris角点检测的方法。

3.1 原理

假设中心位置为 ( x , y ) (x,y) (x,y)的滤波窗口为 w ( x , y ) w(x,y) w(x,y) ,让该窗口的中心对准灰度图像 ( x , y ) (x,y) (x,y)处,这个位置的像素灰度值为 I ( x , y ) I(x,y) I(x,y) ,如果这个窗口分别向 x x x y y y 方向移动一个小的位移 u u u v v v,到一个新的位置 ( x + u , y + v ) (x+u,y+v) (x+u,y+v) ,新位置的像素灰度值就是 I ( x + u , y + v ) I(x+u,y+v) I(x+u,y+v)
则数学表达式为:
E ( u , v ) = ∑ x , y w ( x , y ) [ I ( x + u , y + v ) − I ( x , y ) ] 2 E(u,v)=\sum_{x,y}^{}w(x,y)[I(x+u,y+v)-I(x,y)]^{^{2}} E(u,v)=x,yw(x,y)[I(x+u,y+v)I(x,y)]2

窗口函数可以是正常的矩形窗口,也可以是加权高斯窗口。

角点的检测中要使得 E ( u , v ) E(u,v) E(u,v)的值最大化,即使得 [ I ( x + u , y + v ) − I ( x , y ) ] 2 [I(x+u,y+v)-I(x,y)]^{^{2}} [I(x+u,y+v)I(x,y)]2最大,对上式进行泰勒展开在换算(这里不做探讨只是了解)可得以下等式:
E ( u , v ) ≈ [ u   v ] M [ u v ] E(u,v)\approx [u \ v]M \begin{bmatrix} u\\ v \end{bmatrix} E(u,v)[u v]M[uv]
其中,
M = ∑ w ( x , y ) [ I x I x I x I y I x I y I y I y ] M=\sum_{w(x,y)}^{}\begin{bmatrix} IxIx & IxIy\\ IxIy & IyIy \end{bmatrix} M=w(x,y)[IxIxIxIyIxIyIyIy]
这里 I x Ix Ix I y Iy Iy表示图像在 x x x, y y y方向的导数(可以通过函数cv.Soble()计算得到)。

为了找到那些窗口会引起灰度值的较大变换,我们需要对协方差矩阵M进行处理,这里通过引入角点响应函数R来判定像素点 ( x , y ) (x,y) (x,y)是否为角点,定义如下:
R = d e t ( M ) − k ( t r a c e ( M ) ) 2 R=det(M)-k(trace(M))^{^{2}} R=det(M)k(trace(M))2
其中

  • d e t ( M ) = λ 1 λ 2 det(M)=\lambda_1\lambda_2 det(M)=λ1λ2是矩阵的行列式,
  • t r a c e ( M ) = λ 1 + λ 2 trace(M)=\lambda_1+\lambda_2 trace(M)=λ1+λ2 是矩阵的迹。
  • λ 1 \lambda_1 λ1 λ 2 \lambda_2 λ2是矩阵的特征值

通过以上特征可以判断一个区域是否为角点、边界还是平面。

  • λ 1 \lambda_1 λ1 λ 2 \lambda_2 λ2都小时, ∣ R ∣ \left |R \right | R也小,这个区域就是平面。
  • λ 1 ≫ λ 2 \lambda_1\gg\lambda_2 λ1λ2或者 λ 1 ≪ λ 2 \lambda_1\ll\lambda_2 λ1λ2 R < 0 R<0 R<0时,这个区域就是边缘。
  • λ 1 \lambda_1 λ1 λ 2 \lambda_2 λ2都很大,并且 λ 1 ∼ λ 2 \lambda_1\sim \lambda_2 λ1λ2中的时候, R R R也很大( λ 1 \lambda_1 λ1 λ 2 \lambda_2 λ2中的最小值都大于阈值)说明这个区域是角点。

如下图所示:
特征检测Task01-Harris角点检测_第2张图片
Harris 角点检测的结果是带有这些分数 R 的灰度图像,设定一个阈值,分数大于这个阈值的像素就对应角点。

3.2 Harris角点性质

  • 阈值决定角点的数量:由上可知Harris检测结果是根据角点响应函数R的分数进行区分的,所以阈值的设定决定了可供选择的角点数量。
  • Harris角点检测算子对亮度和对比度的变化不敏感(光照不变性):使用Harris检测时,需计算X,Y方向的梯度(导数),由于梯度运算只与邻域像素变化有关,而亮度或对比度的变换并不会改变角点检测位置,所以其对光照有鲁棒性
  • Harris角点检测算子具有旋转不变性:Harris角点检测算子使用角点附近的区域灰度二阶矩矩阵。而二阶矩矩阵可以表示成一个椭圆,椭圆的长短轴正是二阶矩矩阵特征值平方根的倒数。当特征椭圆转动时,特征值并不发生变化,所以判断角点响应值也不发生变化,由此说明Harris角点检测算子具有旋转不变性。
  • Harris角点检测算子不具有尺度不变性:尺度的变化会将角点变为边缘,或者边缘变为角点,所以Harris不具有尺度不变性。

4、基于python-opencv的实现

python-OpenCV中的函数cv2.cornerHarris() 可以用来进行角点检测。参数如下:
• img:数据类型为 float32 的输入图像。
• blockSize:角点检测中要考虑的领域大小。
• ksize - Sobel:求导中使用的窗口大小
• k - Harris:角点检测方程中的自由参数,取值参数为 [0,04,0.06]

代码如下:

import cv2
import  numpy as np

# 定义Harris检测参数
block_size = 3
sobel_size = 3
k=0.04 # 0.04-0.06

filename = r"C:\Users\CleMints\Desktop/lena.jpg"
img = cv2.imread(filename)
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

gray_img = np.float32(gray_img)  # 输入图像必须是 float32 类型灰度图

# Harris角点检测
dst = cv2.cornerHarris(gray_img,block_size,sobel_size,k)

# 角点标记
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
dst = cv2.dilate(dst,kernel)

img[dst>0.05*dst.max()] = [255,0,0]
# for r in range(img.shape[0]):
#         for c in range(img.shape[1]):
#             pix = dst[r,c]
#             if pix>0.05*dst.max():
#                cv2.circle(img,(c,r),5,(0,0,255),0)

img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
cv2.imshow("HarrisCorner",img)
cv2.waitKey()

运行一张Lena图,灰度化后角点用红色像素点标记,运行结果为:
特征检测Task01-Harris角点检测_第3张图片
参考资料:
1、Harris角点算法
2、角点检测:Harris 与 Shi-Tomasi
3、Datawhale 计算机视觉基础-图像处理(下)- Task01 Harris特征点检测

你可能感兴趣的:(OpenCV3图像处理基础)