一滤波的基本概念
图像常常被强度随机信号(也称为噪声)所污染.一些常见的噪声有椒盐(Salt & Pepper)噪声、脉冲噪声、高斯噪声等.椒盐噪声含有随机出现的黑白强度值.而脉冲噪声则只含有随机的白强度值(正脉冲噪声)或黑强度值(负脉冲噪声).与前两者不同,高斯噪声含有强度服从高斯或正态分布的噪声.研究滤波就是为了消除噪声干扰。
图像滤波总体上讲包括空域滤波和频域滤波。频率滤波需要先进行傅立叶变换至频域处理然后再反变换回空间域还原图像,空域滤波是直接对图像的数据做空间变换达到滤波的目的。它是一种邻域运算,即输出图像中任何像素的值都是通过采用一定的算法,根据输入图像中对用像素周围一定邻域内像素的值得来的。如果输出像素是输入像素邻域像素的线性组合则称为线性滤波(例如最常见的均值滤波和高斯滤波),否则为非线性滤波(中值滤波、边缘保持滤波等)。
线性平滑滤波器去除高斯噪声的效果很好,且在大多数情况下,对其它类型的噪声也有很好的效果。线性滤波器使用连续窗函数内像素加权和来实现滤波。特别典型的是,同一模式的权重因子可以作用在每一个窗口内,也就意味着线性滤波器是空间不变的,这样就可以使用卷积模板来实现滤波。如果图像的不同部分使用不同的滤波权重因子,且仍然可以用滤波器完成加权运算,那么线性滤波器就是空间可变的。任何不是像素加权运算的滤波器都属于非线性滤波器.非线性滤波器也可以是空间不变的,也就是说,在图像的任何位置上可以进行相同的运算而不考虑图像位置或空间的变化。
滤波的目的有两个:一是抽出对象的特征作为图像识别的特征模式;另一个是为适应图像处理的要求,消除图像数字化时所混入的噪声。
对滤波处理的要求有两条:一是不能损坏图像的轮廓及边缘等重要信息;二是使图像清晰视觉效果好。
二 线性滤波
2.1一般的线性滤波
1.相关算子(Correlation Operator)
定义:, 即
,其中h称为相关核(Kernel).
步骤:
1)滑动核,使其中心位于输入图像g的(i,j)像素上
2)利用上式求和,得到输出图像的(i,j)像素值
3)充分上面操纵,直到求出输出图像的所有像素值
例:
A = [17 24 1 8 15 h = [8 1 6
23 5 7 14 16 3 5 7
4 6 13 20 22 4 9 2]
10 12 19 21 3
11 18 25 2 9]计算输出图像的(2,4)元素=
定义:
,
,其中
步骤:
1)将核围绕中心旋转180度
2)滑动核,使其中心位于输入图像g的(i,j)像素上
3)利用上式求和,得到输出图像的(i,j)像素值
4)充分上面操纵,直到求出输出图像的所有像素值
例:计算输出图像的(2,4)元素=
当对图像边缘的进行滤波时,核的一部分会位于图像边缘外面。
常用的策略包括:
1)使用常数填充:imfilter默认用0填充,这会造成处理后的图像边缘是黑色的。(这里是Matlab中的函数)
2)复制边缘像素:I3 = imfilter(I,h,'replicate');
![]()
2..2openCv实现,以下使用的是卷积算子。
#include"opencv2/imgproc/imgproc.hpp" #include"opencv2/highgui/highgui.hpp" //#include
//#include #include using namespace std; using namespace cv; int main() { //变量声明 Mat src,dst; Mat kernel; Point anchor; double delta; int ddepth; int kernel_size; char* window_name = "filter2D 线性滤波例子"; int c; //载入图像 src = imread("D:\\openCV\\openCVProject\\openCv笔记\\openCv笔记\\test.jpg"); //是否载入成功 if(!src.data ) { cout<<""< 2.3高斯滤波器
高斯滤波器是平滑线性滤波器的一种,线性滤波器很适合于去除高斯噪声。而非线性滤波则很适合用于去除脉冲噪声,中值滤波就是非线性滤波的一种。平滑滤波器就是用滤波掩模确定的邻域内像素的平均灰度值去替代图像的每个像素点的值,这很容易用硬件实现。而高斯滤波器是带有权重的平均值,即加权平均,中心的权重比邻近像素的权重更大,这样就可以克服边界效应。高斯滤波如果采用3×3掩模的具体公式如下:g(x,y)={f(x-1,y-1)+f(x-1,y+1)+f(x+1,y-1)+f(x+1,y+1)+[f(x-1,y)+f(x,y-1)+f(x+1,y)+f(x,y+1)]*2+f(x,y)*4}/16;
其中,f(x,y)为原图像中(x,y)像素点的灰度值,g(x,y)为经过高斯滤波和的值。
上述的公式可以结构化为3×3的掩模如下:
×1/16
从结构化掩模中可以看到,处于掩模中心的位置比其他任何像素的权值都大,因此在均值计算中给定的这一像素显得更为重要。而距离掩模中心较远的像素就显得不太重要,这样做是为了减小平滑处理中的模糊。当然可以采取其他的权重达到相同的目的,其中16=1+2+1+2+4+2+1+2+1。但是由于1、2、4、16都是2的整数次幂很便于硬件的实现。
openCv中的函数介绍
高斯滤波:其函数声明为: void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT ) ;
功能:对输入的图像src进行高斯滤波后用dst输出。
参数:src和dst当然分别是输入图像和输出图像。Ksize为高斯滤波器模板大小,sigmaX和sigmaY分别为高斯滤波在横线和竖向的滤波系数(有点晦涩,等下解释)。borderType为边缘点插值类型。
理解:数字图像的滤波可以简单的这么理解,就是对原图像的每一个像素滤波,那么对应这个像素滤波后的值是根据其相邻像素(包括自己那个点)与一个滤波模板进行相乘即可。所以具体到高斯滤波,我们只要知道这个高斯滤波的模板即可。
那怎么确定这个模板呢?首先这个模板的大小为ksize,其每个数字的计算是这样的:
其中 是归一化系数,因为其和要为1.
为了简化,一般在二维图像处理中,ui和uj取0,sigma1和sigma2取相等。所以公式就简化为 :
因此很容易就计算出模板每个位置的数字了,简单吧!
但是要注意2点,第一点就是ksize的宽和高必须是奇数;第二点就是如果参数sigmaX=sigmaY=0,则实际用的是公式sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8
代码:
#include"opencv2/imgproc/imgproc.hpp" #include"opencv2/highgui/highgui.hpp" //#include
//#include #include using namespace std; using namespace cv; int main() { //变量声明 Mat src,dst; char* window_name = "高斯滤波例子"; int c; //载入图像 src = imread("D:\\openCV\\openCVProject\\openCv笔记\\openCv笔记\\test.jpg"); //是否载入成功 if(!src.data ) { cout<<""<
10) { return 0; } GaussianBlur(src,dst,Size(ind,ind),0,0); imshow(window_name,dst); ind+=2; } return 0; }
三 非线性滤波
3.1中值滤波
中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点。方法是去某种结构的二维滑动模板,将板内像素按照像素值的大小进行排序,生成单调上升(或下降)的为二维数据序列。二维中值滤波输出为g(x,y)=med{f(x-k,y-l),(k,l∈W)} ,其中,f(x,y),g(x,y)分别为原始图像和处理后图像。W为二维模板,通常为2*2,3*3区域,也可以是不同的的形状,如线状,圆形,十字形,圆环形等。
中值滤波器是统计滤波器的一种,属于非线性的的空间滤波器。正如其名,它是将像素(中值计算中包括的原像素值)邻域内灰度的中值代替该像素的值。中值滤波器的使用非常普遍,这是因为对于一定类型的随机噪声,它提供了优秀的去噪能力,比小尺寸的线性平滑滤波器的模糊程度明显要低。中值滤波器对处理脉冲噪声非常有效。然说中值滤波器对脉冲信号很有效,但是仅采用简单的中值滤波将不可避免的丢失图像的细节,造成视觉效果的模糊。于是后来又些人提出了一些改进的方法,如基于个数判断的脉冲噪声的中值滤波器、自适应门限的中值滤波器、多窗口下的自适应中值滤波器等等
openCv中的函数
中值滤波:其函数声明为void medianBlur(InputArray src, OutputArray dst, int ksize)。
功能:对输入的图像src进行中值滤波后用dst输出。
参数:src和dst当然分别是输入图像和输出图像。ksize为均值滤波器模板大小,因为模板为正方形,所以只有一个参数。
理解:以原图对应像素为中心的与模板中心重叠,将模板覆盖领域内全部像素排序后的中间值就是滤波后像素的值了,所以模板长度必须为奇数
代码:
/*
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.html#filter-2d
*/
#include"opencv2/imgproc/imgproc.hpp"
#include"opencv2/highgui/highgui.hpp"
//#include
//#include
#include
using namespace std;
using namespace cv;
int main()
{
//变量声明
Mat src,dst;
Mat kernel;
Point anchor;
double delta;
int ddepth;
int kernel_size;
char* window_name = "filter2D 线性滤波例子";
int c;
//载入图像
src = imread("D:\\openCV\\openCVProject\\openCv笔记\\openCv笔记\\test.jpg");
//是否载入成功
if(!src.data )
{
cout<<""<10)
{
return 0;
}
GaussianBlur(src,dst,Size(ind,ind),0,0);
*/
medianBlur(src,dst,ind);
imshow(window_name,dst);
ind+=2;
}
return 0;
}
四形态学滤波
随着数学各分支在理论和应用上的逐步深入,以数学形态学为代表的非线性滤波在保护图像边缘和细节方面取得了显著进展[89][90]。形态学滤波器是近年来出现的一类重要的非线性滤波器,它由早期的二值形滤波器发展为后来的多值(灰度)形态滤波器,在形状识别、边缘检测、纹理分析、图像恢复和增强等领域了广泛的应用。形态滤波方法充分利用形态学运算所具有的几何特征和良好的代数性质,主要采用态学开、闭运算进行滤波操作。从形态学基本原理可知,形态学的开运算会去掉图像上与结构元素的形态不相吻合的相对亮的分布结构,同时保留那些相吻合的部分;而闭运算则会填充那些图像上与结构元素不相吻合的相对暗的分布结构,同时保留那些相吻合的部分。因此他们都可以用来有效的提取特征和平滑像。值得注意地是,采用形态滤波器时,应根据不同的目的选择具有不同形状、大小和方向特性的结构元素。此外,形态学开、闭运算都具有幂等性,这意味着一次滤波就己将所有特定于结构元素的噪声滤除千净,再次重复不会产生新的结果。这是一个经典方法(如线性卷积滤波、中值滤波)所不具备的性质。由于形态学运算是从图像的几何形态观点来进行图像处理的,因此这种优良的非线性滤波器能在滤波的同时,保持图像结构不被钝化。
这个代码见http://blog.csdn.net/caiye917015406/article/details/7797646
五 实例
几个代码的合集
//包含图像处理和界面处理的头文件
#include
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
//采用cv命名空间和标准命名空间
using namespace std;
using namespace cv;
//定义全局变量
int DELAY_CAPTION=1500; //显示标题时延时至少1.5s
int DELAY_BLUR=100; //显示每次滤波时延时0.1s
int MAX_KERNEL_LENGTH=31;//最大的滤波核长度为31
Mat src,dst;
char window_name[]="Filter Demo 1:";
//函数说明
int display_caption(char *caption);
int display_dst(int delay);
//主函数
int main()
{
namedWindow(window_name,CV_WINDOW_AUTOSIZE);//建立一个窗口
//将lena图片读写到矩阵src
src=imread("D:\\openCV\\openCVProject\\openCv笔记\\openCv笔记\\test.jpg",1);
//将Origin Image单词显示在dst图片中,并在窗口中显示1.5s
if(display_caption("Origin Image")!=0){return 0;}
dst=src.clone();//将lena图片复制到dst矩阵中,并显示出来,1.5s
if(display_dst(DELAY_CAPTION)!=0){return 0;}
/*利用均值滤波
其中矩阵滤波的函数原型为void blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT)
其中src为滤波前图像矩阵,dst为滤波后图像矩阵,ksize为滤波矩形核,anchor为定标点,如果采用的是Point(-1,-1)则默认为核的中心点,borderType为边缘模式的展开
其滤波公式为:
也就是利用ksize个像素求平均值而已,很容易理解*/
if(display_caption("Homogeneous Blur")!=0){return 0;}//显示Homogeneous Blur单词1.5s
for(int i=1;i=0){return -1;}
return 0;
}
//显示滤波后的图片,没有按键触发时返回0
int display_dst(int delay)
{
imshow(window_name,dst);
int c=waitKey(delay);
if(c>=0){return -1;}
else return 0;
}
参考:
1.http://www.eefocus.com/xhcbrave/blog/07-11/76210_62438.html
2.http://www.eefocus.com/xhcbrave/blog/07-11/76987_4fc97.html
3.http://baike.baidu.com/view/3485930.htm
4.http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.html#filter-2d
5.http://www.cnblogs.com/pegasus/archive/2011/05/19/2051416.html