常用滤波器
均值滤波
均值滤波也称为线性滤波,其采用的主要方法为邻域平均法。线性滤波的基本原理是用均值代替原图像中的各个像素值,即对待处理的当前像素点(x,y),选择一个模板,该模板由其近邻的若干像素组成,求模板中所有像素的均值,再把该均值赋予当前像素点(x,y),可用下面公式表示:
特点:均值滤波本身存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点。
中值滤波
中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点。
特点:中值滤波对脉冲噪声有良好的滤除作用,特别是在滤除噪声的同时,能够保护信号的边缘,使之不被模糊。这些优良特性是线性滤波方法所不具有的。
高斯滤波
二维高斯分布
高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。而加权的权重就来自根据输入参数生成的二位高斯分布。
特点:图像大多数噪声均属于高斯噪声,因此高斯滤波器应用也较广泛。高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像去噪。
双边滤波
双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近的和像素值相似度的一种折中处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。
空间域(spatial domain S)
像素范围域(range domain R)
总的来说,就是当像素差值大于阈值(即有边缘存在)时,将滤波分为两部分进行,而不影响到边缘分别进行高斯滤波。构造为下面的式子:
特点:双边滤波器顾名思义比高斯滤波多了一个高斯方差,它是基于空间分布的高斯滤波函数,所以在边缘附近,离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波。双边滤波常用于美艳磨皮等应用中。
API介绍
- 均值滤波
-
blur(src, dst, Size(5, 5)); //源图片,生成图片,卷积核大小 //卷积核大小长选用正方形的奇数边长,也可选用奇数长和宽的矩形,但不常用可根据实际情况选定
- 中值滤波
-
medianBlur(src, dst, ksize / 2 * 2 + 1); //源图片,生成图片,卷积核大小(默认为方形)
- 高斯滤波
-
GaussianBlur(src, dst, Size(wkernelSize / 2 * 2 + 1, hkernelSize / 2 * 2 + 1), wsigma, hsigma); //源图片,生成图片,核大小(长、宽),长上分布的标准差,宽上分布的标准差 //同样可以根据需要改变卷积核的长宽,及对应维度上的分布
- 双边滤波
-
bilateralFilter(src, dst, kernelSize / 2 * 2 + 1, sigmaColor, sigmaSpace); //源图片,生成图片,卷积核大小,高斯分布标准差,保护边缘阈值
保护边缘阈值设的越低保留细节越多,标出差设的越大模糊程度越高。
代码实践
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
typedef struct _imgPair {
Mat* src;
Mat* dst;
void* Param;
string winName;
}ImgPair;
typedef struct _gaussianParam {
int kernelSize;
int sigma;
}GaussianParam;
typedef struct _bilateralParam {
int kernelSize;
int sigmaColor;
int sigmaSpace;
}BilateralParam;
void on_gaussiankernelBar(int ksize, void* userdata)
{
ImgPair* pImgPair = (ImgPair*)userdata;
GaussianParam* gPair = (GaussianParam*)(pImgPair->Param);
gPair->kernelSize = ksize;
GaussianBlur(*(pImgPair->src), *(pImgPair->dst), Size(gPair->kernelSize / 2 * 2 + 1, gPair->kernelSize / 2 * 2 + 1), gPair->sigma, gPair->sigma);
imshow(pImgPair->winName, *(pImgPair->dst));
}
void on_gaussianSigmaBar(int sigma, void* userdata)
{
ImgPair* pImgPair = (ImgPair*)userdata;
GaussianParam* gPair = (GaussianParam*)(pImgPair->Param);
gPair->sigma = double(sigma);
GaussianBlur(*(pImgPair->src), *(pImgPair->dst), Size(gPair->kernelSize / 2 * 2 + 1, gPair->kernelSize / 2 * 2 + 1), gPair->sigma, gPair->sigma);
imshow(pImgPair->winName, *(pImgPair->dst));
}
void on_medianSigmaBar(int ksize, void* userdata)
{
ImgPair* pImgPair = (ImgPair*)userdata;
medianBlur(*(pImgPair->src), *(pImgPair->dst), ksize / 2 * 2 + 1);
imshow(pImgPair->winName, *(pImgPair->dst));
}
void on_bilateralDBar(int ksize, void* userdata)
{
ImgPair* pImgPair = (ImgPair*)userdata;
BilateralParam* param = (BilateralParam*)(pImgPair->Param);
bilateralFilter(*(pImgPair->src), *(pImgPair->dst), ksize / 2 * 2 + 1, param->sigmaColor, param->sigmaSpace);
param->kernelSize = ksize;
imshow(pImgPair->winName, *(pImgPair->dst));
}
void on_bilateralSigmaSpaceBar(int sigmaSpace, void* userdata)
{
ImgPair* pImgPair = (ImgPair*)userdata;
BilateralParam* param = (BilateralParam*)(pImgPair->Param);
bilateralFilter(*(pImgPair->src), *(pImgPair->dst), param->kernelSize / 2 * 2 + 1, param->sigmaColor, sigmaSpace);
param->sigmaSpace = sigmaSpace;
imshow(pImgPair->winName, *(pImgPair->dst));
}
void on_bilateralSigmaColorBar(int sigmaColor, void* userdata)
{
ImgPair* pImgPair = (ImgPair*)userdata;
BilateralParam* param = (BilateralParam*)(pImgPair->Param);
bilateralFilter(*(pImgPair->src), *(pImgPair->dst), param->kernelSize / 2 * 2 + 1, sigmaColor, param->sigmaSpace);
param->sigmaColor = sigmaColor;
imshow(pImgPair->winName, *(pImgPair->dst));
}
int main()
{
Mat src = imread("4.jpg");
namedWindow("src");
imshow("src", src);
/*-------GaussianBlur-----------*/
Mat GaussianBlurImg;
namedWindow("GaussianBlurImg");
GaussianParam gaussianParam = { 5, 1.0 };
GaussianBlur(src, GaussianBlurImg, Size(5, 5), 1, 1);
GaussianParam gparam = { 5, 1.0 };
ImgPair gaussianPair = { &src, &GaussianBlurImg, &gparam, "GaussianBlurImg" };
imshow("GaussianBlurImg", GaussianBlurImg);
createTrackbar("kernelsize", "GaussianBlurImg", &(gparam.kernelSize), 30, on_gaussiankernelBar, &gaussianPair);
createTrackbar("sigma", "GaussianBlurImg", &(gparam.kernelSize), 10, on_gaussianSigmaBar, &gaussianPair);
/*-------medianBlur-----------*/
Mat MedianBlurImg;
int kernelSize = 5;
ImgPair medianPair = { &src, &MedianBlurImg, nullptr, "MedianBlurImg" };
medianBlur(src, MedianBlurImg, 5);
imshow("MedianBlurImg", MedianBlurImg);
createTrackbar("kernelsize", "MedianBlurImg", &(kernelSize), 30, on_medianSigmaBar, &medianPair);
/*---Bilateral-----------------*/
Mat BilateralFilterImg;
bilateralFilter(src, BilateralFilterImg, 5, 2, 2);
BilateralParam bparam = { 5,1,1 };
ImgPair bilateralPair = { &src, &BilateralFilterImg, &bparam, "BilateralFilterImg" };
imshow("BilateralFilterImg", BilateralFilterImg);
createTrackbar("kernelsize", "BilateralFilterImg", &(bparam.kernelSize), 30, on_bilateralDBar, &bilateralPair);
createTrackbar("sigmaspace", "BilateralFilterImg", &(bparam.sigmaSpace), 30, on_bilateralSigmaSpaceBar, &bilateralPair);
createTrackbar("sigmacolor", "BilateralFilterImg", &(bparam.sigmaColor), 30, on_bilateralSigmaColorBar, &bilateralPair);
waitKey(0);
}