前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenCV:特征及角点检测

OpenCV:特征及角点检测

作者头像
用户3578099
发布2023-09-01 09:23:38
3970
发布2023-09-01 09:23:38
举报
文章被收录于专栏:AI科技时讯

目标1

在本章中,将学习

  • 理解什么是特征
  • 为什么拐角重要等

解释

大多数人都会玩拼图游戏。会得到很多小图像,需要正确组装它们以形成大的真实图像。问题是,你是如何去拼图的?同样地,将相同的理论投影到计算机程序上,以使得计算机也可以玩拼图游戏呢?如果计算机可以玩拼图游戏,为什么不能给计算机提供很多自然风光的真实图像,并告诉计算机将所有这些图像拼接成一个大图像呢?如果计算机可以将多个自然图像缝合在一起,那么如何给建筑物或任何结构提供大量图片并告诉计算机从中创建3D模型呢?

这全都取决于最基本的问题:人们是如何玩拼图游戏?如何将许多杂乱的图像片段排列成一个大的单张图像?如何将许多自然图像拼接到一张图像上?

答案是,在寻找独特的、易于跟踪和比较的特定模板或特定特征。如果我们对这种特征进行定义,可能会发现很难用语言来表达它,但是我们知道它们是什么。如果有人要求你指出一项可以在多张图像中进行比较的良好特征,就可以指出其中一项,这就是为什么即使是小孩也可以玩这些游戏的原因。我们在图像中搜索这些特征,找到它们,在其他图像中寻找相同的特征并将它们对齐。仅此而已。(在拼图游戏中,更多地研究了不同图像的连续性)。所有的这些能力都是我们固有的。

因此,可以将这个基本问题扩展开来,但变得更加具体。这些特征是什么?(答案对于计算机也应该是可以理解的。)

很难说人们如何发现这些特征,因为这已经在我们的大脑中进行了编码。但是,如果深入研究某些图片并搜索不同的模板,我们会发现一些有趣的东西。例如,看以下的图片:

在这里插入图片描述

图像非常简单。在图像的顶部,给出了六个小图像块。问题是在原始图像中找到这些补丁的确切位置。你可以找到多少正确的结果?

A和B是平坦的表面,它们散布在很多区域上,很难找到这些补丁的确切位置

C和D更简单,它们是建筑物的边缘。可以找到一个大概的位置,但是准确的位置仍然很困难。这是因为沿着边缘的每个地方的图案都是相同的。但是,在边缘,情况有所不同。因此,与平坦区域相比,边缘是更好的特征,但不够好(在拼图游戏中比较边缘的连续性很好)。

最后,E和F是建筑物的某些角落,而且很容易被找到。因为在拐角处,无论将此修补程序移动到何处,它的外观都将有所不同。因此,它们可以被视为很好的特征。因此,现在进入更简单(且被广泛使用的图像)以更好地理解。

在这里插入图片描述

就像上面一样,蓝色补丁是平坦区域,很难找到和跟踪。无论将蓝色补丁移到何处,它看起来都一样。黑色补丁有一个边缘。如果沿垂直方向(即沿渐变)移动它,则它会发生变化。沿着边缘(平行于边缘)移动,看起来相同。对于红色补丁,这是一个角落。无论将补丁移动到何处,它看起来都不同,这意味着它是唯一的。因此,基本上角落点被认为是图像中的良好特征。(不仅是角落,在某些情况下,斑点也被认为是不错的特征)。

因此,现在回答了这个问题,“特征是什么?”。但是出现了下一个问题。如何找到它们?还是如何找到角落?我们以一种直观的方式回答了这一问题,即寻找图像中在其周围所有区域中移动(少量)变化最大的区域。在接下来的章节中,这将被投影到计算机语言中。因此,找到这些图像特征称为特征检测。

在图像中找到了特征之后,应该能够在其他图像中找到相同的图像。这是如何做到的呢?我们围绕该特征采取一个区域,用自己的语言解释它,例如“上部是蓝天,下部是建筑物的区域,在建筑物上有玻璃等”,而在另一个建筑物中搜索相同的区域图片。基本上,这就是在描述特征。同样,计算机还应该描述特征周围的区域,以便可以在其他图像中找到它。所谓的描述称为特征描述获得特征及其描述后,可以在所有图像中找到相同的特征并将它们对齐,缝合在一起或进行所需的操作

因此,可以在OpenCV中寻找不同的算法来查找特征,对其进行描述,进行匹配等操作。

附加资源

  • https://docs.opencv.org/4.1.2/df/d54/tutorial_py_features_meaning.html

目标2

在本章中,将学习

  • "Harris Corner Detection”背后的思想
  • 函数:cv2.cornerHarris(),cv.2cornerSubPix()

理论

在上一章中看到,角是图像中各个方向上强度变化很大的区域。Chris Harris和Mike Stephens在1988年的论文《 A Combined Corner and Edge Detector 》中做了一次找到这些角点的早期尝试,所以现在将该方法称为哈里斯角点检测器。他把这个简单的想法变成了数学形式。它基本上找到了

(u,v)

在所有方向上位移的强度差异。表示如下:

E(u,v) = \sum\_{x,y} \underbrace{w(x,y)}*\text{window function} , \[\underbrace{I(x+u,y+v)}*\text{shifted intensity}-\underbrace{I(x,y)}\_\text{intensity}]^2

窗口函数可以是一个矩形窗口,也可以是一个高斯窗口,它在下面赋予了值。

必须最大化这个函数

E(u,v)

用于角点检测。这意味着,必须最大化第二个项。将泰勒扩展应用于上述方程,并使用一些数学步骤,得到最后的等式:

E(u,v) \approx \begin{bmatrix} u & v \end{bmatrix} M \begin{bmatrix} u \ v \end{bmatrix}

其中

M = \sum\_{x,y} w(x,y) \begin{bmatrix}I_x I_x & I_x I_y \ I_x I_y & I_y I_y \end{bmatrix}
I_x

I_y

分别是在x和y方向上的图像导数。(可以使用cv2.Sobel()获得)

在此之后,他们定义了一个分数,用等式表示,这将决定窗口是否包含角点。

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

其中

det(M) = \lambda\_1 \lambda\_2

(行列式值)

trace(M) = \lambda\_1 + \lambda\_2

(迹,主对角线元素和)

\lambda\_1

\lambda\_2

是M矩阵的特征值

因此,这些特征值的值决定了区域是拐角,边缘还是平坦。

∣R∣

较小,这在

\lambda\_1

\lambda\_2

较小时发生,该区域平坦。

R < 0

时,这是在

\lambda\_1 >>\lambda\_2

时发生,反之亦然),该区域为边

R

很大时,这是在

\lambda\_1

\lambda\_2

比较大且

\lambda\_1

~

\lambda\_2

时,该区域是角点。

可以用如下图来表示:

因此,Harris Corner Detection的结果是具有这些分数的灰度图像。合适的阈值可提供图像的各个角落。

OpenCV中的哈里斯角检测

在OpenCV中有实现哈里斯角点检测,cv2.cornerHarris()。其参数为:

dst = cv2.cornerHarris(src, blockSize, ksize, k[, dst[, borderType]] )

  • src - 输入图像,灰度和float32类型
  • blockSize - 是拐角检测考虑的邻域大小
  • ksize - 使用的Sobel导数的光圈参数
  • k- 等式中的哈里斯检测器自由参数
代码语言:javascript
复制
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('chessboard.png')
img_copy = img.copy()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

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.
img[dst >0.01*dst.max()]=[255,0,0]

# plot
plt.subplot(121)
plt.imshow(img_copy, cmap='gray')
plt.xticks([])
plt.yticks([])

plt.subplot(122)
plt.imshow(img, cmap='gray')
plt.xticks([])
plt.yticks([])
plt.show()

以下是结果:

可以看到,各个角点已经标红。

SubPixel精度的转角

有时候可能需要找到最精确的角点。OpenCV附带了一个函数cv2.cornerSubPix(),它进一步细化了以亚像素精度检测到的角点。下面是一个例子。

  • 和之前一样,首先需要先找到哈里斯角点
  • 然后通过这些角的质心(可能在一个角上有一堆像素,取它们的质心)来细化它们
  • Harris角用红色像素标记,SubPixel角用绿色像素标记

对于cv2.cornerSubPix()函数,必须定义停止迭代的条件。我们可以在特定的迭代次数或达到一定的精度后停止它。此外,还需要定义它将搜索角点的邻居的大小。

corners = cv.cornerSubPix( image, corners, winSize, zeroZone, criteria )

  • image: 输入图像,单通道
  • corners: 输入的初始坐标和为输出提供的精制坐标
  • winSize: 搜索窗口的一半侧面长度
  • zeroZone: 搜索区域中间的死区大小的一半在下面的公式中的求和,有时用于避免自相关矩阵的可能奇点。
(-1,-1)

的值表示没有这样的尺寸

  • criteria: 终止角点细化过程的条件
代码语言:javascript
复制
# sub pixel更精度角点
import cv2
import numpy as np

img = cv2.imread('chessboard2.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# find Harris corners
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)

# find centroids
ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst)

# define the criteria to stop and refine the corners
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)

# Now draw them
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('subpixel', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

以下是结果, 可以看到SubPixel更精确一点:

附加资源

  • https://docs.opencv.org/4.1.2/dd/d1a/group__imgproc__feature.html#gac1fc3598018010880e370e2f709b4345
  • https://docs.opencv.org/4.1.2/dd/d1a/group__imgproc__feature.html#gac1fc3598018010880e370e2f709b4345
  • https://docs.opencv.org/4.1.2/dd/d1a/group__imgproc__feature.html#ga354e0d7c86d0d9da75de9b9701a9a87e
  • https://docs.opencv.org/4.1.2/d4/d86/group__imgproc__filter.html#gacea54f142e81b6758cb6f375ce782c8d
  • https://docs.opencv.org/4.1.2/dd/d1a/group__imgproc__feature.html#ga354e0d7c86d0d9da75de9b9701a9a87e

目标

在本章中,将学习另一个角点检测器:

  • Shi-Tomasi拐角检测器
  • 函数:cv2.goodFeaturesToTrack()

理论3

在上一章中,学习了Harris Corner Detector。1994年下半年,J.Shi和C. Tomasi在论文《Good Features to Track》中做了一个小修改,与Harris Harris Detector相比,展示了更好的结果。哈里斯角落探测器的计分功能由下式给出:

R = \lambda\_1 \lambda\_2 - k(\lambda\_1+\lambda\_2)^2

取而代之的是,C. Tomasi提出:

R=min(\lambda\_1, \lambda\_2)

如果大于阈值,则将其视为拐角。如果像在Harris Corner Detector中那样在

\lambda\_1-\lambda\_2

空间中绘制它,则会得到如下图像:

从图中可以看到,只有当

\lambda\_1

\lambda\_2

大于最小值

\lambda\_{min}

时,才将其视为拐角(绿色区域)。

代码

OpenCV有一个函数cv2.goodFeaturesToTrack()。它通过Shi-Tomasi方法(或哈里斯角检测,如果指定的话)找到图像中的N个最强角。像往常一样,图像应该是灰度图像。然后,指定要查找的角的数量。然后,指定质量级别,该值是介于0-1之间的值,该值表示每个角落都被拒绝的最低拐角质量。然后,提供检测到的角之间的最小欧式距离。 利用所有这些信息,该函数可以找到图像中的拐角,低于平均质量的所有拐角点均被拒绝。然后,会根据质量以降序的方式对剩余的角进行排序。然后函数首先获取最佳拐角,然后丢弃最小距离范围内的所有附近拐角,然后返回N个最佳拐角。

corners = cv.goodFeaturesToTrack( image, maxCorners, qualityLevel, minDistance, mask, blockSize, gradientSize[, corners[, useHarrisDetector[, k]]] )

  • image 输入单通道图片
  • corners 输出的角点结果
  • maxCorners 最大的角点数量 maxCorners <= 0表示不限制
  • qualityLevel 最小的能接受的质量分数For example, if the best corner has the quality measure = 1500, and the qualityLevel=0.01 , then all the corners with the quality measure less than 15 are rejected.
  • minDistance 返回的角落之间的最小可能的欧几里德距离
  • mask 可选的兴趣区域。如果图像不为空(需要具有类型CV_8UC1和与图像相同的大小),则指定检测到角落的区域
  • blockSize 用于计算每个像素邻域的衍生协变矩阵的平均块的大小
  • useHarrisDetector 参数指示是否使用Harris检测器
  • 哈里斯检测器的免费参数

在下面的示例中,将尝试找到24个最佳角点:

代码语言:javascript
复制
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('shi.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

corners = cv2.goodFeaturesToTrack(gray, 24, 0.01, 10)  # 四个参数,图像,个数,分数,距离
corners = np.int0(corners)

for i in corners:
    x, y = i.ravel()
    cv2.circle(img, (x,y), 3, 255, -1)

plt.imshow(img)
plt.show()

附加资源

  • https://docs.opencv.org/4.1.2/d4/d8c/tutorial_py_shi_tomasi.html
  • https://docs.opencv.org/4.1.2/dd/d1a/group__imgproc__feature.html#ga1d6bb77486c8f92d79c8793ad995d541
  • https://zhuanlan.zhihu.com/p/83064609
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-05-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI科技时讯 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目标1
  • 解释
  • 附加资源
  • 目标2
  • 理论
  • OpenCV中的哈里斯角检测
  • SubPixel精度的转角
  • 附加资源
  • 目标
  • 理论3
  • 代码
  • 附加资源
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档