Harris算子的定义:
Harris算子是Harris和Stephens在1998年提出的一种基于信号的点特征提取算子。其前身是Moravec算子。
其基本思想是:在图像中设计一个局部检测窗口,当该窗口沿各个方向做微小移动时,考察窗口的平均能量变化,当该能量变化超过设定的阈值时,就将窗口的中心像素点提取为角点。
在角点处,任意方向移动,窗口灰度值均剧烈变化
引入角点响应函数的意义:
对于图像I(x,y)I(x,y),当在点(x,y)(x,y)处平移(Δx,Δy)(Δx,Δy)后的自相似性,可以通过自相关函数给出:
c(x,y;Δx,Δy)=∑(u,v)∈W(x,y)w(u,v)(I(u,v)–I(u+Δx,v+Δy))2
根据泰勒展开,对图像I(x,y)I(x,y)在平移(Δx,Δy)(Δx,Δy)后进行一阶近似:
I(u+Δx,v+Δy)=I(u,v)+Ix(u,v)Δx+Iy(u,v)Δy+O(Δx2,Δy2)≈I(u,v)+Ix(u,v)Δx+Iy(u,v)Δy
其中,Ix,IyIx,Iy是图像I(x,y)I(x,y)的偏导数,这样的话,自相关函数则可以简化为:
c(x,y;Δx,Δy)≈∑w(Ix(u,v)Δx+Iy(u,v)Δy)2=[Δx,Δy]M(x,y)[ΔxΔy]
也就是说图像I(x,y)I(x,y)在点(x,y)(x,y)处平移(Δx,Δy)(Δx,Δy)后的自相关函数可以近似为二项函数:
c(x,y;Δx,Δy)≈AΔx2+2CΔxΔy+BΔy2
其中
A=∑wI2x,B=∑wI2y,C=∑wIxIy
二次项函数本质上就是一个椭圆函数。椭圆的扁率和尺寸是由M(x,y)M(x,y)的特征值λ1、λ2λ1、λ2决定的,椭贺的方向是由M(x,y)M(x,y)的特征矢量决定的,如下图所示,椭圆方程为:
[Δx,Δy]M(x,y)[ΔxΔy]=1
椭圆函数特征值与图像中的角点、直线(边缘)和平面之间的关系如下图所示。共可分为三种情况:
- 图像中的直线。一个特征值大,另一个特征值小,λ1≫λ2λ1≫λ2或λ2≫λ1λ2≫λ1。自相关函数值在某一方向上大,在其他方向上小。
- 图像中的平面。两个特征值都小,且近似相等;自相关函数数值在各个方向上都小。
- 图像中的角点。两个特征值都大,且近似相等,自相关函数在所有方向都增大。
根据二次项函数特征值的计算公式,我们可以求M(x,y)M(x,y)矩阵的特征值。但是Harris给出的角点差别方法并不需要计算具体的特征值,而是计算一个角点响应值RR来判断角点。RR的计算公式为:
R=detM−α(traceM)2
R为正值是,检测到的是角点,R为负时检测到的是边,R很小时检测到的是平坦区域。
所以,引入角点响应函数的意义是由于λ1、λ2的大小是相对而言的,无法量化进行判断,所以引入角点响应函数,方便判断该点是否是角点。
以下是 Opencv+python 的代码实现
import cv2
import numpy as np
img = cv2.imread("left03.jpg")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #图像灰度化
gray = np.float32(gray)
#图像转换为float32
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.
#print(dst)
#img[dst>0.00000001*dst.max()]=[0,0,255] #可以试试这个参数,角点被标记的多余了一些
img[dst>0.01*dst.max()]=[0,0,255]#角点位置用红色标记
#这里的打分值以大于0.01×dst中最大值为边界
cv2.namedWindow("Harris", 2) #创建一个窗口
cv2.imshow('Harris',img)
cv2.waitKey()
主要函数cv2.cornerHarris(img,blockSize,ksize,k) 可以用来进行角点检测。参数如下:
- img - 数据类型为 float32 的输入图像。
- blockSize - 角点检测中要考虑的领域大小。
- ksize - Sobel 求导中使用的窗口大小
- k - Harris 角点检测方程中的自由参数,取值参数为 [0,04,0.06].
效果图: