【OpenCV】harris算法角点检测

角点引入

如图所示,从图像的灰度级考虑,A,B为平面无论沿任何方向灰度级都不会发生过大的变化。C,D沿某一方向会发生巨大变化。E,F沿着任何方向都发生巨大变化。

结论

R= detM- \alpha (trac M)^2

其中,det M=\lambda _1 \lambda_2traceM=\lambda_1+\lambda_2

当R》》0时,为角点,

当R\approx0时,为边界,

当R《0时,平坦区。

推导

本质上是根据图像滑动前后灰度的变化进行判断,所以是一个减法:

其中,u,v是窗口当前的坐标I(u,v)为当前的灰度值,I(u+\Delta x ,v+\Delta y )为进行微小移动后的灰度值。w(u,v)是窗口的权重项。

基于泰勒展开,对图像I(x,y)在平移(\Delta x,\Delta y)后进行一阶近似:

其中,I_x,I_yI(x,y)的偏导数

近似可得

 

二次函数A\Delta x^2+2C\Delta x \Delta y +B\Delta y^2可以理解为一个不在原点的椭圆它的等高线未定,设A\Delta x^2+2C\Delta x \Delta y +B\Delta y^2 =1 且因为M是是对称阵,椭圆可以化简为\lambda_1 x^2+\lambda_2y^2=C,如图

所以这个椭圆=灰度值差值,它的某个方向的变化大小(形状)体现它当前位置的情况(平坦、边、脚),如图

 所以推出判断标准:

R= detM- \alpha (trac M)^2

其中,det M=\lambda _1 \lambda_2traceM=\lambda_1+\lambda_2

当R》》0时,为角点,

当R\approx0时,为边界,

当R《0时,平坦区。

补充:非极大值抑制,NMS。有的边灰度值变化也大,但并不是角点。

代码实现

import cv2

img = cv2.imread('./data/test2.png')
print ('img.shape:',img.shape)
#转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)


#cv2.cornerHarris(img, blockSize, ksize, k)
# img:数据类型为float32的图像
# blockSize: 角点检测中指定区域的大小
# ksize: Sobel求导中使用的窗口大小,边缘检测的算子
# k :参数,一般取[0.04]
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
print ('dst.shape:',dst.shape)

# dst.max是最大值,一定是角点
# 只要dst中满足0.01倍的最大值,就判定为角点,要求较高的也可以设置为其他倍数
img[dst>0.01*dst.max()]=[0,0,255]
cv2.imshow('dst',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('./data/test_1_dst.jpg',img)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wL魔法师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值