OpenCV学习笔记八(图像模糊)
图像模糊模糊原理归一化盒子滤波(均值滤波)高斯滤波中值滤波双边滤波相关API模糊原理Smooth/Blur 是图像处理中最简单和常用的操作之一使用该操作的原因之一就为了给图像预处理时候减低噪声使用Smooth/Blur操作其背后是数学的卷积计算通常这些卷积算子计算都是线性操作,所以又叫线性滤波假设有6x6的图像像素点矩阵。卷积过程:6x6上面是个3x3的窗口,从左向右,从上向下移动,黄色的每个像个
·
模糊原理
- Smooth/Blur 是图像处理中最简单和常用的操作之一
- 使用该操作的原因之一就为了给图像预处理时候减低噪声
- 使用Smooth/Blur操作其背后是数学的卷积计算
- 通常这些卷积算子计算都是线性操作,所以又叫线性滤波
假设有6x6的图像像素点矩阵。
卷积过程:6x6上面是个3x3的窗口,从左向右,从上向下移动,黄色的每个像个像素点值之和取平均值赋给中心红色像素作为它卷积处理之后新的像素值。每次移动一个像素格。
滤波与卷积区别
参考链接:https://blog.csdn.net/zhaoshuling1109/article/details/78082385
滤波和卷积存在些许差别。
- 滤波器与卷积核意义相同。
- 滤波操作就是图像对应像素与掩膜(滤波器)的乘积之和。
- 卷积操作也是卷积核与图像对应位置的乘积和。但是卷积操作在做乘积之前,需要先将卷积核翻转180度,之后再做乘积。
- 如果卷积核是个对称矩阵,则滤波和卷积操作相同。
滤波器规则
重要链接:https://blog.csdn.net/zouxy09/article/details/49080029
-
2D卷积需要4个嵌套循环4-double loop,所以它并不快,除非我们使用很小的卷积核。这里一般使用3x3或者5x5。而且,对于滤波器,也有一定的规则要求:
1)滤波器的大小应该是奇数,这样它才有一个中心,例如3x3,5x5或者7x7。有中心了,也有了半径的称呼,例如5x5大小的核的半径就是2。 2)滤波器矩阵所有的元素之和应该要等于1,这是为了保证滤波前后图像的亮度保持不变。当然了,这不是硬性要求了。 3)如果滤波器矩阵所有元素之和大于1,那么滤波后的图像就会比原图像更亮,反之,如果小于1,那么得到的图像就会变暗。如果和为0,图像不会变黑,但也会非常暗。 4)对于滤波后的结构,可能会出现负数或者大于255的数值。对这种情况,我们将他们直接截断到0和255之间即可。对于负数,也可以取绝对值。
相关API
【均值滤波】
均值滤波是方框滤波归一化后的特殊情况。
void blur(
InputArray src,
OutputArray dst,
Size ksize,
Point anchor=Point(-1,-1),
int borderType=BORDER_DEFAULT );
参数1:输入图像
参数2:输出图像
参数3:内核大小
参数4:锚点(被平滑的点)。默认值为Point(-1,-1)表示是中心点。
参数5:边界模式,默认值BORDER_DEFAULT 。我们一般不管它。
缺点:不能很好地保护细节。
【高斯滤波】
void GaussianBlur(
InputArray src,
OutputArray dst,
Size ksize,
double sigmaX,
double sigmaY=0,
int borderType=BORDER_DEFAULT );
参数1:输入图像
参数2:输出图像
参数3:内核大小,Size(w,h)其中w,h必须为正数,而且必须为奇数。w表示像素宽度,h表示高度。
参数4:高斯核函数在X方向的标准偏差
参数5:高斯核函数在Y方向的标准偏差
参数6:边界模式,默认值BORDER_DEFAULT 。我们一般不管它。
【中值模糊】
- 统计排序滤波器
- 中值对椒盐噪声有很好的抑制作用
void medianBlur( InputArray src, OutputArray dst, int ksize );
参数1:InputArray类型的src,函数的输入参数,填1、3或者4通道的Mat类型的图像;当ksize为3或者5的时候,图像深度需为CV_8U,CV_16U,或CV_32F其中之一,而对于较大孔径尺寸的图片,它只能是CV_8U。
参数2:OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。我们可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
参数3:int类型的ksize,孔径的线性尺寸(aperture linear size),注意这个参数必须是大于1的奇数,比如:3,5,7,9 ...
【双边模糊】
- 均值模糊无法克服边缘像素信息丢失缺陷。原因是均值滤波是基于平均权重
- 高斯模糊部分克服了该缺陷,但是无法完全避免,因为没有考虑像素值的不同
- 高斯双边模糊 – 是边缘保留的滤波方法,避免了边缘信息丢失,保留了图像轮廓不变
void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT )
参数1:InputArray src,输入图像,可以是Mat类型,图像必须是8位或浮点型单通道、三通道的图像。
参数2: OutputArray dst, 输出图像,和原图像有相同的尺寸和类型。
参数3:int d,表示在过滤过程中每个像素邻域的直径范围。如果这个值是非正数,则函数会从第五个参数sigmaSpace计算该值。
参数4: double sigmaColor,颜色空间过滤器的sigma值,这个参数的值月大,表明该像素邻域内有月宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
参数5: double sigmaSpace, 坐标空间中滤波器的sigma值,如果该值较大,则意味着颜色相近的较远的像素将相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色。当d>0时,d指定了邻域大小且与sigmaSpace五官,否则d正比于sigmaSpace.
参数6:int borderType=BORDER_DEFAULT, 用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT.
结果显示
- 原始图像
- 均值模糊后的图像
- 高斯滤波后的图像
- 中值滤波后的图像
- 双边模糊后的图像
- 经过掩膜操作的后的图像
代码实现
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(){
Mat src = imread("4.jpg");
if (src.empty()){
cout << "could not load image..." << endl;
getchar();
return -1;
}
imshow("input image", src);
Mat blur1;
//blur(src, blur1, Size(3, 3), Point(-1, -1));// Size(3, 3)中选择的数应尽量都是奇数
//blur(src, blur1, Size(1, 15), Point(-1, -1));//y方向的模糊
//blur(src, blur1, Size(15, 1), Point(-1, -1));//x方向的模糊
blur(src, blur1, Size(5, 5), Point(-1, -1)); //均值模糊
//一般均值模糊选择3*3的模糊即可,filter2D也可以做模糊
imshow("blur image", blur1);
Mat gblur;
GaussianBlur(src, gblur, Size(5, 5), 3, 3);//高斯滤波,GaussianBlur是基于权重的模糊
imshow("GaussianBlur image", gblur);
//由上对比可以看到双边模糊比高斯模糊的要清楚一些,边缘更加清楚
Mat dst;
medianBlur(src, dst, 3); //中值模糊
imshow("medianBlur image", dst);
bilateralFilter(src, dst, 15, 100, 5);//15具有磨皮的效果,调成100,边缘的信息更多的保留下来
imshow("bilateralFilter image", dst);
Mat resultImg;
Mat kernel = (Mat_<int>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
filter2D(dst, resultImg, -1, kernel, Point(-1, -1), 0);
imshow("filter2D Result", resultImg);
//之前学过的第一个滤波的函数就是filter2D,对双边模糊再掩码操作,效果很好
waitKey(0);
return 0;
}
更多推荐
已为社区贡献3条内容
所有评论(0)