OPENCV基本滤波算法
图像滤波的主要目的是为了在保留图像细节的情况下尽量的对图像的噪声进行消除,从而是后来的图像处理变得更加的方便.
图像的滤波效果要满足两个条件: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基本滤波算法的更多相关文章
- CUDA加opencv复现导向滤波算法
CUDA是GPU通用计算的一种,其中现在大热的深度学习底层GPU计算差不多都选择的CUDA,在这我们先简单了解下其中的一些概念,为了好理解,我们先用DX11里的Compute shader来和CUDA ...
- 目标跟踪之粒子滤波---Opencv实现粒子滤波算法
目标跟踪学习笔记_2(particle filter初探1) 目标跟踪学习笔记_3(particle filter初探2) 前面2篇博客已经提到当粒子数增加时会内存报错,后面又仔细查了下程序,是代码方 ...
- 基于Vivado HLS在zedboard中的Sobel滤波算法实现
基于Vivado HLS在zedboard中的Sobel滤波算法实现 平台:zedboard + Webcam 工具:g++4.6 + VIVADO HLS + XILINX EDK + ...
- SSE图像算法优化系列二十二:优化龚元浩博士的曲率滤波算法,达到约1000 MPixels/Sec的单次迭代速度
2015年龚博士的曲率滤波算法刚出来的时候,在图像处理界也曾引起不小的轰动,特别是其所说的算法的简洁性,以及算法的效果.执行效率等方面较其他算法均有一定的优势,我在该算法刚出来时也曾经有关注,不过 ...
- 非局部均值滤波算法的python实现
如题,比opencv自带的实现效果好 #coding:utf8 import cv2 import numpy as np def psnr(A, B): return 10*np.log(255*2 ...
- OpenCV: kalman滤波的代码段
序言:在我的疲劳检测工程 AviTest中!显示框为320*240,使用OpenCV的kalman滤波算法,可以实现简单的锁相追踪-实现对眼球的位置锁定. 代码如下: CvPoint Wishchin ...
- OpenCV实现KNN算法
原文 OpenCV实现KNN算法 K Nearest Neighbors 这个算法首先贮藏所有的训练样本,然后通过分析(包括选举,计算加权和等方式)一个新样本周围K个最近邻以给出该样本的相应值.这种方 ...
- 关于中值滤波算法,以及C语言实现(转)
源:关于中值滤波算法,以及C语言实现 1.什么是中值滤波? 中值滤波是对一个滑动窗口内的诸像素灰度值排序,用其中值代替窗口中心象素的原来灰度值,它是一种非线性的图像平滑法,它对脉冲干扰级椒盐噪声的抑制 ...
- 基于FPGA的均值滤波算法实现
我们为了实现动态图像的滤波算法,用串口发送图像数据到FPGA开发板,经FPGA进行图像处理算法后,动态显示到VGA显示屏上,前面我们把硬件平台已经搭建完成了,后面我们将利用这个硬件基础平台上来实现基于 ...
随机推荐
- 【jsp/servlet】 javaweb中的一些简单问题整理
1 jsp工作原理 答: 动态网页技术标准blabla...jsp程序的工作方式为请求/响应模式,客户端发出http请求,jsp程序收到请求后进行处理,并返回处理的结果. jsp程序需要运行在特定的w ...
- 一款值得推荐的shell工具
1. 一款比较出色的shell工具 熟练的运用shell语言可以提高我们的工作效率,而一款好的shell工具能提高学习的效率,fish shell就是这样一款工具.并且是一款跨平台的工具, 同时可以在 ...
- TextureView+SurfaceTexture+OpenGL ES来播放视频(二)
引自:http://www.jianshu.com/p/b2d949ab1a1a 在使用OpenGL ES 绘制前,我先概括下接下来要做的工作:我先借用一个博主kiffa举的的一个栗子,我觉得说的恰到 ...
- Android OpenGL ES(九)绘制线段Line Segment .
创建一个DrawLine Activity,定义四个顶点: float vertexArray[] = { -0.8f, -0.4f * 1.732f, 0.0f, -0.4f, 0.4f * 1.7 ...
- Ubuntu配置eclipse
1.安装jdk 去官网下载最新版jdk,目前是 jdk-8u45-linux-x64.tar.gz 创建Java的目标路径文件夹,这里我们放在/usr/lib/jvm下面.在终端下操作: sudo m ...
- 从零开始学习OpenGL ES之一 – 基本概念
我曾写过一些文章介绍iPhone OpenGL ES编程,但大部分针对的是已经至少懂得一些3D编程知识的人.作为起点,请下载我的OpenGL Xcode项目模板,而不要使用Apple提供的模板.你可以 ...
- java数据结构之链表的实现
这个链表的内部是使用双向链表来表示的,但是并未在主函数中进行使用 /** * 链表 * 2016/4/26 **/ class LinkList{ Node head = new Node(); No ...
- Unity3D项目优化(转)
前言: 刚开始写这篇文章的时候选了一个很土的题目...<Unity3D优化全解析>.因为这是一篇临时起意才写的文章,而且陈述的都是既有的事实,因而给自己“文(dou)学(bi)”加工留下的 ...
- Lucene入门教程(转载)
http://blog.csdn.net/tianlincao/article/details/6867127 Lucene教程 1 lucene简介 1.1 什么是lucene Lucene ...
- Spring的事务传播机制
1.事务传播类型 新建事务 required required_new - 挂起当前 非事务方式运行 supports not_supported - 挂起当前 never ...