OpenCV学习8——图像模糊处理

  1. 图像模糊处理原理:
    图像模糊处理即图像的滤波处理,在图像的掩模处理中我们第一次接触到图像的滤波处理。

    图像的滤波处理目的:
    ①、消除图像中混入的噪声;②、为图像识别抽取出图像特。
    要求:
    ①、不能损坏图像轮廓及边缘 ;②、图像视觉效果应当更好。

    smooth/blur操作是低频增强的空间滤波技术,他的目的是:①模糊②消除噪音

    滤波器的种类:
    ①线性滤波:归一化盒子滤波(均值滤波)(Blur函数)、高斯滤波(GaussianBlur函数)
    ②非线性滤波:中值滤波(medianBlur函数)、双边滤波(bilateralFilter函数)

以下内容参考总结整理于:
https://www.cnblogs.com/snowxshy/p/3855011.html
https://blog.csdn.net/zouxy09/article/details/49080029
https://blog.csdn.net/sinat_36264666/article/details/78023481

  1. 线性滤波:
    线性滤波器笔者上个学期刚在模电中学习过,低通、高通、带通、带阻、全通滤波器等等。而线性滤波器则正是利用上述这几种滤波器来进行实现的,例如对于高斯滤波,如果为高斯低通则对图像产生的效果是造成其模糊,如果为高斯高通则对原图像的效果是使其锐化。

    线性滤波器的原始数据与滤波结果是一种算术运算,即用加减乘除等运算实现(因而我们称其为线性滤波),如均值滤波器(模板内像素灰度值的平均值)、高斯滤波器(高斯加权平均值)等。由于线性滤波器是算术运算,有固定的模板,因此滤波器的转移函数是可以确定并且是唯一的(转移函数即模板的傅里叶变换)。线性滤波可以说是图像处理最基本的方法,它可以允许我们对图像进行处理,产生很多不同的效果。做法很简单。首先,我们有一个二维的滤波器矩阵(有个高大上的名字叫卷积核)和一个要处理的二维图像。然后,对于图像的每一个像素点,计算它的邻域像素和滤波器矩阵的对应元素的乘积,然后加起来,作为该像素位置的值。这样就完成了滤波过程。

    smooth/blur操作的本质是数学中的卷积运算,对于图像处理而言,有两大类方法,即空域处理与频域处理,空域处理指的是直接对所要操作的图像的像素进行操作,而频域处理则是先将图像变换到频域再进行图像处理。
    空域处理:
    对于图像的每一个像素点,计算它的邻域像素和滤波器矩阵的对应元素的乘积,然后加起来,作为该像素位置的值。
    在这里插入图片描述
    OpenCV学习8——图像模糊处理_第1张图片
    但是我们可以发现对于图像边缘,例如最上面的一行的像素,由于其上方已经没有像素了,所以无法利用上面的卷积公式来进行计算,对于图非图像边界(即除了四个角的图像边缘)我们一般采用的是用该像素与其左右相邻的两个元素的平均值来代替它,假设我们对I(见下图)的第四个像素3做局部平均。也就是我们用2,3和7做平均,来取代这个位置的像素值。也就是,平均会产生一副新的图像J,这个图像在相同位置J (4) = (I(3)+I(4)+I(5))/3 = (2+3+7)/3 = 4。同样,我们可以得到J(3) = (I(2)+I(3)+I(4))/3 =(4+2+3)/3 = 3。需要注意的是,新图像的每个像素都取决于旧的图像,在计算J (4)的时候用J (3)是不对的,而是用I(3),I(4)和I(5)。所以每个像素都是它和它邻域两个像素的平均。平均是线性的操作,因为每个新的像素都是旧像素的线性组合。
    在这里插入图片描述
    对于边界部分的元素,因为其左或右元素存在缺失,所以不能够用上面的均值代替法,主要有以下几种处理方法:
    (一):第一种就是想象I是无限长的图像的一部分,除了我们给定值的部分,其他部分的像素值都是0。再利用均值代替,来计算。
    (二):第二种方法也是想象I是无限图像的一部分。但没有指定的部分是用图像边界的值进行拓展。在我们的例子中,因为图像I最左边的值I(1)=5,所以它左边的所有值,我们都认为是5 。而图像右边的所有的值,我们都认为和右边界的值I(10)一样,都是6。
    (三):第三种情况就是认为图像是周期性的。也就是I不断的重复。周期就是I的长度。在我们这里,I(0)和I(10)的值就是一样的,I(11)的值和I(1)的值也是一样的。
    (四):最后一种情况就是不管其他地方了。我们觉得I之外的情况是没有定义的,所以没办法使用这些没有定义的值,所以要使用图像I没有定义的值的像素都没办法计算。在这里,J(1)和J(10)都没办法计算,所以输出J会比原图像I要小。

  2. 均值滤波
    均值滤波是输出邻域内像素的简单平均值,是一种低通滤波器, 我们可以将当前像素和它的四邻域的像素一起取平均,然后再除以5,或者直接在滤波器的5个地方取0.2的值即可,如下图:OpenCV学习8——图像模糊处理_第2张图片
    均值滤波用到的函数分析:

    CV_EXPORTS_W void blur( InputArray src,
    						OutputArray dst,
                            Size ksize,
                            Point anchor = Point(-1,-1) );
    

    第一二个参数分别为输入的图像与输出的图像
    第三个参数为Size类型的卷积核大小Size(3,3)表示一个3*3的卷积核
    第四个参数表示表示锚点即被平滑的点,我们一般取Point(-1,-1),即卷积核的中心为锚点。

  3. 高斯滤波
    均值模糊很简单,但不是很平滑。高斯模糊就有这个优点,所以被广泛用在图像降噪上。特别是在边缘检测之前,都会用来移除细节。高斯滤波器是一个低通滤波器。
    通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波引入了数学中的高斯函数(正态分布函数)高斯滤波的思路就是:对高斯函数进行离散化,以离散点上的高斯函数值为权值,对我们采集到的灰度矩阵的每个像素点做一定范围邻域内的加权平均,即可有效消除高斯噪声。在图像处理中,高斯滤波一般有两种实现方式,一是用离散化窗口滑窗卷积,另一种通过傅里叶变换。最常见的就是第一种滑窗实现,只有当离散化的窗口非常大,用滑窗计算量非常大(即使用可分离滤波器的实现)的情况下,可能会考虑基于傅里叶变化的实现方法。

    在这里插入图片描述OpenCV学习8——图像模糊处理_第3张图片高斯滤波用到的函数分析:

    	```
    	CV_EXPORTS_W void GaussianBlur( InputArray src, 
    									OutputArray dst, Size ksize,
    	                                double sigmaX, 
    	                                double sigmaY = 0);
    	```
    

    第三个参数为Size类型的高斯函数的内核Size(x,y),x与y必须为奇数
    第四个参数表示高斯核函数在X方向的标准偏差。
    第五个参数表示高斯核函数在Y方向的标准偏差

  4. 线性滤波实验代码

    #include
    #include
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
    	Mat src, dst,dst1;
    	src = imread("C:/Users/he104/Desktop/timg.jpg");
    	if (src.empty())
    	{
    		cout << "could not load the src..." << endl;
    		return -1;
    	}
    	namedWindow("原图", CV_WINDOW_AUTOSIZE);
    	imshow("原图", src);
    	blur(src, dst, Size(5, 5), Point(-1, -1));
    	namedWindow("均值滤波", CV_WINDOW_AUTOSIZE);
    	imshow("均值滤波", dst);
    	GaussianBlur(src,dst1,Size(5,5),5,5);
    	namedWindow("高斯滤波", CV_WINDOW_AUTOSIZE);
    	imshow("高斯滤波", dst1);
    	waitKey(0);
    	destroyAllWindows();
    	return 0;
    }
    

  1. 线性滤波补充:
    若卷积核为3×3时,则对于均值滤波,其应除以5,而对于5×5的卷积核,对于均值滤波,其应处理13,这是由于3×3的卷积核其核半径为1,5×5的卷积核其核半径为2。

  2. 非线性滤波:
    非线性滤波器的原始数据与滤波结果是一种逻辑关系,即用逻辑运算实现,如最大值滤波器、最小值滤波器、中值滤波器等,是通过比较一定邻域内的灰度值大小来实现的,没有固定的模板,因而也就没有特定的转移函数(因为没有模板作傅里叶变换),另外,膨胀和腐蚀也是通过最大值、最小值滤波器实现的。

  3. 中值滤波:
    中值滤波是一种统计排序滤波器,中值滤波对椒盐噪声有良好的滤除作用,特别是在滤除噪声的同时,能够保护信号的边缘,使之不被模糊,但它会洗去均匀介质区域中的纹理。这些优良特性是线性滤波方法所不具有的。
    椒盐噪声:椒盐噪声也称为脉冲噪声,是图像中经常见到的一种噪声,它是一种随机出现的白点或者黑点,可能是亮的区域有黑色像素或是在暗的区域有白色像素(或是两者皆有)。盐和胡椒噪声的成因可能是影像讯号受到突如其来的强烈干扰而产生、类比数位转换器或位元传输错误等。例如失效的感应器导致像素值为最小值,饱和的感应器导致像素值为最大值。
    OpenCV学习8——图像模糊处理_第4张图片
    中值滤波用到的函数分析:

CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize );

第三个参数为int类型的 ksize,表示卷积核的大小,同上面一样,需要将其设置为奇数。
9. 双边滤波:
双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的,具有简单、非迭代、局部的特点。
双边滤波器的好处是可以做边缘保存,这个特点对于一些图像模糊来说很有用。一般过去用的维纳滤波或者高斯滤波去降噪,都会较明显地模糊边缘,对于高频细节的保护效果并不明显。一般的高斯模糊在进行采样时主要考虑了像素间的空间距离关系,但是却并没有考虑像素值之间的相似程度,因此这样我们得到的模糊结果通常是整张图片一团模糊。
双边滤波的改进就在于在采样时不仅考虑像素在空间距离上的关系,同时加入了像素间的相似程度考虑。双边滤波器比高斯滤波多了一个高斯方差sigma-d,它是基于空间分布的高斯滤波函数,所以在边缘附近,离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波。对于脉冲噪声,双边滤波会把它当成边缘从而不能去除。
双边滤波用到的函数分析:

CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d,
                                   double sigmaColor, double sigmaSpace,
                                   int borderType = BORDER_DEFAULT );

参数3:表示在过滤过程中每个像素邻域的直径。如果这个值我们设其为非正数,那么OpenCV会从第五个参数sigmaSpace来计算出它来。
参数4:表示颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
参数5:double类型的sigmaSpace坐标空间中滤波器的sigma值,坐标空间的标注方差。它的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。
10. 非线性滤波器实验代码及实验效果:

#include
#include

using namespace std;
using namespace cv;

int main()
{
	Mat src, dst, dst1;
	src = imread("C:/Users/he104/Desktop/salt.jpg");
	if (src.empty())
	{
		cout << "could not load the src..." << endl;
		return -1;
	}
	namedWindow("原图", CV_WINDOW_AUTOSIZE);
	imshow("原图", src);
	medianBlur(src, dst, 3);
	namedWindow("中值滤波", CV_WINDOW_AUTOSIZE);
	imshow("中值滤波", dst);
	waitKey(0);
	destroyAllWindows();
	return 0;
}

#include
#include

using namespace std;
using namespace cv;

int main()
{
	Mat src, dst, dst1;
	src = imread("C:/Users/he104/Desktop/timg.jpg");
	if (src.empty())
	{
		cout << "could not load the src..." << endl;
		return -1;
	}
	namedWindow("原图", CV_WINDOW_AUTOSIZE);
	imshow("原图", src);
	bilateralFilter(src,dst,15,100,3);
	namedWindow("双边滤波", CV_WINDOW_AUTOSIZE);
	imshow("双边滤波", dst);
	waitKey(0);
	destroyAllWindows();
	return 0;
}

你可能感兴趣的:(数字图像处理,OpenCV学习,图像滤波,数字图像处理)