【opencv学习笔记】010之图像非线性滤波原理与操作(中值滤波、双边滤波)

冷暖自知 提交于 2020-02-17 06:33:03

一、前言

着实好久没有写博客了,回来填坑,不过opencv4已经出来很久了,我的教程还在3徘徊。作为基础完全够用了,先把基础的坑填完吧,确实是很纠结自己的研究方向,不知道,还是多学吧,想太多,不如好好学。

如果想看其他有关于OpenCV学习方法介绍、学习教程、代码实战、常见报错及解决方案等相关内容,可以直接看我的OpenCV分类:

【OpenCV系列】:https://blog.csdn.net/shuiyixin/article/category/7581855

如果你想了解更多有关于计算机视觉、OpenCV、机器学习、深度学习等相关技术的内容,想与更多大佬一起沟通,那就扫描下方二维码加入我们吧!

 

二、线性滤波与非线性滤波

1、回顾

1.分类

上节课我么讲到线型滤波和非线性滤波,我们讲了三种重要的线性滤波。也提到两种非线性滤波。常用的线性与非线性滤波如下:

(1)线性滤波:方框滤波、均值滤波、高斯滤波;

(2)非线性滤波:中值滤波、双边滤波

 

2.线性滤波器的分类

上节课我们也讲到线性滤波器的分类,线性滤波器经常用于剔除输入信号中不想要的频率或者从许多频率中选择一个想要的频率。几种常见的线性滤波器如下:

(1)低通滤波器:允许低频率的波通过。

(2)高通滤波器:允许高频率的波通过的。

(3)带通滤波器:允许一定范围频率的波通过。

(4)带阻滤波器:阻止一定范围频率的波通过并且允许其它频率的波通过。

(5)全通滤波器:允许所有频率的波通过、仅仅改变波的相位关系。

(6)陷波滤波器:阻止一个狭窄频率范围通过的特殊带阻滤波器。

 

2、对比

1.线性滤波器

线性滤波器的原始数据与滤波结果是一种算术运算,即用加减乘除等运算实现,如均值滤波器(模板内像素灰度值的平均值)、高斯滤波器(高斯加权平均值)等。由于线性滤波器是算术运算,有固定的模板,因此滤波器的转移函数是可以确定并且是唯一的(转移函数即模板的傅里叶变换)。

2.非线性滤波器

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

三、OpenCV中的非线型滤波操作

opencv中最常用的两种非线性滤波为中值滤波和双边滤波。

1、中值滤波——medianBlur函数

中值滤波很简单,就是某个区域里面的中值,将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值.。这个区域是一个正方形区域,并且正方形的边长即区域的行数和列数都为奇数。中值对椒盐噪声有很好的抑制作用。

例如:

上图中的为正方形区域,按照从小到大排序为:

14,15,17,28,31,53,65,72,84

中值为:31。

1.API

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

函数参数含义如下:

(1)InputArray类型的src,输入图像。输入1、3或4通道图像;当ksize为3或5时,图像深度应为 CV_8U、CV_16U或CV_32F,对于较大孔径,它只能是CV_8U。

(2)OutputArray类型的dst,即目标图像,与输入图像有相同的尺寸和类型。

(3)int类型的ksize,光圈线性大小;它必须是奇数且大于1,例如:3、5、7 ...。

2.代码展示

#include<opencv2\opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat src, dst;
	src = imread("E:/image/Girl2.png");
	if (!src.data)
	{
		cout << "could not load image !";
		return -1;
	}
	imshow("src", src);

	//中值滤波
	medianBlur(src, dst, 7);
	imshow("medianBlur_src", dst);

	waitKey(0);
	return 0;
}

3.执行结果

原图
ksize = 3
ksize = 7

2、双边滤波——bilateralFilter函数

双边滤波是结合图像的空间邻近度和像素值相似度的一种折中处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点。双边滤波器的好处是可以做边缘保存,一般过去用的维纳滤波或者高斯滤波去降噪,都会较明显地模糊边缘,对于高频细节的保护效果并不明显。

双边滤波器比高斯滤波多了一个高斯方差sigma-d,它是基于空间分布的高斯滤波函数,所以在边缘附近,离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波。

1.API

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

函数参数含义如下:

(1)InputArray类型的src,输入图像。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。

(2)OutputArray类型的dst,即目标图像,与输入图像有相同的尺寸和类型。

(3)int类型的d,滤波过程中使用的每个像素邻域的直径。如果是非正的,则从sigmaSpace计算。

(4)double类型的sigmaColor ,颜色空间中过滤器sigma。参数值越大,意味着像素邻域(参见sigmaSpace)中的更多颜色将混合在一起,从而产生更大的半等色区域。

(5)double类型的sigmaSpace,在坐标空间中过滤器sigma。参数值越大,意味着更远的像素将相互影响,只要它们的颜色足够接近(参见sigmaColor)。当d大于0时,它指定邻域大小,而不考虑sigmaSpace。否则,d与sigmaSpace成比例。

(6)int类型的borderType,用于在图像外部外推像素的边框模式,具体请参见cv::BorderTypes。

 

2.代码展示

#include<opencv2\opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat src, dst;
	src = imread("E:/image/Girl2.png");
	if (!src.data)
	{
		cout << "could not load image !";
		return -1;
	}
	imshow("src", src);


	//双边滤波
	bilateralFilter(src, dst, 15, 150, 3);
	imshow("bilateralFilter_src", dst);


	waitKey(0);
	return 0;
}

3.执行结果

双边滤波后的图像

 

好啦今天的内容就讲到这里啦,希望大家能够多多练习,才能真正学懂啊!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!