『youcans 的 OpenCV 例程300篇 - 总目录』
【youcans 的 OpenCV 例程 300篇】240. OpenCV 中的 Shi-Tomas 角点检测
角是直线方向的快速变化。角点通常被定义为两条边的交点,或者说角点的邻域应该具有两个不同区域的不同方向的边界。
角是高度有效的特征。角点检测(Corner Detection)广泛应用于运动检测、图像匹配、视频跟踪、三维重建和目标识别。
Shi-Tomas 算法是对 Harris角点检测算法的改进,一般会比Harris算法得到更好的角点。
6.1 哈里斯-斯蒂芬斯角检测器(Harris)
Harris角点检测算法的原理是,通过检测窗口在图像上移动,计算移动前后窗口中像素的灰度变化。角点是两条边的交点,其特征是检测窗口沿任意方向移动都会导致灰度的显著变化。
对于点 ( x , y ) (x,y) (x,y),令 w ( x , y ) w(x,y) w(x,y) 为矩形检测窗口或高斯检测窗口, I ( x , y ) I(x,y) I(x,y) 是检测窗口在点 ( x , y ) (x,y) (x,y) 的灰度值, I ( x + u , y + v ) I(x+u,y+v) I(x+u,y+v) 是检测窗口滑动 ( u , v ) (u,v) (u,v) 距离之后的灰度值。
计算窗口
w
(
x
,
y
)
w(x,y)
w(x,y) 滑动
(
u
,
v
)
(u,v)
(u,v) 距离之后的灰度变化:
E
(
u
,
v
)
=
∑
x
,
y
w
(
x
,
y
)
[
I
(
x
+
u
,
y
+
v
)
−
I
(
x
,
y
)
]
2
E(u,v) = \sum _{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
对于很小的位移
(
u
,
v
)
(u,v)
(u,v),使用一阶泰勒展开进行简化:
E
(
u
,
v
)
=
∑
x
,
y
w
(
x
,
y
)
[
I
(
x
,
y
)
+
u
I
x
+
v
I
y
+
O
(
u
2
,
v
2
)
−
I
(
x
,
y
)
]
2
≈
∑
x
,
y
w
(
x
,
y
)
[
u
2
I
x
2
+
2
u
v
I
x
I
y
+
v
2
I
y
2
]
≈
[
u
,
v
]
∑
x
,
y
w
(
x
,
y
)
[
I
x
I
x
I
x
I
y
I
x
I
y
I
y
I
y
]
[
u
v
]
\begin{aligned}E(u,v) = &\sum_{x,y} w(x,y) [I(x,y) + uI_x + vI_y +O(u^2,v^2)- I(x,y)]^2 \\\approx & \sum_{x,y} w(x,y) [u^2 I_x^2 + 2uv I_x I_y + v^2 I_y^2] \\\approx & [u,v] \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}\begin{bmatrix}u\\v\end{bmatrix}\end{aligned}
E(u,v)=≈≈x,y∑w(x,y)[I(x,y)+uIx+vIy+O(u2,v2)−I(x,y)]2x,y∑w(x,y)[u2Ix2+2uvIxIy+v2Iy2][u,v]x,y∑w(x,y)[IxIxIxIyIxIyIyIy][uv]
I
x
,
I
y
I_x,I_y
Ix,Iy 分别是在 x, y 方向的导数,可以由 Sobel 梯度算子求出。
记 M 为梯度的协方差矩阵:
M
=
∑
x
,
y
w
(
x
,
y
)
[
I
x
I
x
I
x
I
y
I
x
I
y
I
y
I
y
]
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}
M=x,y∑w(x,y)[IxIxIxIyIxIyIyIy]
在几何模型中通过判断两个特征值的大小,来判定像素的属性。矩阵 M 是 I x , I y I_x,I_y Ix,Iy 的二次函数,可以表示为椭圆形状,椭圆的长短半轴由矩阵 M 的特征值 λ 1 , λ 2 \lambda _1,\lambda _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
k 是调节参数(通常取 0.04~0.06)。
角点响应函数 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 或 $ \lambda _2 >> \lambda _1$ 时, R < 0 R <0 R<0 ,即灰度在某个方向变化,但在其正交方向不变化,表明检测器处于边缘区域;
- λ 1 , λ 2 \lambda _1,\lambda _2 λ1,λ2 较大且 λ 1 ∼ λ 2 \lambda _1 \sim \lambda _2 λ1∼λ2时, ∣ R ∣ |R| ∣R∣ 很大,即灰度在所有方向都发生重大变化,表明检测器包含角点(或孤立点。
6.3 OpenCV 中的 Shi-Tomas 角检测器
Shi-Tomas 算法是对 Harris角点检测算法的改进,一般会比Harris算法得到更好的角点。
Harris 算法中的角点响应函数为:
R
=
λ
1
λ
2
−
k
(
λ
1
+
λ
2
)
2
R =\lambda _1 \lambda _2 - k (\lambda _1 + \lambda _2)^2
R=λ1λ2−k(λ1+λ2)2
Shi-Tomas 算法将角点响应函数修改为:
R
=
m
i
n
(
λ
1
,
λ
2
)
R = min (\lambda _1 , \lambda _2 )
R=min(λ1,λ2)
只有当 M 矩阵的特征值 $ \lambda _1,\lambda _2$ 都大于最小值 λ m i n \lambda {min} λmin 时,才将其视为拐角。
OpenCV 中提供了 Shi-Tomas 角点检测函数 cv.goodFeaturesToTrack() 。
函数说明:
cv.goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance[, corners=None, mask=Mat(), blockSize=3, useHarrisDetector=false, k=0.04]) → corners
函数 cv.goodFeaturesToTrack 通过 Shi-Tomasi 方法找出图像中最突出的 N 个角点。
参数说明:
- src:输入图像,单通道的 8 位图像或 32 位浮点数图像
- corners:输出向量,检测到的角点
- maxCorners:获取的角点数量的上限阈值
- qualityLevel:可接受的角点质量最低阈值,取值范围 0~1
- minDistance:可接受的角点之间最小的欧式距离
- mask:掩模区域,仅在掩模区域检测角点
- blockSize:邻域尺寸,默认值为 3
- k:Harris 检测器调节参数,默认值 0.04
- useHarrisDetector :默认值 False,使用 cornerMinEigenVal 的参数,True 表示使用 Harris 检测器
注意事项:
- 函数使用 cornerMinEigenVal 或 cornerHarris 计算出每个像素的角点响应结果。
- 以 qualityLevel 与最大角点值相乘作为最小特征值(cornerMinEigenVal)或响应函数值(cornerHarris),小于该值的角点都被拒绝。例如,最大响应值为 1500,系数为 0.1,则响应值小于 150 的角点都被放弃。
- 小于 maxDistance 距离的角点被拒绝,以避免得到相邻特征点。
例程 14.21:特征检测之 Shi-tomas 角检测器
# 14.21 特征检测之 Shi-tomas 角检测器
img = cv2.imread("../images/sign04.png", flags=1) # (300, 300, 3)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Harris 检测角点
dst = cv2.cornerHarris(gray, 2, 3, k=0.04)
# Harris[dst > 0.01*dst.max()] = [0, 0, 255] # 筛选角点,红色标记
corners = np.column_stack(np.where(dst>0.1*dst.max())) # 筛选并返回角点坐标 (y,x)
corners = corners.astype(np.int) # 检测到的角点的点集 (y,x), (92, 2)
imgHarris = np.copy(img)
for point in corners: # 注意坐标次序
cv2.circle(imgHarris, (point[1], point, 4, (0,0,255), 2) # # 在点 (x,y) 处画圆
# Shi-tomas 检测角点
corners = cv2.goodFeaturesToTrack(gray, 30, 0.3, 5) # (30, 1, 2)
corners = np.squeeze(corners).astype(np.int) # (30, 1, 2)->(30,2) 角点坐标 (x,y)
imgShiTomas = np.copy(img)
for point in corners:
cv2.circle(imgShiTomas, point, 4, (0,0,255), 2) # # 在点 (x,y) 处画圆
plt.figure(figsize=(9, 6))
plt.subplot(131), plt.axis('off'), plt.title("Origin")
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(132), plt.axis('off'), plt.title("Harris corners")
plt.imshow(cv2.cvtColor(imgHarris, cv2.COLOR_BGR2RGB))
plt.subplot(133), plt.axis('off'), plt.title("Shi-tomas corners")
plt.imshow(cv2.cvtColor(imgShiTomas, cv2.COLOR_BGR2RGB))
plt.tight_layout()
plt.show()
【本节完】
版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/125828053)
Copyright 2022 youcans, XUPT
Crated:2022-7-15238. OpenCV 中的 Harris 角点检测
239. Harris 角点检测之精确定位(cornerSubPix)
240. OpenCV 中的 Shi-Tomas 角点检测