【OpenCV-Python】教程:4-2 Harris角点检测
创始人
2024-03-20 21:58:41

OpenCV Python Harris 角点检测

【目标】

  • 理解Harris角点检测背后的概念;
  • cv2.cornerHarris(), cv2.cornerSubPix()

【理论】

上一章节中,我们看到在图像中每个方向变化都很大的区域就是角点,一个早期的尝试是由 Chris Harris & Mike Stephens 在1998年的论文 A Combined Corner and Edge Detector 完成的。所以现在称之为 Harris 角点检测。他讲这些思想转换为数学公式形式,通过寻找不同方向上位移的亮度差异。

E(u,v)=∑x,yw(x,y)[I(x+u,y+v)−I(x,y)]2E(u,v)=\sum\limits_{x,y}w(x,y) [I(x+u,y+v)-I(x,y)]^2 E(u,v)=x,y∑​w(x,y)[I(x+u,y+v)−I(x,y)]2

w(x,y)w(x,y)w(x,y) 是窗口函数,可以是矩形窗口,也可以是高斯窗口,对应像素不同的权重。
I(x+u,y+v)I(x+u,y+v)I(x+u,y+v) 是移动区域的亮度,
I(x,y)I(x,y)I(x,y) 是亮度函数;

我们需要最大化函数 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)≈[uv]M[uv]E(u,v)\approx[u \quad v] M \begin{bmatrix} u \\ v \end{bmatrix} E(u,v)≈[uv]M[uv​]

其中

M=∑x,yw(x,y)[IxIxIxIyIyIxIyIy]M=\sum\limits_{x,y}w(x,y)\begin{bmatrix} I_xI_x & I_xI_y \\ I_yI_x & I_yI_y \end{bmatrix} M=x,y∑​w(x,y)[Ix​Ix​Iy​Ix​​Ix​Iy​Iy​Iy​​]

其中 IxI_xIx​ 和 IyI_yIy​ 是图像在 xxx 和 yyy 方向上的梯度(可以通过 sobel 获得);

然后来到了主要部分,创建了一个分数,基本就是一个等式,确定了窗口是否包含了角点与否。

R=det(M)−k(trace(M))2R=det(M)-k(trace(M))^2 R=det(M)−k(trace(M))2

其中:

  • det(M)=λ1λ2det(M)=\lambda_1 \lambda_2det(M)=λ1​λ2​
  • trace(M)=λ1+λ2trace(M)=\lambda_1+\lambda_2trace(M)=λ1​+λ2​
  • λ1\lambda_1λ1​和 λ2\lambda_2λ2​ 是 MMM的特征值

因此,这些特征值的大小决定了这个区域是角点,边还是平坦区域。

  • ∣R∣|R|∣R∣ 很小,当 λ1\lambda_1λ1​和 λ2\lambda_2λ2​ 很小时,区域平坦;
  • R<0R<0R<0,当 λ1≫λ2\lambda_1\gg \lambda_2λ1​≫λ2​ 或 λ1≪λ2\lambda_1 \ll \lambda_2λ1​≪λ2​ 时,区域是边缘;
  • RRR 很大,当 λ1\lambda_1λ1​和λ2\lambda_2λ2​很大时并且 λ1≈λ2\lambda_1 \approx \lambda_2λ1​≈λ2​ 时,区域是角点。

在这里插入图片描述

【代码】

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

import cv2
import numpy as np # 读入图片并灰度化
# img = cv2.imread("assets/blox.jpg")
img = cv2.imread("assets/left08.jpg")
# img = cv2.imread("assets/chessboard(1).png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 检测角点
gray = np.float32(gray)
dst = cv2.cornerHarris(gray, 2, 3, 0.04)# 膨胀
dst = cv2.dilate(dst, None)# 找到计算值比较大的,并显示
img[dst>0.01*dst.max()] = [0, 0, 255]cv2.imshow('dst', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 亚像素精度角点检测

在这里插入图片描述

  • 局部图
    在这里插入图片描述
import numpy as np
import cv2# 读入图片并灰度化
img = cv2.imread("assets/left08.jpg")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)# 寻找角点
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)# 找到连通域中心
ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst)# 寻找亚像素角点
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)# 显示
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.imshow("res", img)
cv2.imshow("dst", dst)cv2.waitKey(0)
cv2.destroyAllWindows()cv2.imwrite('subpixel5.png', img)

【接口】

  • cornerHarris
cv2.cornerHarris(	src, blockSize, ksize, k[, dst[, borderType]]	) ->	dst

在这里插入图片描述

Harris 角点检测

  • src: 单通道8位图像或者浮点图像
  • dst: 存储 harris 角点检测响应, CV_FC1 大小与源图像一致;
  • blocksize: 领域大小
  • ksize: sobel算子的直径
  • k: harris角点检测的自由参数里的 kkk
  • borderType: 扩边参数,BORDER_WRAP 不支持
  • borderType

在这里插入图片描述

  • cornerSubPix
cv2.cornerSubPix(	image, corners, winSize, zeroZone, criteria	) ->	corners

优化角点位置

  • image: 输入的单通道图像,8位或者浮点数
  • corners: 初始化的角点位置,并且可以接受输出
  • winSize: 搜寻窗口的半径,如果设置为 (5, 5),则搜索区域为 (52+1, 52+1) =(11,11)的窗口;
  • zeroZone: (-1,-1) 表示没有这个尺寸
  • criteria: 迭代准则,要么次数达到了,要么移动的距离很小了。
  • connectedComponentsWithStats
cv.connectedComponentsWithStats(	image[, labels[, stats[, centroids[, connectivity[, ltype]]]]]	) ->	retval, labels, stats, centroids
cv.connectedComponentsWithStatsWithAlgorithm(	image, connectivity, ltype, ccltype[, labels[, stats[, centroids]]]	) ->	retval, labels, stats, centroids

计算二值图像连通区域,并返回一系列的统计值

  • image: 8位单通道需要标记的图像
  • labels: 输出的标签图像
  • stats: 统计每一个标签的输出,包含背景标签
  • centroids: 每个区域的中心,可以通过 centroids(label, 0) 访问 x, centroids(label, 1) 访问 y;
  • connectivity: 4邻域或8邻域
  • ltype: 输出标签类型 CV_32S 或者 CV_16U
  • ccltype: 连通区域类型
  • ConnectedComponentsAlgorithmsTypes

在这里插入图片描述

【参考】

  1. OpenCV 官方文档

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...