(1)原理
通过一个小窗口对图像进行积分,随着窗口的移动,根据窗口内像素灰度积分值来判断像素点是否为角点,依据如下:
(2)灰度积分变化
定义灰度积分变化为 E ( u , v ) = Σ w ( x , y ) [ I ( x + u , y + v ) − I ( x , y ) ] 2 E(u,v) = \Sigma w(x, y)[I(x+u,y+v)-I(x, y)]^2 E(u,v)=Σw(x,y)[I(x+u,y+v)−I(x,y)]2其中
Σ [ I ( x + u , y + v ) − I ( x , y ) ] 2 ≈ Σ [ I ( x , y ) + u I x + v I y − I ( x , y ) ] \Sigma [I(x+u,y+v)-I(x, y)]^2\approx \Sigma [I(x, y)+uI_x+vI_y-I(x,y)] Σ[I(x+u,y+v)−I(x,y)]2≈Σ[I(x,y)+uIx+vIy−I(x,y)]
= Σ u 2 I x 2 + 2 u v I x I y + v 2 I y 2 =\Sigma u^2I_x^2+2uvI_xI_y+v^2I_y^2 =Σu2Ix2+2uvIxIy+v2Iy2
= Σ [ u v ] [ I x 2 I x I y I x I y I y 2 ] [ u v ] =\Sigma \left[ \begin{matrix} u & v \end{matrix}\right] \left[ \begin{matrix} I_x^2 & I_xI_y \\ I_xI_y & I_y^2 \end{matrix}\right] \left[ \begin{matrix} u \\ v \end{matrix}\right] =Σ[uv][Ix2IxIyIxIyIy2][uv]
= [ u v ] ( Σ [ I x 2 I x I y I x I y I y 2 ] ) [ u v ] =\left[ \begin{matrix} u & v \end{matrix}\right] (\Sigma \left[ \begin{matrix} I_x^2 & I_xI_y \\ I_xI_y & I_y^2 \end{matrix}\right] ) \left[ \begin{matrix} u \\ v \end{matrix}\right] =[uv](Σ[Ix2IxIyIxIyIy2])[uv]
当窗口移动的距离很小的时候,即 ( u , v ) (u,v) (u,v)的变换很小,则有
E ( u , v ) = [ u v ] M [ u v ] E(u,v) = \left[ \begin{matrix} u & v \end{matrix}\right] M \left[ \begin{matrix} u \\ v \end{matrix}\right] E(u,v)=[uv]M[uv]其中, M = Σ w ( x , y ) [ I x 2 I x I y I x I y I y 2 ] M = \Sigma w(x,y)\left[ \begin{matrix} I_x^2 & I_xI_y \\ I_xI_y & I_y^2 \end{matrix}\right] M=Σw(x,y)[Ix2IxIyIxIyIy2]
可以发现, E E E是一个二次型,可以化简为 E = [ u v ] [ A C C B ] [ u v ] = A u 2 + B v 2 + 2 C u v E= \left[ \begin{matrix} u & v \end{matrix}\right] \left[ \begin{matrix} A & C \\ C & B\end{matrix}\right] \left[ \begin{matrix} u \\ v \end{matrix}\right] = Au^2+Bv^2+2Cuv E=[uv][ACCB][uv]=Au2+Bv2+2Cuv
等效为椭圆模型,则为
u 2 / a 2 + v 2 / b 2 = 1 u^2/a^2+v^2/b^2=1 u2/a2+v2/b2=1
(3)Harris算子
λ 1 − 1 / 2 \lambda_1^{-1/2} λ1−1/2和 λ 2 − 1 / 2 \lambda_2^{-1/2} λ2−1/2是椭圆的长短轴
(4)角点响应函数
上一点说的 λ 1 和 λ 2 \lambda_1和\lambda_2 λ1和λ2比较小和比较大是一个相对值,在实际检测中是无法有效界定的,因此,Harris算子引入角点响应函数来判断像素点的类型
R = d e t M − k ( t r a c e M ) 2 R = detM-k(traceM)^2 R=detM−k(traceM)2 t r a c e M = λ 1 + λ 2 trace M = \lambda_1+\lambda_2 traceM=λ1+λ2 d e t M = λ 1 λ 2 det M = \lambda_1\lambda_2 detM=λ1λ2
(5)opencv Harris角点检测函数
C++:
void cv::cornerHarris ( InputArray src, # 输入图像,单通道-8位或者浮点型图像
OutputArray dst, # 输出图像,保存Harris角点检测结果,和源图像尺寸一样
int blockSize, # 邻域的大小
int ksize, # Sobel算子的孔径大小
double k, # 角点响应函数的参数k
int borderType = BORDER_DEFAULT # 图像像素的边界模式
)
Python:
dst = cv.cornerHarris( src, blockSize, ksize, k[, dst[, borderType]] )
import cv2 as cv
import numpy as np
# Harris method
lena = cv.imread("/home/lihoon/code/opencvImg/Harris/lena.jpg")
gray_lena = cv.cvtColor(lena, cv.COLOR_BGR2GRAY)
gray_lena = np.float32(gray_lena)
dst = cv.cornerHarris(gray_lena, 3, 3, 0.05)
lena[dst > 0.01 * dst.max()] = [0, 0, 255]
cv.imshow("Harris", lena)
cv.waitKey()
图中,红色的点就是通过Harris角点检测算子检测的特征点