图像滤波的主要目的是为了在保留图像细节的情况下尽量的对图像的噪声进行消除,从而是后来的图像处理变得更加的方便.

图像的滤波效果要满足两个条件:1.不能损坏图像的轮廓和边缘这些重要的特征信息.2.图像的视觉效果更好

opencv支持图像滤波,提供了五个基本算法,分别是方框滤波,均值滤波,高斯滤波,中值滤波以及双边滤波,前三种为线性滤波算法,后两种为非线性滤波算法,接下来分别对这五种滤波方式进行讲解和演示

一.方框滤波

首先,线性滤波算法必须知道的概念叫做邻域算子,是指利用一张图片中给点的像素点的周围的像素值决定该给定点的像素的一种算子,爱opencv中经常使用,用来做图像的模糊或者是锐化,例如,邻域算子实际上是一个X*Y的矩阵和该矩阵怎么和图像中的像素进行计算并得到最终的结果的一种集合性质的描述.

就像程序=算法+数据结构一样,邻域算子=矩阵+计算方法,计算方法可以是乘法,除法,求和,卷积等.

方框滤波算法的原理很简单,指定一个X*Y的矩阵大小,目标像素的周围X*Y矩阵内的像素全部相加作为目标像素的值,就这么简单.

API: void boxFilter(源图像,目的图像,int 输出图像的深度,Size 邻域算子的大小,Point 锚点,bool 归一化标志,int 边界模式).

说明:1.源图像可以是彩色图或者是灰度图,因为图像处理的时候,通道是分开来处理的

2.目的图像的大小和通道数必须和源图像相同,另外,目的图像的深度由后一个参            数决定

3.输出图像的深度,指定CV_8U....,当为-1的时候,目标图像的深度和源图像的深度                            相同

4.锚点,指被平滑的那个点位于领域算子矩阵的哪一个位置,从而确定计算时候的                   像素点的取值,如果是Point(-1,-1),那么自动取值中间的那个点.

5.归一化标志,默认归一化为真,会将目标图像归一化到源图像的取值范围

可以看到,我们可以改变的参数就是邻域算子的大小,通过这种算法,我们能够去除图像中突然出现的极大值点(噪点)的影响,但是同时,这种算法不能很好的保存图像的细节,在滤波的时候容易丢失细节.一下是方框滤波的程序演示.

//方¤?框¨°滤?波¡§
const int g_boxFilterMax = 100;//最大的邻域取值
int g_nboxFilterValue;
Mat boxFilterImage;
Mat srcImage;
void onBoxFilterTrackBar(int pos,void* userData); int main(int argc,char* argv[])
{
g_nboxFilterValue = 5;
srcImage = imread("F:\\opencv\\OpenCVImage\\boxFilter.jpg"); namedWindow("box filter");
createTrackbar("size value ", "box filter", &g_nboxFilterValue, g_boxFilterMax,onBoxFilterTrackBar,0);
onBoxFilterTrackBar(g_nboxFilterValue, 0); imshow("src image", srcImage);
moveWindow("src image", 0, 0);
moveWindow("box filter", srcImage.cols, 0); waitKey(0);
return 0;
} void onBoxFilterTrackBar(int pos,void* userData)
{
if(pos == 0)
{
imshow("box filter", srcImage);
}
else
{
boxFilter(srcImage, boxFilterImage, srcImage.depth(), Size(pos,pos));
imshow("box filter", boxFilterImage);
}
}

  

二.均值滤波

均值滤波其实就是方框滤波的默认归一化版本,这个算法接口取消了归一化参数,所以实际效果和方框滤波,差异不大

API void blur(源图,目标图,size,锚点,边界模式);

实际操作代码如下

// 均值滤波
Mat srcImage;
const int g_blurMax = 100;
int g_nblurValue;
Mat blurImage;
void onBlurTrackBar(int pos,void* userData);
int main(int argc,char* argv[])
{
srcImage = imread("F:\\opencv\\OpenCVImage\\boxFilter.jpg");
g_nblurValue = 5; namedWindow("blur");
createTrackbar("size value ", "blur", &g_nblurValue, g_blurMax,onBlurTrackBar,0);
onBlurTrackBar(g_nblurValue, 0); imshow("src image", srcImage);
moveWindow("src image", 0, 0);
moveWindow("blur", srcImage.cols, 0); waitKey(0);
return 0;
} void onBlurTrackBar(int pos,void* userData)
{
if(pos == 0)
{
imshow("blur", srcImage);
}
else
{
boxFilter(srcImage, blurImage, srcImage.depth(), Size(pos,pos));
imshow("blur", blurImage);
}
}

  

三.高斯滤波

高斯滤波是专门用于消除满足高斯分布(正态分布)的误差而存在的滤波,此时邻域算子是专门的高斯核,图像中的像素与高斯核做卷积,生成的结果加权平均存放到目标像素中,对于抑制符合正态分布的噪声非常有效,并可以增强图像值不同比例下的图像效果,视觉效果类似于隔了一层半透明玻璃看图像.

API:void GaussianBlur(源图像,目标图像,Size 高斯内核,double 高斯核函数在X方向上的标准差,double 高斯核函数在Y方向的标准差,int 边界模式).

注:高斯核函数的大小必须为奇数,同时也必须为正数,原图片可以使单通道或者是多通道,如果X,Y方向标准差都为0,那么API将自动根据核函数的长宽,计算出一个合适的二维零均值高斯函数.

使用代码如下

Mat srcImage;
const int g_GaussianBlurMax = 100;
int g_nGaussianBlurValue;
Mat GaussianBlurImage;
void onGaussianBlurTrackBar(int pos,void* userData);
int main(int argc,char* argv[])
{
srcImage = imread("F:\\opencv\\OpenCVImage\\boxFilter.jpg");
g_nGaussianBlurValue = 5;
namedWindow("GaussianBlur");
createTrackbar("size value ", "GaussianBlur", &g_nGaussianBlurValue, g_GaussianBlurMax,onGaussianBlurTrackBar,0);
onGaussianBlurTrackBar(g_nGaussianBlurValue, 0); imshow("src image", srcImage);
moveWindow("src image", 0, 0);
moveWindow("GaussianBlur", srcImage.cols, 0);
waitKey(0);
return 0;
} void onGaussianBlurTrackBar(int pos,void* userData)
{
if(pos == 0)
{
imshow("GaussianBlur", srcImage);
}
else
{
//高斯滤波核必须为奇数
if(pos%2 == 0)
{
pos++;
}
GaussianBlur(srcImage, GaussianBlurImage, Size(pos,pos), 0,0);//自动计算xy标准差
imshow("GaussianBlur",GaussianBlurImage);
}
}

  

通过以上的情况我们可以看到,对于那种散粒噪声,尖峰噪声,线性滤波往往不能很好的清除,或者清除之后必然会带来对邻域的影响,噪声只是变得柔和了而已.这时候就可以考虑非线性滤波

四.中值滤波

线性滤波的基本原理是对指定像素的指定邻域的灰度值进行一个排序,然后选择中间的灰度值来直接替代指定像素的灰度值,从而消除孤立的噪声点,对于斑点噪声和椒盐噪声尤其有用,同时还可以保存边缘.对脉冲型的干扰尤其有效,因为在实际情况中,噪声点的灰度和邻域的值的差别很大,所以,中值一般不容易是噪声点灰度.但是因为基于统计排序,所以运行时间一般是均值滤波的五倍以上.

API:void medianBlur(源图像,目标图像,int 邻域大小)

注:邻域必须是大于1的奇数

使用例子如下

const int g_MedianBlurMax = 100;
int g_nMedianBlurValue;
Mat MedianBlurImage;
Mat srcImage;
void onMedianBlurTrackBar(int pos,void* userData); int main(int argc,char* argv[])
{
srcImage = imread("F:\\opencv\\OpenCVImage\\boxFilter.jpg"); g_nMedianBlurValue = 5;
namedWindow("median filter");
createTrackbar("size value ", "median filter", &g_nMedianBlurValue, g_MedianBlurMax,onMedianBlurTrackBar,0);
onMedianBlurTrackBar(g_nMedianBlurValue, 0); imshow("src image", srcImage);
moveWindow("src image", 0, 0);
moveWindow("median filter", srcImage.cols, 0); waitKey(0);
return 0;
} void onMedianBlurTrackBar(int pos,void* userData)
{
if(pos == 0)
{
imshow("median filter", srcImage);
}
else
{
//中值¦滤波孔径大小必须为奇数
if(pos%2 == 0)
{
pos++;
}
medianBlur(srcImage, MedianBlurImage, pos);
imshow("median filter",MedianBlurImage);
}
}

  

五.双边滤波

前面的滤波,或多或少的都会使得目标点的像素受到邻域的影响,邻域越大,影响越大,而双边滤波同时考虑了图像的灰度相似性和空间域信息,基本理念是邻域的计算附带权重,距离目标点越远的邻域像素对目标像素的影响越小,也就是权重越低,这样,离得较远的像素就不会对边缘的影响过多,能很好的保存边缘,同时也能滤波部分噪声.

但是,双边滤波保存了过多的高频信息,对于彩色图像中的高频噪声,双边滤波不能很好的滤除掉.

API:void bilateralFilter(源图像,目标图像,int 像素邻域直径, ,double 颜色空间滤波器sigma doble 坐标空间滤波器sigma,int 边缘类型);

注:1.若像素直径为负数,会自动从坐标空间滤波器sigma来计算像素邻域直径.

2.颜色空间滤波器sigma值,这个值越大,代表像素领域内越宽广的颜色会被混合在一                            起,造成更大的半相等的颜色区域

3.坐标空间滤波器sigma,这是坐标空间的标准方差,这个值越大,代表邻域空间中越远              的值会相互影响

例程如下

Mat srcImage;
const int g_BialateralFilterMax = 100;
int g_nBialateralFilterValue;
Mat BialateralFilterImage;
void onBialateralFilterTrackBar(int pos,void* userData);
int main(int argc,char* argv[])
{
srcImage = imread("F:\\opencv\\OpenCVImage\\boxFilter.jpg");
g_nBialateralFilterValue = 5;
namedWindow("bilateral filter");
createTrackbar("size value ", "bilateral filter", &g_nBialateralFilterValue, g_BialateralFilterMax,onBialateralFilterTrackBar,0);
onBialateralFilterTrackBar(g_nBialateralFilterValue, 0); imshow("src image", srcImage);
moveWindow("src image", 0, 0);
moveWindow("bilateral filter", srcImage.cols, 0); waitKey(0);
return 0;
} //双边滤波计算速度比较慢
void onBialateralFilterTrackBar(int pos,void* userData)
{
if(pos == 0)
{
imshow("bilateral filter", srcImage);
}
else
{
//必须为奇数
if(pos%2 == 0)
{
pos++;
}
bilateralFilter(srcImage, BialateralFilterImage, pos, pos/2, pos*2);
imshow("bilateral filter",BialateralFilterImage);
}
}

  

小结:以上就是opencv的五种基本滤波操作,在实际应用中,要根据实际情况灵活的选择滤波方式,噪声不同,图像数据的分析重点不同,都会影响最终滤波算法的选择.

OPENCV基本滤波算法的更多相关文章

  1. CUDA加opencv复现导向滤波算法

    CUDA是GPU通用计算的一种,其中现在大热的深度学习底层GPU计算差不多都选择的CUDA,在这我们先简单了解下其中的一些概念,为了好理解,我们先用DX11里的Compute shader来和CUDA ...

  2. 目标跟踪之粒子滤波---Opencv实现粒子滤波算法

    目标跟踪学习笔记_2(particle filter初探1) 目标跟踪学习笔记_3(particle filter初探2) 前面2篇博客已经提到当粒子数增加时会内存报错,后面又仔细查了下程序,是代码方 ...

  3. 基于Vivado HLS在zedboard中的Sobel滤波算法实现

     基于Vivado HLS在zedboard中的Sobel滤波算法实现 平台:zedboard  + Webcam 工具:g++4.6  + VIVADO HLS  + XILINX EDK + ...

  4. SSE图像算法优化系列二十二:优化龚元浩博士的曲率滤波算法,达到约1000 MPixels/Sec的单次迭代速度

      2015年龚博士的曲率滤波算法刚出来的时候,在图像处理界也曾引起不小的轰动,特别是其所说的算法的简洁性,以及算法的效果.执行效率等方面较其他算法均有一定的优势,我在该算法刚出来时也曾经有关注,不过 ...

  5. 非局部均值滤波算法的python实现

    如题,比opencv自带的实现效果好 #coding:utf8 import cv2 import numpy as np def psnr(A, B): return 10*np.log(255*2 ...

  6. OpenCV: kalman滤波的代码段

    序言:在我的疲劳检测工程 AviTest中!显示框为320*240,使用OpenCV的kalman滤波算法,可以实现简单的锁相追踪-实现对眼球的位置锁定. 代码如下: CvPoint Wishchin ...

  7. OpenCV实现KNN算法

    原文 OpenCV实现KNN算法 K Nearest Neighbors 这个算法首先贮藏所有的训练样本,然后通过分析(包括选举,计算加权和等方式)一个新样本周围K个最近邻以给出该样本的相应值.这种方 ...

  8. 关于中值滤波算法,以及C语言实现(转)

    源:关于中值滤波算法,以及C语言实现 1.什么是中值滤波? 中值滤波是对一个滑动窗口内的诸像素灰度值排序,用其中值代替窗口中心象素的原来灰度值,它是一种非线性的图像平滑法,它对脉冲干扰级椒盐噪声的抑制 ...

  9. 基于FPGA的均值滤波算法实现

    我们为了实现动态图像的滤波算法,用串口发送图像数据到FPGA开发板,经FPGA进行图像处理算法后,动态显示到VGA显示屏上,前面我们把硬件平台已经搭建完成了,后面我们将利用这个硬件基础平台上来实现基于 ...

随机推荐

  1. addEventListener与removeEventListener

    addEventListener:添加事件监听器 element.addEventListener(event, function, useCapture) event:事件类型,字符串,不要加&qu ...

  2. 转 由一次磁盘告警引发的血案:du 和 ls 的区别

    如果你完全不明白或者完全明白图片含义, 那么你不用继续往下看了. 否则, 这篇文章也许正是你需要的. 背景 确切地说,不是收到的自动告警短信或者邮件告诉我某机器上的磁盘满了,而是某同学人肉发现该机器写 ...

  3. 设置TabBar分栏控制器上图片的大小问题

    我们都知道,iOS因为屏幕分辨率的问题,UID在交付我们iOS开发人员程序配图的时候,一般是三套图,分别对应三种不同的分辨率,对不同size的屏幕系统会自动使用不同像素的图片,我们只需要在命名时给三套 ...

  4. 灵感闪现 篇 (一) 2d场景 3d 效果

    中途打断一下 ,框架文档的 更新. 另开一篇主题为 灵感闪现的 板块. 在工作生活中,总有发现新事物或新东西 而让自己突然 灵感闪现的时候,那么这个时候,我必须要抓住,并尽快把 这份灵感实现下来. 之 ...

  5. POJ 1523 SPF (去掉割点能形成联通块的个数)

    思路:使用tarjan算法求出割点,在枚举去掉每一个割点所能形成的联通块的个数. 注意:后来我看了下别的代码,发现我的枚举割点的方式是比较蠢的方式,我们完全可以在tarjan过程中把答案求出来,引入一 ...

  6. Linux学习 -- 备份与恢复

    备份 Linux系统需要备份的数据 /root/ /home/ /var/spool/mail /etc/ others 备份策略 完全备份 增量备份 差异备份 备份和恢复命令 dump  resto ...

  7. HDU 3265 Posters ——(线段树+扫描线)

    第一次做扫描线,然后使我对线段树的理解发生了动摇= =..这个pushup写的有点神奇.代码如下: #include <stdio.h> #include <algorithm> ...

  8. 在Visual C++中的用ADO进行数据库编程

    1. 生成应用程序框架并初始化OLE/COM库环境 创建一个标准的MFC AppWizard(exe)应用程序,然后在使用ADO数据库的InitInstance函数中初始化OLE/COM库(因为ADO ...

  9. Ubuntu14.04下SP_Flash_Tool_exe_Linux无法烧录

    1,用命令lsusb查看usb信息. 2,vim 20-mm-blacklist-mtk.rules 输入下面内容: ATTRS{idVendor}=="0e8d",ENV{ID_ ...

  10. jna

    http://topmanopensource.iteye.com/blog/1752355