图像滤波与边缘检测
直接采集到的图像可能带有噪声的干扰,因此去除噪声是图像预处理中十分重要的一步。图像滤波是图像噪声去除的重要方式。
图像卷积
卷积操作广泛应用于信号处理领域,而图像本质上可以视为一种二维信号数据。
卷积过程可以理解为一个卷积模板(卷积核)在图像上逐像素移动,对模板覆盖区域内的像素值进行加权求和,计算结果作为模板中心位置的输出值。
为避免卷积输出值超出数据表示范围,通常对卷积模板进行归一化处理,使模板中所有元素的和为1。
卷积运算所需函数如下:
filter2D(src, dst, ddepth, kernel, anchor=Point(-1, -1), delta, borderType=BORDER_DEFAULT);
src
与dst
为源图像和输出图像,ddepth
为输出图像的数据类型(深度)
kernel
为卷积模板矩阵,anchor
为模板中心,(-1, -1)表示模板中心位于模板的中心元素。
delta
为偏值,在计算中会将其加上
borderType
为像素外推法选择标志
示例:
#include<opencv2/opencv.hpp>
#include<iostream>
#include<stdio.h>
using namespace std;
using namespace cv;
int main(void) {
Mat img = imread("test.jpg");
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
Mat kernel = (Mat_<float>(3, 3) << 1, 2, 1,
2, 0, 2,
1, 2, 1);
Mat kernel_norm = kernel/12; // 归一化
Mat result, result_norm;
filter2D(img, result,-1 , kernel);
filter2D(img, result_norm, -1, kernel_norm);
imshow("Original Image", img);
imshow("Result Image", result);
imshow("Result Image Normalized", result_norm);
waitKey(0);
return 0;
}
卷积提取特征原理
卷积核通过在图像上滑动,每次只关注一个小的局部区域(感受野),这使得它能够专注于图像中的小块区域,识别局部特征如边缘、角点、纹理等,同时避免全局干扰,不会被图像其他无关区域的信息干扰。
卷积过程本质上是模板匹配。卷积核与图像区域进行点乘求和,计算相似度,当图像区域与卷积核模式相似时,产生强烈的响应值,响应值的大小和位置表明了特征的强度和位置。
并且同一个卷积核在整个图像上共享权重参数,无论特征出现在图像的哪个位置,都能被同一个卷积核检测到,相比全连接层,大大减少了计算的参数数量,且对图像中目标的小幅移动具有一定的容忍度。
线性滤波
图像滤波的主要目的是去除不重要的信息,突出关键特征。主要应用包括:噪声消除和特征提取。
线性滤波操作与图像卷积操作过程相似,此时卷积模板称为滤波模板。
均值滤波
将模板中所有像素值的平均值作为模板中心的输出值。
优点:在像素值变换趋势一致时去除噪声影响。
缺点:缩小像素间的差距,使细节变模糊。
blur(src, dst, ksize, anchor=Point(-1, -1), borderType=BORDER_DEFAULT);
ksize
为滤波模板大小,anchor
为模板基准点
borderType
为像素外推法选择标志
示例:
#include<opencv2/opencv.hpp>
#include<iostream>
#include<stdio.h>
using namespace std;
using namespace cv;
int main(void) {
Mat img = imread("/home/bandiera/桌面/1/test.jpg");
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
imshow("Original Image", img);
imshow("Gray Image", gray);
Mat result1, result2;
blur(img, result1, Size(13, 13));//size越大,结果越模糊
blur(gray, result2, Size(13, 13));
imshow("Blur Image", result1);
imshow("Blur Gray Image", result2);
waitKey(0);
}
方框滤波
方框滤波是均值滤波的一般形式,可以选择是否对求和结果进行归一化。
boxFilter(src, ast, ddepth, ksize, anchor, normalize, borderType);
normalize
是否进行归一化,默认为true
(此时等同于均值滤波)
当normalize
=false
时,直接输出像素值的和
高斯滤波
高斯滤波主要用于去除高斯噪声,其滤波模板的权重符合高斯分布。
GaussianBlur(src, dst, ksize, sigmaX, sigmaY, borderType);
sigmaX
为X方向高斯核的标准差,sigmaY
为Y方向的标准差,如果为0则等同sigmaX
。若二者均为0,则自动计算。
getGaussianKernel(ksize, sigma, ktype=CV_64F);
ksize
为滤波器尺寸,必须为正奇数,sigma
为标准差,ktype
为滤波器系数数据类型。
这个函数用于生成指定尺寸的高斯滤波器。
可分离滤波
此前的滤波函数使用的滤波器都是固定形式的滤波器,需要手动去调整滤波模板。故opencv4给出了根据根自定义滤波器实现滤波的函数。
滤波过程中不会对原图像进行修改,故滤波是一个并行过程。并且往不同方向分别滤波的结果与整体滤波的结果一致,故有可分离性。
对于某些滤波器,可以将二维滤波分解为两个一维滤波的组合,从而提高计算效率。
opencv4提供了可根据两个方向的滤波器进行联合滤波的函数,如下:
sepFilter2D(src, dst, ddepth. kernelX, kernelY, anchor, delta, borderType);
kernelX
为x方向的滤波器,kernelY
为y方向的滤波器
非线性滤波
非线性滤波的计算结果不是由滤波器内的像素值通过线性组合计算得到的,其过程可能包含排序、逻辑运算等。线性滤波只是令噪声更柔和,而不会完全去除噪声,此时使用非线性滤波的效果可能更好。
非线性滤波主要包含中值滤波和双边滤波。
中值滤波
中值滤波使用滤波器覆盖区域内所有像素值的中位数作为输出,对椒盐噪声具有良好的去除效果。
以滤波器范围内的所有像素值的中值作为输出。由于涉及排序,其处理时间较大。
medianBlur(src, dst, ksize);
ksize
为滤波器大小,只能为大于1的奇数
不能用于两通道和五通道及以上的Mat
双边滤波
双边滤波能够在去除噪声的同时保持边缘信息,是一种边缘保持滤波器。
bilateralFilter(src, dst, d, sigaColor, sigmaSpace, borderType);
d
为滤波过程中每个像素领域的直径,若为非正数,则由sigmaSpace
决定。建议为5
sigmaColor
为颜色空间滤波器的标准差值,参数越大,产生的半相等颜色区域越大。
sigmaSpace
为空间坐标滤波器的标准差值,参数越大,越远的像素会相互影响。
两个差值小于10时滤波效果弱,大于150时过强。
缺点:性能较差
边缘检测
边缘指像素灰度值突然发生变化的地方,可通过计算图像梯度寻找边缘。
计算得到的梯度可能是正数,也可能是负数。以下给出了求矩阵各元素绝对值的函数:
convertScaleAbs(src, dst, alpha = 1, bats = 0);
alpha
为缩放因子,默认参数为1,即不进行缩放
bats
为偏值,默认为不添加
Sobel算子
Sobel
算子是经典的边缘检测算子,可以检测水平和垂直方向的边缘。
Sobel(src, dst, ddepth, dx, dy, ksize=3, scale=1, delta=0, borderType);
dx
为X方向的差分阶数,dy
为Y方向的差分阶数
ksize
为算子大小,必须为1、3、5、7
scale
为缩放因子,delta
为偏置
一般情况下,差分阶数为1,ksize
为3;阶数为2,ksize
为5
Scharr算子
Sobel
对图像中较弱的边缘提取效果较差,故需要加宽像素间的差距
Scharr
算子对弱边缘的检测效果优于Sobel
算子,能够提供更高的检测精度。Scharr
滤波器尺寸固定为3*3。
Scharr(src, dst, ddepth, dx, dy, scale, delta, borderType);
同Sobel
,dx
、dy
不能同时为0
生成边缘检测滤波器
可以通过以下函数获得不同尺寸和阶次的Sobel或Scharr滤波器:
getDerivKernels(kx, ky, dx, dy, ksize, normalize, ktype);
kx
、ky
、dx
、dy
分别为行滤波器的输出矩阵、列滤波器的输出矩阵、X方向的导数阶次、Y方向的导数阶次
ksize
为滤波器大小,可选参数为FILTER_SCHARR
、1、3、5、7
normalize
为归一化
ktype
为滤波器系数类型
Laplacian算子(各项同性)
使用Laplacian算子提取边缘可以不分别检测X方向和Y方向,只需要一次边缘检测。Laplacian是一种二阶导数算子,对噪声敏感,故须配合高斯滤波。
L
a
p
l
a
c
i
a
n
(
f
)
=
∂
2
f
∂
x
2
+
∂
2
f
∂
y
2
Laplacian(f)=\frac{\partial^2 f}{\partial x^2}+\frac{\partial^2 f}{\partial y^2}
Laplacian(f)=∂x2∂2f+∂y2∂2f
Laplacian(src, dst, ddepth, kssize=1, scale, delta, borderType);
ddepth
为输出图像深度,-1为自动设置
ksize
必须为正奇数
Canny算法(常用)
Canny
边缘检测算法是目前最优秀的边缘检测算法之一,能够识别强边缘和弱边缘,并基于连通性给出完整的边缘信息,抗噪声能力强。
其原理分为五个步骤:
1.使用高斯滤波平滑图像。
2.通过Sobel
算子计算各个方向的梯度,随后计算梯度的方向和幅值。
3.应用非极大值抑制算法消除边缘检测带来的杂散影响。
4.应用双阈值法划分强边缘和弱边缘。
5.消除孤立的弱边缘。
Canny(image,edges, threshold1, threshold2, apertureSize=3, L2gradient=false);
image
输入图像,必须是CV_8U
的单通道或三通道图像
edges
输出图像
threshold
滞后阈值
apertureSize Sobel
算子的直径
L2gradient
计算图像梯度幅值的方法