?? 角点检测(Corner Detection)是计算机视觉系统中用来获得图像特征的一种方法,广泛应用于运动检测、图像匹配、视频跟踪、三维建模和目标识别等领域中,也称为特征点检测。本文主要介绍了两种经典的检测方法,具体可以详读本文~
目录
- Harris角点检测
- 概述
- 函数
- 示例
- Shi-Tomas角点检测
- 概述
- 函数
- 示例
- 亚像素级的角点检测
- 概述
- 函数
- 代码
Harris角点检测
概述
?? Chris_Harris 和 Mike_Stephens 早在 1988 年的文章《A Combined Corner and Edge Detector》中就已经提出了焦点检测的方法被称为 Harris角点检测。他把这个简单的想法转换成了数学形式。将窗口向各个方向 移动(u , v)然后计算所有差异的总和。
表达式如下:
数学转换后:
其中:
I_{x}Ix?和I_{y}Iy?是图像在x和y方向的导数(可以用函数cv2.Sobel()计算得到).
最终,根据一个用来判定窗口内是否包含角点的等式进行打分:
其中:
函数
?? OpenCV 中的函数 cv2.cornerHarris() 可以用来进行角点检测,参数如下:
- img - 输入图像。
- blockSize - 角点检测中领域像素的大小。
- ksize - Sobel 求导中使用的窗口大小
- k - Harris 角点检测方程中的自由参数,取值参数为 [0,04,0.06].
- 输出 response
示例
import numpy as np
import cv2 as cv
def harris(image, opt=1):
# Detector parameters
blockSize = 2
apertureSize = 3
k = 0.04
# Detecting corners
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
dst = cv.cornerHarris(gray, blockSize, apertureSize, k)
# Normalizing
dst_norm = np.empty(dst.shape, dtype=np.float32)
cv.normalize(dst, dst_norm, alpha=0, beta=255, norm_type=cv.NORM_MINMAX)
# Drawing a circle around corners
for i in range(dst_norm.shape[0]):
for j in range(dst_norm.shape[1]):
if int(dst_norm[i, j]) > 120:
cv.circle(image, (j, i), 2, (0, 255, 0), 2)
# output
return image
src = cv.imread("chessboard.jpg")
cv.imshow("input", src)
result = harris(src)
cv.imshow('result', result)
cv.imwrite('result.jpg', result)
cv.waitKey(0)
cv.destroyAllWindows()
Shi-Tomas角点检测
概述
?? Shi-Tomas是源于《Good Features to Track》,其中对Harris角点检测算法改进后的新算法。
?? Shi-Tomas使用的打分函数为:
R=\min\left(\lambda_{1},\lambda_{2}\right)R=min(λ1?,λ2?)
如果打分超过阈值,则认为它是一个角点,因此可以绘制如下所示的空间图:
图中,只有当\lambda_{1}λ1?和\lambda_{1}λ1?都大于之最小值,才可以被认为是角点(绿色区域)
函数
?? OpenCV 中的函数 cv2.goodFeaturesToTrack() 可以用来进行角点检测,参数如下:
输入:
- src单通道输入图像,八位或者浮点数。
- maxCorners表示最大返回关键点数目。
- qualityLevel 角点品质因子:表示拒绝的关键点 R < qualityLevel × max response将会被直接丢弃。
- minDistance 表示两个关键点之间的最短距离。
- mask 表示mask区域,如果有表明只对mask区域做计算。
- blockSize 计算梯度与微分的窗口区域。
- useHarrisDetector 表示是否使用harris角点检测,默认是false 为shi-tomas。
- k = 0.04默认值,当useHarrisDetector为ture时候起作用。
输出:
- corners是输出的关键点坐标集合
示例
import numpy as np
import cv2
def process(image, opt=1):
# Detecting corners
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
corners = cv2.goodFeaturesToTrack(gray, 35, 0.05, 10)
print(len(corners))
for pt in corners:
print(pt)
b = np.random.random_integers(0, 256)
g = np.random.random_integers(0, 256)
r = np.random.random_integers(0, 256)
x = np.int32(pt[0][0])
y = np.int32(pt[0][1])
cv2.circle(image, (x, y), 5, (int(b), int(g), int(r)), 2)
# output
return image
src = cv2.imread("blox.jpg")
cv2.imshow("input", src)
result = process(src)
cv2.imshow('result', result)
cv2.imwrite('result.jpg',result)
cv2.waitKey(0)
cv2.destroyAllWindows()
亚像素级的角点检测
概述
?? OpenCV中角点检测的结果实际不够精准,因为真实的计算中有些位置可能是在浮点数的空间内才最大值,这样就需要我们通过给定的响应值,在像素邻域空间进行拟合,实现亚像素级别的角点检测。
函数:
cv2.cornerSubPix(
InputArray image,
InputOutputArray corners,
Size winSize,
Size zeroZone,
TermCriteria criteria
)
- image单通道输入图像,八位或者浮点数。
- corners是输入输出的关键点坐标集合。
- winSize表示插值计算时候窗口大小。
- zeroZone表示搜索区域中间的dead。 region边长的一半,有时用于避免自相关矩阵的奇异性。如果值设为(-1,-1)则表示没有这个区域。
- criteria角点精准化迭代过程的终止条件。
代码:
import numpy as np
import cv2 as cv
def process(image, opt=1):
# Detecting corners
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
corners = cv.goodFeaturesToTrack(gray, 100, 0.05, 10)
print(len(corners))
for pt in corners:
print(pt)
b = np.random.random_integers(0, 256)
g = np.random.random_integers(0, 256)
r = np.random.random_integers(0, 256)
x = np.int32(pt[0][0])
y = np.int32(pt[0][1])
cv.circle(image, (x, y), 5, (int(b), int(g), int(r)), 2)
# detect sub-pixel
winSize = (3, 3)
zeroZone = (-1, -1)
# Stop condition
criteria = (cv.TERM_CRITERIA_EPS + cv.TermCriteria_COUNT, 40, 0.001)
# Calculate the refined corner locations
corners = cv.cornerSubPix(gray, corners, winSize, zeroZone, criteria)
# display
for i in range(corners.shape[0]):
print(" -- Refined Corner [", i, "] (", corners[i, 0, 0], ",", corners[i, 0, 1], ")")
return image
src = cv.imread("tyt.png")
cv.imshow("input", src)
result = process(src)
cv.imshow('result', result)
cv.imwrite('result.jpg',result)
cv.waitKey(0)
cv.destroyAllWindows()
未完待续~
更多Opencv教程将持续发布!
欢迎关注哟~??????