滤波
它是信号中的名词,依照傅里叶定理,一个信号是由很多信号叠加而成,其中的外界干扰信号称作噪声,滤波就是过滤某些频率的波,一般就是指过滤噪声了,在图像中滤波可以看作是去除瑕点,减少其对图片的影响。
一般,我们通过将该像素点值设为周围像素点的加权平均来淡化噪声的影响,但也因此使得像素之间差异变小,看上去变模糊了。根据权值在周围像素的分布及大小分为均值分布,高斯分布等。
滤波器种类 | 原理 |
---|---|
均值滤波 | 每个像素点参考周围像素值平均值赋值,权重相同(周围像素对所赋值影响一样) |
中值滤波 | 每个像素点参考周围像素的中间值赋值 |
高斯滤波 | 每个像素点参考周围像素加权平均赋值,权重-距离差符合高斯分布(越远的影响越小) |
双边滤波 | 既考虑距离差也考虑像素灰度值差,双重要素影响,权重-距离差和权重-灰度值差符合高斯分布 |
常见滤波API实现:
#include<opencv2\opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main(){
Mat src = imread("D:/a.jpg",0);
Mat dst,dst1,dst2,dst3 = src.clone();
blur(src, dst, Size(3, 3));//均值滤波
medianBlur(src, dst1,3);//中值滤波
GaussianBlur(src, dst2, Size(3, 3), 0.1); //高斯滤波
bilateralFilter(src, dst3, 3,1, 3); //双边滤波
imshow("src", src);
imshow("均值滤波", dst);
imshow("中值滤波", dst1);
imshow("高斯滤波", dst2);
imshow("双边滤波", dst3);
waitKey(0);
}
bilateraFilter()函数 第二个参数,为领域直径大小,第四个参数关系到 色度差高斯核函数平缓还是尖峭,第五个关系到空间距离高斯核函数平缓还是尖峭。
实现双边滤波:(以下高斯函数权重纯属胡诌,因为个人认为满足越近权重越大的规则即可)
void test_doubleedge()//双边滤波自实现
{
Mat src = imread("d:/9.jpg",0);
imshow("原始图片src", src);
Mat fdst;
Mat dst(src.rows, src.cols, CV_8UC1);
for (int i =1; i < src.rows-1; i++)
{
uchar* src_prev = src.ptr<uchar>(i - 1);
uchar* src_cur = src.ptr<uchar>(i);
uchar* src_next = src.ptr<uchar>(i + 1);
int array[8];
uchar* dst_cur = dst.ptr<uchar>(i);
for (int j = 1; j < src.cols-1; j++)
{
double colorrel, dancerel;
dancerel = 0.2*src_cur[j] + 0.1*src_cur[j - 1] + 0.1*src_cur[j + 1] + 0.1*src_prev[j - 1] + 0.1*src_prev[j] + 0.1*src_prev[j + 1] + 0.1*src_next[j - 1] + 0.1*src_next[j] + 0.1*src_next[j + 1];
array[0] = src_cur[j] - src_cur[j - 1];
array[1] = src_cur[j] - src_cur[j+1];
array[2] = src_cur[j] - src_prev[j];
array[3] = src_cur[j] - src_prev[j - 1];
array[4] = src_cur[j] - src_prev[j + 1];
array[5] = src_cur[j] - src_next[j+1];
array[6] = src_cur[j] - src_next[j - 1];
array[7] = src_cur[j] - src_next[j];
double p_array[8];
districoe(array, 8,p_array);
colorrel = p_array[0] * src_cur[j - 1]+p_array[1]*src_cur[j+1]+p_array[2]*src_prev[j]+p_array[3]*src_prev[j-1]+p_array[4]*src_prev[j+1]
+p_array[5]*src_next[j+1]+p_array[6]*src_next[j-1]+p_array[7]*src_next[j];
dst_cur[j]=(uchar)(0.5*colorrel+ 0.5*dancerel );
}
}
imshow("自实现三核dst", dst);
bilateralFilter(src, fdst, 7, 30, 30);
imshow("API函数实现七核dst", fdst);
waitKey();
}
void districoe(int array[],int N,double p_array[])
{
for (int i = 0; i < N; i++)
{
array[i]=array[i] > 0 ? array[i] : -array[i];
}
int max=array[0];
for (int i = 1; i < N; i++)
{
max=max < array[i]?array[i]:max;
}
double sum = 0;
for (int i = 0; i < N; i++)
{
if (0 <= array[i] && array[i] < max/4)
p_array[i] = 0.4;
if (array[i] >= max/4 && array[i] < max/2)
p_array[i] = 0.3;
if (array[i] >= max/2 && array[i] < max*3/4)
p_array[i] = 0.2;
if(array[i]>=max*3/4) p_array[i] = 0.1;
sum += p_array[i];
}
for (int i = 0; i < N; i++)
{
p_array[i] = p_array[i]/sum;
}
}
效果:
双边滤波也就是磨皮特效,高斯核size越大效果越明显,3核和5核效果不是很明显,当到达7核时肉眼可见