图像平滑处理

目标

本教程教您怎样使用各种线性滤波器对图像进行平滑处理,相关OpenCV函数如下:

原理

Note

以下原理来源于Richard Szeliski 的著作 Computer Vision: Algorithms and Applications 以及 Learning OpenCV

  • 平滑 也称 模糊, 是一项简单且使用频率很高的图像处理方法。

  • 平滑处理的用途有很多, 但是在本教程中我们仅仅关注它减少噪声的功用 (其他用途在以后的教程中会接触到)。

  • 平滑处理时需要用到一个 滤波器 。 最常用的滤波器是 线性 滤波器,线性滤波处理的输出像素值 (i.e. ) 是输入像素值 (i.e. )的加权和 :

     称为 , 它仅仅是一个加权系数。

    不妨把 滤波器 想象成一个包含加权系数的窗口,当使用这个滤波器平滑处理图像时,就把这个窗口滑过图像。

  • 滤波器的种类有很多, 这里仅仅提及最常用的:

归一化块滤波器 (Normalized Box Filter)

  • 最简单的滤波器, 输出像素值是核窗口内像素值的 均值 ( 所有像素加权系数相等)

  • 核如下:

高斯滤波器 (Gaussian Filter)

  • 最有用的滤波器 (尽管不是最快的)。 高斯滤波是将输入数组的每一个像素点与 高斯内核 卷积将卷积和当作输出像素值。

  • 还记得1维高斯函数的样子吗?

    假设图像是1维的,那么观察上图,不难发现中间像素的加权系数是最大的, 周边像素的加权系数随着它们远离中间像素的距离增大而逐渐减小。

Note

2维高斯函数可以表达为 :

其中  为均值 (峰值对应位置),  代表标准差 (变量  和 变量  各有一个均值,也各有一个标准差)

中值滤波器 (Median Filter)

中值滤波将图像的每个像素用邻域 (以当前像素为中心的正方形区域)像素的 中值 代替 。

双边滤波 (Bilateral Filter)

  • 目前我们了解的滤波器都是为了 平滑 图像, 问题是有些时候这些滤波器不仅仅削弱了噪声, 连带着把边缘也给磨掉了。 为避免这样的情形 (至少在一定程度上 ), 我们可以使用双边滤波。
  • 类似于高斯滤波器,双边滤波器也给每一个邻域像素分配一个加权系数。 这些加权系数包含两个部分, 第一部分加权方式与高斯滤波一样,第二部分的权重则取决于该邻域像素与当前像素的灰度差值。
  • 详细的解释可以查看 链接

源码

  • 本程序做什么?

    • 装载一张图像
    • 使用4种不同滤波器 (见原理部分) 并显示平滑图像
  • 下载代码: 点击 这里

  • 代码一瞥:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp" using namespace std;
using namespace cv; /// 全局变量
int DELAY_CAPTION = 1500;
int DELAY_BLUR = 100;
int MAX_KERNEL_LENGTH = 31; Mat src; Mat dst;
char window_name[] = "Filter Demo 1"; /// 函数申明
int display_caption( char* caption );
int display_dst( int delay ); /**
* main 函数
*/
int main( int argc, char** argv )
{
namedWindow( window_name, CV_WINDOW_AUTOSIZE ); /// 载入原图像
src = imread( "../images/lena.jpg", 1 ); if( display_caption( "Original Image" ) != 0 ) { return 0; } dst = src.clone();
if( display_dst( DELAY_CAPTION ) != 0 ) { return 0; } /// 使用 均值平滑
if( display_caption( "Homogeneous Blur" ) != 0 ) { return 0; } for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ blur( src, dst, Size( i, i ), Point(-1,-1) );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } /// 使用高斯平滑
if( display_caption( "Gaussian Blur" ) != 0 ) { return 0; } for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ GaussianBlur( src, dst, Size( i, i ), 0, 0 );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } /// 使用中值平滑
if( display_caption( "Median Blur" ) != 0 ) { return 0; } for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ medianBlur ( src, dst, i );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } /// 使用双边平滑
if( display_caption( "Bilateral Blur" ) != 0 ) { return 0; } for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ bilateralFilter ( src, dst, i, i*2, i/2 );
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } /// 等待用户输入
display_caption( "End: Press a key!" ); waitKey(0);
return 0;
} int display_caption( char* caption )
{
dst = Mat::zeros( src.size(), src.type() );
putText( dst, caption,
Point( src.cols/4, src.rows/2),
CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) ); imshow( window_name, dst );
int c = waitKey( DELAY_CAPTION );
if( c >= 0 ) { return -1; }
return 0;
} int display_dst( int delay )
{
imshow( window_name, dst );
int c = waitKey ( delay );
if( c >= 0 ) { return -1; }
return 0;
}

解释

  1. 下面看一看有关平滑的OpenCV函数,其余部分大家已经很熟了。

  2. 归一化块滤波器:

    OpenCV函数 blur 执行了归一化块平滑操作。

    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
    { blur( src, dst, Size( i, i ), Point(-1,-1) );
    if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }

    我们输入4个实参 (详细的解释请参考 Reference):

    • src: 输入图像
    • dst: 输出图像
    • Size( w,h ): 定义内核大小( w 像素宽度, h 像素高度)
    • Point(-1, -1): 指定锚点位置(被平滑点), 如果是负值,取核的中心为锚点。
  3. 高斯滤波器:

    OpenCV函数 GaussianBlur 执行高斯平滑 :

    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
    { GaussianBlur( src, dst, Size( i, i ), 0, 0 );
    if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }

我们输入4个实参 (详细的解释请参考 Reference):

  • src: 输入图像
  • dst: 输出图像
  • Size(w, h): 定义内核的大小(需要考虑的邻域范围)。  和  必须是正奇数,否则将使用  和  参数来计算内核大小。
  • : x 方向标准方差, 如果是  则  使用内核大小计算得到。
  • : y 方向标准方差, 如果是  则  使用内核大小计算得到。.
  1. 中值滤波器:

    OpenCV函数 medianBlur 执行中值滤波操作:

    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
    { medianBlur ( src, dst, i );
    if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }

    我们用了3个参数:

    • src: 输入图像
    • dst: 输出图像, 必须与 src 相同类型
    • i: 内核大小 (只需一个值,因为我们使用正方形窗口),必须为奇数。
  2. 双边滤波器

    OpenCV函数 bilateralFilter 执行双边滤波操作:

    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
    { bilateralFilter ( src, dst, i, i*2, i/2 );
    if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }

    我们使用了5个参数:

    • src: 输入图像
    • dst: 输出图像
    • d: 像素的邻域直径
    • : 颜色空间的标准方差
    • : 坐标空间的标准方差(像素单位)

结果

  • 程序显示了原始图像( lena.jpg) 和使用4种滤波器之后的效果图。

  • 这里显示的是使用 中值滤波 之后的效果图:

翻译者

niesu@ OpenCV中文网站 <sisongasg@hotmail.com>

from: http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.html#smoothing

OpenCV图像平滑处理的更多相关文章

  1. 八.使用OpenCv图像平滑操作

    1.cvSmooth函数 函数 cvSmooth 可使用简单模糊.简单无缩放变换的模糊.中值模糊.高斯模糊.双边滤波的不论什么一种方法平滑图像.每一种方法都有自己的特点以及局限. 没有缩放的图像平滑仅 ...

  2. OpenCV 图像平滑处理

    #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" us ...

  3. OpenCV 之 图像平滑

    1  图像平滑 图像平滑,可用来对图像进行去噪 (noise reduction) 或 模糊化处理 (blurring),实际上图像平滑仍然属于图像空间滤波的一种 (低通滤波) 既然是滤波,则图像中任 ...

  4. 图像滤波与OpenCV中的图像平滑处理

    .About图像滤波 频率:可以这样理解图像频率,图像中灰度的分布构成一幅图像的纹理.图像的不同本质上是灰度分布规律的不同.但是诸如"蓝色天空"样的图像有着大面积近似的灰度强度,而 ...

  5. OpenCV图像处理篇之图像平滑

    图像平滑算法 图像平滑与图像模糊是同一概念,主要用于图像的去噪.平滑要使用滤波器.为不改变图像的相位信息,一般使用线性滤波器,其统一形式例如以下: %20\Large%20g(i,j)=\sum_{k ...

  6. 13、OpenCV实现图像的空间滤波——图像平滑

    1.空间滤波基础概念 1.空间滤波基础 空间滤波一词中滤波取自数字信号处理,指接受或拒绝一定的频率成分,但是空间滤波学习内容实际上和通过傅里叶变换实现的频域的滤波是等效的,故而也称为滤波.空间滤波主要 ...

  7. OpenCV学习笔记(8)——图像平滑

    使用不同的低筒滤波器对图像进行模糊 使用自定义的率弄起对图像进行卷积(2D卷积) 2D卷积 与信号一样,我们也可以对2D图像实施低通滤波,高通滤波等.LPF帮助我们去除噪声,模糊图像.而HPF帮助我们 ...

  8. Python 图像处理 OpenCV (7):图像平滑(滤波)处理

    前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...

  9. OpenCV计算机视觉学习(4)——图像平滑处理(均值滤波,高斯滤波,中值滤波,双边滤波)

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice &q ...

随机推荐

  1. MYSQL-----流程控制 if() 函数的用法

    语法:IF(condition,result,result) 如果函数的第一个参数中给定的condition符合条件(如,condition不等于0或者不为NULL),那么函数的执行结果为第二个参数中 ...

  2. Linux (x86) Exploit 开发系列教程之六(绕过ASLR - 第一部分)

    转:https://bbs.pediy.com/thread-217390.htm 前提条件: 经典的基于堆栈的缓冲区溢出 虚拟机安装:Ubuntu 12.04(x86) 在以前的帖子中,我们看到了攻 ...

  3. linux——(3)文件与目录管理

    文件与目录管理相关指令 ls [-adlR] 目录 #查看目录与文件的命令. -a #连同隐藏文件一起列出来. -d #只列出目录. -l #列出相关属性和权限等数据. -R #连同子目录内容一起列出 ...

  4. BZOJ1087【状压DP】

    题目链接[http://www.lydsy.com/JudgeOnline/problem.php?id=1087] 题意:在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击 ...

  5. [APIO2010]特别行动队 --- 斜率优化DP

    [APIO2010]特别行动队 题面很直白,就不放了. 太套路了,做起来没点感觉了. \(dp(i)=dp(j)+a*(s(i)-s(j))^{2}+b*(s(i)-s(j))+c\) 直接推出一个斜 ...

  6. [GCJ2017R2]Fresh Chocolate

    题目大意: 有n个团和很多盒糖,每个团中人数不一定相同,每盒糖中都有p颗糖. 现在要给每个团发糖,要求每个人都要发到糖,只有一盒糖发完后才能发下一盒糖. 发糖的顺序可以任意安排,问经过合理安排后,最多 ...

  7. [AHOI2009]同类分布

    题目大意: 问在区间[l,r]内的正整数中,有多少数能被其个位数字之和整除. 思路: 数位DP. 极端情况下,每一位都是9,所以各位数字之和不超过9*18.(为了方便这里用了9*19) f[i][j] ...

  8. Spring Mvc 前台数据的获取、SpringMvc 表单数据的获取

    首先在web.xml 里面配置一个编码过滤器 <!-- springmvc框架本身没有处理请求编码,我们自己配置一个请求编码过滤器 --> <filter> <filte ...

  9. Problem C: 深入浅出学算法004-求多个数的最小公倍数

    Description 求n个整数的最小公倍数 Input 多组测试数据,先输入整数T表示组数 然后每行先输入1个整数n,后面输入n个整数k1 k2...kn Output 求k1 k2 ...kn的 ...

  10. 高斯消元法求解异或方程组: cojs.tk 539.//BZOJ 1770 牛棚的灯

    高斯消元求解异或方程组: 比较不错的一篇文章:http://blog.sina.com.cn/s/blog_51cea4040100g7hl.html cojs.tk  539. 牛棚的灯 ★★☆   ...