OpenCV实战(13)——高通滤波器及其应用
Posted 盼小辉丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV实战(13)——高通滤波器及其应用相关的知识,希望对你有一定的参考价值。
OpenCV实战(13)——高通滤波器以及应用
0. 前言
在频域分析中,滤波器是一种放大图像某些频带同时减少其他频带的操作,低通滤波器 (low-pass filters
) 是消除图像高频成分的滤波器,而高通滤波器 (high-pass filters
) 消除图像的低频成分。在《滤波器》一节中,已经介绍了低通滤波器的实现以及应用,在本节中,我们介绍另一类重要的滤波器,即高通滤波器。
1. 检测图像边缘
在《滤波器》一节中,我们已经介绍了如何使用核矩阵进行线性滤波,使用低通滤波器通过去除或衰减图像高频分量来模糊图像。在本节中,我们将执行相反的变换,即放大图像的高频内容,介绍高通滤波器用于执行边缘检测。
1.2 Sobel 滤波器
本节主要介绍 Sobel
滤波器,它也被称为定向滤波器,因为它仅影响垂直或水平图像频率,具体取决于使用的滤波器核。
(1) 要在水平方向应用 Sobel
算子,使用以下参数调用函数:
cv::Mat sobelX;
cv::Sobel(image, // 输入
sobelX, // 输出
CV_8U, // 图像类型
1, 0, // 核
3, // 核大小
0.4, 128); // 缩放和偏移因子
(2) 垂直滤波与水平滤波类似,可以通过使用以下方式实现:
cv::Sobel(image, sobelY, CV_8U, 0, 1, 3, 0.4, 128);
生成的输出用 8
位图像 (CV_8U
) 表示。水平 Sobel
算子操作结果如下所示:
Sobel
算子的核包含正值和负值,Sobel
滤波器的结果通常用 16
位有符号整数图像 (CV_16S
) 计算,为了使结果可显示为 8
位图像,我们使用如下表示:使用零值对应于灰度级 128
,负值由较暗的像素表示,而正值由较亮的像素表示。垂直 Sobel
算子操作结果如下所示:
以上图像类似于照片编辑软件中的浮雕效果,实际上,浮雕图像转换通常基于方向滤镜完成。
(3) 然后将以上两个结果(垂直和水平 Sobel
)进行组合,以获得 Sobel
滤波器的范数结果:
// 计算 Sobel 范数
cv::Sobel(image, sobelX, CV_16S, 1, 0);
cv::Sobel(image, sobelY, CV_16S, 0, 1);
cv::Mat sobel;
sobel = abs(sobelX) + abs(sobelY);
(4) 使用 convertTo
方法的缩放参数可以在图像中显示 Sobel
范数结果,得到的图像中使用零值表示白色像素,而较大的值用于表示灰色阴影:
double sobmin, sobmax;
cv::minMaxLoc(sobel, &sobmin, &sobmax);
// 转换为 8 位图像
cv::Mat sobelImage;
sobel.convertTo(sobelImage, CV_8U, -255./sobmax, 255)
从上图中可以看出 Sobel
算子被称为边缘检测器的原因,对该图像进行阈值处理,可以获得图像轮廓的二值图:
// 对 Sobel 范数应用阈值
cv::Mat sobelThresholded;
cv::threshold(sobelImage, sobelThresholded, 225, 255, cv::THRESH_BINARY);
Sobel
算子是一个经典的边缘检测线性滤波器,它基于简单的 3x3
核,垂直和水平核分别具有以下结构:
[ − 1 0 1 − 2 0 2 − 1 0 1 ] [ − 1 − 2 − 1 0 0 0 1 2 1 ] \\left[ \\beginarrayccc -1 & 0 & 1\\\\ -2 & 0 & 2\\\\ -1 & 0 & 1\\\\\\endarray\\right] \\left[ \\beginarrayccc -1 & -2 & -1\\\\ 0 & 0 & 0\\\\ 1 & 2 & 1\\\\\\endarray\\right] −1−2−1000121 −101−202−101
如果我们将图像视为一个二维函数,那么 Sobel
算子就可以看作是图像在垂直和水平方向上的变化的度量。在数学中,这种度量称为梯度,定义为由函数在两个正交方向上的一阶导数构成的二维向量:
g
r
a
d
(
I
)
=
[
∂
I
∂
x
,
∂
I
∂
y
]
T
grad(I)=[\\frac \\partial I \\partial x,\\frac \\partial I \\partial y]^T
grad(I)=[∂x∂I,∂y∂I]T
因此,Sobel
算子在水平和垂直方向上计算图像梯度的近似值,对目标像素周围的窗口进行操作,以减少噪声的影响。cv::Sobel
函数计算图像与 Sobel
核的卷积结果,其完整调用形式如下:
cv::Sobel(image, // 输入
sobel, // 输出
image_depth, // 图像类型
xorder, yorder, // 指定核
kernel_size, // 核尺寸
alpha, beta); // 缩放和偏移
我们可以将结果写入无符号字符、有符号整数或浮点图像,如果结果落在图像像素域之外,将应用饱和运算。最后两个参数用于将结果存储在图像中之前将结果缩放(乘以) alpha
并添加偏移量 beta
,在上一节生成的图像中,Sobel
值 0
由中灰度级 128
表示;每个 Sobel
掩码对应一个方向的导数,因此,使用两个参数来指定应用的内核:x
和 y
方向的导数阶数,例如,通过为 xorder
和 yorder
参数指定 1
和 0
来使用水平 Sobel
核,将而指定 0
和 1
则使用垂直 Sobel
核,我们也可以使用其他组合,但这两种是最常用的组合(二阶导数将在下一节中介绍);最后,也可以使用其他尺寸的核,例如,值 1
、3
、5
和 7
,大小为 1
的核对应于一维 Sobel
滤波器( 1x3
或 3x1
)。
由于梯度是一个二维向量,它包含一个范数和一个方向,梯度向量的范数表示梯度变化的幅度,它通常使用欧几里得范数(也称为 L2
范数)计算:
∣
g
r
a
d
(
I
)
∣
=
(
∂
I
∂
x
)
2
+
(
∂
I
∂
y
)
2
|grad(I)|=\\sqrt (\\frac \\partial I \\partial x)^2+(\\frac \\partial I \\partial y)^2
∣grad(I)∣=(∂x∂I)2+(∂y∂I)2
然而,在图像处理中,梯度范数通常使用 L1
范数计算(绝对值之和),它可以以更低的计算成本得到接近 L2
范数的计算结果:
sobel= abs(sobelX)+abs(sobelY);
梯度向量总是指向变化最陡峭的方向,对于图像而言,这意味着梯度方向会与边缘正交,从较暗的方向指向较亮的方向,梯度方向可以使用以下公式计算:
a
t
a
n
(
g
r
a
d
(
I
)
)
atan(grad(I))
atan(grad(I))
大多数情况下,对于边缘检测,只需要计算范数。但是,如果同时需要范数和方向,可以使用以下 OpenCV
函数:
cv::Sobel(image, sobelX, CV_32F, 1, 0);
cv::Sobel(image, sobelY, CV_32F, 0, 1);
// 计算梯度的 L2 范数和方向
cv::Mat norm, dir;
cv::cartToPolar(sobelX, sobelY, norm, dir);
默认情况下,方向以弧度计算,需添加 true
作为附加参数将弧度制转换为角度值。
通过在梯度幅度上应用阈值,可以获得二值边缘图像,其关键在于设置合适的阈值。如果阈值太低,会保留太多(粗)边缘,而如果阈值太高,则会得到较多断边。例如下图是使用较高阈值得到的二值边缘图像:
可以使用滞后阈值技术获得合适的阈值。也可以在应用微分滤波器之前应用高斯平滑滤波器,能够降低噪声影响。接下来,我们将介绍一些其他梯度算子。
1.2 梯度算子
为了估计像素位置的梯度,Prewitt
算子使用以下矩阵核:
[
−
1
0
1
−
1
0
1
−
1
0
1
]
[
−
1
−
1
−
1
0
0
0
1
1
1
]
\\left[ \\beginarrayccc -1 & 0 & 1\\\\ -1 & 0 & 1\\\\ -1 & 0 & 1\\\\\\endarray\\right] \\left[ \\beginarrayccc -1 & -1 & -1\\\\ 0 & 0 & 0\\\\ 1 & 1 & 1\\\\\\endarray\\right]
−1−1−1000111
−101−101−101
Roberts
算子基于简单的 2x2
矩阵核:
[
1
0
0
−
1
]
[
0
1
−
1
0
]
\\left[ \\beginarrayccc 1 & 0\\\\ 0 & -1\\\\\\endarray\\right] \\left[ \\beginarrayccc 0 & 1\\\\ -1 & 0\\\\\\endarray\\right]
[100−1][0−110]
当需要更准确地估计梯度方向时,应当首选 Scharr
算子:
[
−
3
0
3
−
10
0
10
−
3
0
3
]
[
−
3
−
10
−
3
0
0
0
1
1
1
]
\\left[ \\beginarrayccc -3 & 0 & 3\\\\ -10 & 0 & 10\\\\ -3 & 0 & 3\\\\\\endarray\\right] \\left[ \\beginarrayccc -3 & -10 & -3\\\\ 0 & 0 & 0\\\\ 1 & 1 & 1\\\\\\endarray\\right]
−3−10−30003103
−301以上是关于OpenCV实战(13)——高通滤波器及其应用的主要内容,如果未能解决你的问题,请参考以下文章