1、原理概述
我们知道,图像的空间域和频域构成了描述图像的两种方式,前者对应图像中不同灰度的分布,后者则用于描述图像灰度变化的频率。那么从空间域来看,图像滤波就是去除图像中的噪声,提取感兴趣的部分;而在频域中,滤波的作用是增强部分频段,同时限制(或衰减)其他频段。按照频域滤波的特点,滤波器分为低通滤波器和高通滤波器,前者去除图像中的高频成分,后者去除低频成分。
2、均值滤波器
均值滤波的原理是将每个像素替换为相邻像素的平均值(或加权平均值),它是一种低通滤波器。OpenCV中的API为blur,用法如下:
void blur(InputArray src,
OutputArray dst,
Size ksize,
Point anchor=Point(-1,-1),
int borderType=BORDER_DEFAULT )
Parameters:
src – 原始图像;
dst – 目标图像 ;
ksize – 滤波器大小;
anchor – 指定锚点位置(被平滑点), 如果是负值,锚点为滤波器的中心点,默认参数为Point(-1, -1);
borderType – 计算图像边界时用于指定滤波器越界地方的像素类型。
//示例
cv::blur(image, result, cv::Size(5, 5))
若将每个像素替换为相邻像素的加权平均值,则API函数为GaussianBlur,用法如下:
void GaussianBlur(InputArray src,
OutputArray dst,
double sigmaX,
double sigmaY=0,
int borderType=BORDER_DEFAULT )
src: 输入图像
dst: 输出图像
Ksize(w, h): 定义滤波器的大小。 w 和 h 必须是正奇数,否则将使用 σx 和 σy 参数来计算内核大小。
σx:x 方向标准方差, 如果是 0 则 σx 使用内核大小计算得到。
σy:y 方向标准方差, 如果是 0 则 σy 使用内核大小计算得到。
3、中值滤波器
中值滤波器是一种非线性的低通滤波器,其原理是将每个像素替换为其相邻像素点的中值。中值滤波器对去除椒盐噪点尤为有用,并且具有保留图像边缘信息的优点 。OpenCV中的API为medianBlur,用法如下:
void medianBlur(InputArray src,
OutputArray dst,
int ksize)
参数作用与均值滤波器的类似。
4、方向滤波器
常用的方向滤波器是Sobel算子,它是一种高通滤波器,所以可用于图像的边缘检测。由于Sobel算子滤波具有方向性,因此也被称为方向滤波器。方向滤波器的原理:Sobel算子是一个离散微分算子,它用来计算图像灰度函数的近似梯度,即Sobel算子可用来度量图像在垂直和水平方向的变化,由于像素点的离散特性,所以Sobel算子通过水平和垂直方向下进行像素差分给出图像梯度的近似,差分算子如下:
OpenCV中的API为Sobel,用法如下:
void Sobel(InputArray src,
OutputArray dst,
int xorder,
int yorder,
int ksize=3,
double scale=1,
double delta=0,
int borderType=BORDER_DEFAULT )
Parameters:
src – 输入图像;
dst – 输出图像;
ddepth – 图像类型;
xorder – 滤波器 x 方向偏导的阶数;
yorder – 滤波器y 方向偏导的阶数;
ksize – 滤波器的大小,其值必须为 1, 3, 5, or 7;
scale – 缩放值;
delta – 偏移量 ;
borderType – 计算图像边界时用于指定滤波器越界地方的像素类型。
Demo如下:
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;
int main()
{
Mat dst;
Mat src = imread("test.jpg");
if(!src.data)
{
cout<<"image is not built!"<<endl;
return -1;
}
cvtColor( src, src, CV_RGB2GRAY );
imshow("src",src);
//水平方向的Sobel算子
Sobel(src, dst, CV_8U, 1, 0, 3, 0.4, 128);
imshow("xSobel", dst);
//垂直方向的Sobel算子
Sobel(src, dst, CV_8U, 0, 1, 3, 0.4, 128);
imshow("ySobel", dst);
waitKey();
return 0;
}
运行结果如下:
Sobel算子是求像素点的一阶导,OpenCV还提供了计算二阶导进行滤波的函数,常用的有拉普拉斯变换法。拉普拉斯(Laplacian)是一种线性的高通滤波器,其原理与Sobel算子类似,其滤波器均可看成微分方程的数值形式,拉普拉斯方程如下:
OpenCV中的API为Laplacian,用法如下:
void Laplacian(InputArray src,
OutputArray dst,
int ddepth,
int ksize=1,
double delta=0,
int borderType=BORDER_DEFAULT )
参数的意义与Sobel函数类似。
最后,Sobel算子和Laplacian算子作为高通滤波器,它们具有去除图像中低频成分,保留高频成分的特性,因此常用于图像的边缘检测。但需要注意的是,Laplacian对噪点特别敏感,所以用于边缘检测时,通常在之前的操作中一般进行低通滤波器来去除噪点。