《数字图像处理-OpenCV/Python》第17章:图像的特征描述
本书京东 优惠购书链接 https://item.jd.com/14098452.html
本书CSDN 独家连载专栏 https://blog.csdn.net/youcans/category_12418787.html
第17章:图像的特征描述
特征检测与匹配是计算机视觉的基本任务,包括检测、描述和匹配三个相互关联的步骤。广泛应用于目标检测、图像检索、视频跟踪和三维重建等诸多领域。
OpenCV提供了丰富的特征检测和匹配算法,不仅继承了cv::Feature2D 类,而且采用了统一的定义和封装。
17.1 角点检测之Harris算法
角是直线方向的快速变化,角点定义为两条边的交点,是简单高效的特征。角点检测(Corner Detection)是特征检测的基础,Harris算法是经典的角点检测算法。
Harris角点检测
Harris角点检测算法的原理是,通过检测窗口在图像上移动,计算移动前后窗口中像素的灰度变化。角点是两条边的交点,其特征是检测窗口沿任方向移动都会导致灰度的显著变化。
Harris算法计算梯度的协方差矩阵M,协方差矩阵形状为椭圆,长短半轴由特征值 ( λ 1 , λ 2 ) (λ_1, λ_2) (λ1,λ2)决定,方向由特征向量决定。定义如下的角点响应函数 R。
R = d e t ( M ) − k [ t r a c e ( M ) ] 2 d e t ( M ) = λ 1 ∗ λ 2 t r a c e ( M ) = λ 1 + λ 2 \begin{aligned}R =& det(M) - k [trace(M)]^2 \\&det(M) = \lambda _1 * \lambda _2 \\&trace(M) = \lambda _1 + \lambda _2\end{aligned} R=det(M)−k[trace(M)]2det(M)=λ1∗λ2trace(M)=λ1+λ2
角点响应 R 只与矩阵 M 的特征值 λ 1 , λ 2 \lambda _1,\lambda _2 λ1,λ2 有关,可以用来判断区域是拐角、边缘还是平坦:
- λ 1 , λ 2 \lambda _1,\lambda _2 λ1,λ2 较小时, ∣ R ∣ |R| ∣R∣ 较小,即各个方向上灰度基本不变,表明检测器处于平坦区域;
- λ 1 > > λ 2 \lambda _1 >> \lambda _2 λ1>>λ2 或 λ 2 > > λ 1 \lambda _2 >> \lambda _1 λ2>>λ1 时, R < 0 R <0 R<0 ,即灰度在某个方向变化,但在其正交方向不变化,表明检测器处于边缘区域;
- λ 1 , λ 2 \lambda _1,\lambda _2 λ1,λ2 较大且数值相当时,灰度在某个方向及其正交方向都变化强烈,表明存在角点或孤立点。
Harris角点检测算法的重复性好、检测效率高,应用比较广泛。
Shi-Tomas角点检测
Shi-Tomas算法是对Harris角点检测算法的改进,区别在于将角点响应函数修改如下。
R
=
m
i
n
(
λ
1
,
λ
2
)
R = min(\lambda _1 , \lambda _2)
R=min(λ1,λ2)
只有当梯度协方差矩阵M的特征值
λ
1
,
λ
2
λ_1, λ_2
λ1,λ2 都大于阈值时,才判定为角点。
OpenCV的角点检测函数
在OpenCV中提供了函数cv.cornerEigenValsAndVecs计算图像或矩阵的特征值和特征向量,函数cv.cornerMinEigenVal计算梯度矩阵的最小特征值,函数cv.cornerHarris实现Harris角点检测。
函数原型
cv.cornerHarris(src, blockSize, ksize, k[, dst, borderType]) → dst
cv.cornerEigenValsAndVecs(src, blockSize, ksize[, dst, borderType]) → dst
cv.cornerMinEigenVal(src, blockSize[, dst, ksize, borderType]) → dst
参数说明
src:输入图像,单通道,数据类型为CV_8U或浮点数类型。
dst:输出图像,角点响应函数,大小与src相同,格式为CV_32FC1。
blockSize:检测器的滑动窗口尺寸,为整数。
ksize:Sobel梯度算子的孔径,即卷积核的大小,为整数。
k:Harris角点响应函数的调节参数,通常取0.04~0.06。
borderType:边界扩充的类型,不支持BORDER_WRAP。
注意问题
⑴ 函数cv.cornerHarris返回值是如下的Harris的角点响应图像R。
R
=
d
s
t
(
x
,
y
)
=
d
e
t
(
M
(
x
,
y
)
)
−
k
∗
[
t
r
a
c
e
(
M
(
x
,
y
)
)
]
2
R=dst(x,y)=det(M(x,y))-k*[trace(M(x,y))]^2
R=dst(x,y)=det(M(x,y))−k∗[trace(M(x,y))]2
从角点响应图像中筛选大于检测阈值、且为局部最大值的点,就是图像的角点。检测阈值通常可以设为最大响应值的0.01~0.1。
⑵ 函数cv.cornerMinEigenVal与cv.cornerEigenValsAndVecs类似,区别在于它计算和保存矩阵M的最小特征值,即
m
i
n
(
λ
1
,
λ
2
)
min(λ_1 ,λ_2)
min(λ1,λ2)。
在OpenCV中提供了函数cv.goodFeaturesToTrack实现Shi-Tomas角点检测。
先使用cornerHarris或cornerMinEigenVal计算角点响应函数,最小特征值小于阈值的角点被剔除;并进行非最大值抑制,只保留(3×3)邻域中的局部最大值;最后按照角点响应函数的大小排序,输出前N个结果。
函数原型
cv.goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance[, corners, mask, blockSize, useHarrisDetector, k=0.04]) → corners
参数说明
src:输入图像,单通道,数据类型为CV_8U或浮点数类型。
corners:二维点向量集合的坐标(x,y),形如(n,1,2)的Numpy数组,浮点数。
maxCorners:角点数量的最大值N,整数。
qualityLevel:角点阈值系数,浮点数,取值范围0.0~1.0。
minDistance:角点之间的最小欧式距离。
mask:掩模图像,指定检测角点的区域,可选项。
blockSize:检测器的滑动窗口尺寸,可选项,默认值为3。
k:Harris角点响应函数的调节参数,可选项,默认值0.04。
useHarrisDetector:计算角点响应的方法,默认值false,使用cornerMinEigenVal计算,true表示使用cornerHarris计算。
注意问题
⑴ 输出参数corners是形如(n,1,2)的Numpy数组,表示检测到n个角点的坐标(x,y)。
⑵ 检测阈值是阈值系数qualityLevel与最大响应值的乘积,小于阈值的角点都被拒绝。例如,最大响应为1500,系数为0.1,则检测阈值为150。
⑶ 剔除间距小于maxDistance的角点,实现非最大值抑制方法,避免重复的邻近角点。
【例程1701】角点检测之Harris算法和Shi-Tomas算法
本例程示例Harris角点检测算法和Shi-Tomas角点检测算法的使用。
Harris角点检测函数的返回值是角点响应图像,需要进行阈值处理才能得到角点坐标。Shi-Tomas角点检测函数的返回值是角点坐标。
# 【1701】角点检测之Harris算法和Shi-Tomas算法
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
if __name__ == '__main__':
img = cv.imread("../images/Fig1201.png", flags=1)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# Harris 角点检测算法
dst = cv.cornerHarris(gray, 5, 3, k=0.04) # 角点响应图像,坐标(y,x)
# Harris[dst>0.1*dst.max()] = [0,0,255] # 筛选角点,红色标记
stack = np.column_stack(np.where(dst>0.2*dst.max())) # 阈值筛选角点 (n,2)
corners = stack[:, [1, 0]] # 调整坐标次序:(y,x) -> (x,y)
print("num of corners by Harris: ", corners.shape)
imgHarris = img.copy()
for point in corners:
cv.drawMarker(imgHarris, point, (0,0,255), cv.MARKER_CROSS, 10, 1) # 在点(x,y)标记
# Shi-Tomas 角点检测算法
maxCorners, qualityLevel, minDistance = 100, 0.1, 5
corners = cv.goodFeaturesToTrack(gray, maxCorners, qualityLevel, minDistance) # 角点坐标 (x,y)
corners = np.squeeze(corners).astype(np.int) # 检测到的角点 (n,1,2)->(n,2)
print("num of corners by Shi-Tomas: ", corners.shape[0])
imgShiTomas = np.copy(img)
for point in corners: # 注意坐标次序
cv.drawMarker(imgShiTomas, (point[0], point[1]), (0,0,255), cv.MARKER_CROSS, 10, 2) # 在点(x,y)标记
plt.figure(figsize=(9, 3.3))
plt.subplot(131), plt.title("1. Original")
plt.axis('off'), plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.subplot(132), plt.title("2. Harris corners")
plt.axis('off'), plt.imshow(cv.cvtColor(imgHarris, cv.COLOR_BGR2RGB))
plt.subplot(133), plt.title("3. Shi-tomas corners")
plt.axis('off'), plt.imshow(cv.cvtColor(imgShiTomas, cv.COLOR_BGR2RGB))
plt.tight_layout()
plt.show()
运行结果:
num of corners by Harris: 589
num of corners by Shi-Tomas: 66
图17-1 Harris角点检测和Shi-Tomas角点检测
程序说明:
⑴ 程序运行结果如图17-1所示。子图1是原始图像,子图2是Harris角点检测的结果,子图3是Shi-Tomas角点检测的结果。
⑵ 运行结果表明,Harris算法函数检测到的角点数量远大于Shi-Tomas算法函数的结果。这是由于角点周围像素的响应值都很高,都被识别为角点,因此Harris函数会检测到大量重复的角点。
版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/140212758)
Copyright 2024 youcans, XUPT
Crated:2024-07-05
《数字图像处理-OpenCV/Python》 独家连载专栏 : https://blog.csdn.net/youcans/category_12418787.html