图像处理_滤波器

(1)图像的平滑处理

图像的平滑也称模糊,平滑处理需要一个滤波器,最常用的滤波器就是线性滤波器,线性滤波器的输出像素值是g(x,y),是输入像素值是  f(x,y)的加权和:                                                                                    

h( k,l )称为核,它仅仅是一个加权系数,那么滤波器有很多种,最常用的滤波器介绍如下:

归一化块滤波器:是比较简单的滤波器,输出的像素值是核窗口内像素值的均值(所有像素的加权系数相等),核如下:

高斯滤波器:最有用的滤波器。高斯滤波器是将输入数组的每一个像素点与高斯内核卷积,将卷积当作输出像素值,比如一维高斯函数的:

可以发现中间像素的加权系数最大,周边的像素的加权系数随着它们远离中间像素的距离的增大而减小,二维高斯函数的表达式是

其中u为均值,峰值对应的位置,o是代表标准差,变量x,y各有一个均值,也各有一个标准差

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

双边滤波器:类似与高斯滤波器,双边滤波器也给每一个领域像素分配一个加权系数,这个加权系数包含两个部分,第一部分加权方式与高斯滤波一样(是有几何空间距离决定滤波器的系数),第二部分的权重则取决于该领域像素与当前像素的灰度差值,是一种可以包边去噪的滤波器

双边滤波器中输出滤波器的值依赖于邻域像素值的加权组合

权重系数w(i,j,k,l)取决于定义域核

和值域核

的卷积

源码与结果

  1. #include <iostream>
  2. #include <vector>
  3.  
  4. #include "opencv2/imgproc/imgproc.hpp"
  5. #include "opencv2/highgui/highgui.hpp"
  6. #include "opencv2/features2d/features2d.hpp"
  7.  
  8. using namespace std;
  9. using namespace cv;
  10.  
  11. /// 全局变量
  12. int DELAY_CAPTION = 1500;
  13. int DELAY_BLUR = 100;
  14. int MAX_KERNEL_LENGTH = 31; //最大的核长度
  15.  
  16. Mat src; Mat dst;
  17. char window_name[] = "Smoothing Demo";
  18.  
  19. /// Function headers函数声明
  20. int display_caption( const char* caption );
  21. int display_dst( int delay );
  22.  
  23. /**
  24. * function main
  25. */
  26. int main( void )
  27. {
  28. namedWindow( window_name, WINDOW_AUTOSIZE );
  29.  
  30. ///载入原图想
  31. src = imread( "/home/salm/myopencv/images/cat.jpg", 1 );
  32.  
  33. if( display_caption( "Original Image" ) != 0 ) { return 0; }
  34.  
  35. dst = src.clone();
  36. if( display_dst( DELAY_CAPTION ) != 0 ) { return 0; }
  37.  
  38. /// Applying Homogeneous blur 使用均值平滑
  39. /*blur归一化块滤波
  40. src: 输入图像
  41. dst: 输出图像
  42. Size( w,h ): 定义内核大小( w 像素宽度, h 像素高度)
  43. Point(-1, -1): 指定锚点位置(被平滑点), 如果是负值,取核的中心为锚点。
  44. */
  45. if( display_caption( "Homogeneous Blur" ) != 0 ) { return 0; }
  46.  
  47. for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
  48. { blur( src, dst, Size( i, i ), Point(-1,-1) );
  49. if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
  50.  
  51. /// Applying Gaussian blur 使用高斯平滑
  52. if( display_caption( "Gaussian Blur" ) != 0 ) { return 0; }
  53.  
  54. for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
  55. { GaussianBlur( src, dst, Size( i, i ), 0, 0 ); //Size(w, h): 定义内核的大小(需要考虑的邻域范围)。 w 和 h 必须是正奇数,否则将使用 \sigma_{x} 和 \sigma_{y} 参数来计算内核大小
  56. if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
  57.  
  58. /// Applying Median blur 中值滤波
  59. if( display_caption( "Median Blur" ) != 0 ) { return 0; }
  60.  
  61. for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
  62. { medianBlur ( src, dst, i ); //i: 内核大小 (只需一个值,因为我们使用正方形窗口),必须为奇数
  63. if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
  64.  
  65. /// Applying Bilateral Filter 双边滤波
  66. /*
  67. bilateral执行双边滤波操作
  68. src: 输入图像
  69. dst: 输出图像
  70. d: 像素的邻域直径
  71. sigma_{Color}: 颜色空间的标准方差
  72. sigma_{Space}: 坐标空间的标准方差(像素单位)
  73. */
  74. if( display_caption( "Bilateral Blur" ) != 0 ) { return 0; }
  75.  
  76. for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
  77. { bilateralFilter ( src, dst, i, i*2, i/2 );
  78. if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
  79.  
  80. /// Wait until user press a key
  81. display_caption( "End: Press a key!" );
  82.  
  83. waitKey(0);
  84.  
  85. return 0;
  86. }
  87.  
  88. /**
  89. * @function display_caption
  90. */
  91. int display_caption( const char* caption )
  92. {
  93. dst = Mat::zeros( src.size(), src.type() );
  94. putText( dst, caption,
  95. Point( src.cols/4, src.rows/2),
  96. FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );
  97.  
  98. imshow( window_name, dst );
  99. int c = waitKey( DELAY_CAPTION );
  100. if( c >= 0 ) { return -1; }
  101. return 0;
  102. }
  103.  
  104. /**
  105. * @function display_dst
  106. */
  107. int display_dst( int delay )
  108. {
  109. imshow( window_name, dst );
  110. int c = waitKey ( delay );
  111. if( c >= 0 ) { return -1; }
  112. return 0;
  113. }

结果为

腐蚀与膨胀(Eroding and Dilating)

形态学操作是基于形状的一系列图像处理操作,通过结构元素作用于输入图像来产生输出图像,最基本的形态学操作有两种:erision  与  dilation  它们的应用广泛,主要有消除噪声,分割独立的图像元素,连接相邻的元素,寻找图像中明显的极大值或极小值区域

通俗的说:膨胀算法是图像扩大一圈,腐蚀算法是图像缩小一圈,腐蚀是删除对象边界的某些元素,膨胀是给图像的边界添加某些元素,算法从图像的角度来看,二值图像的腐蚀与膨胀就是将一个小型的二值图像(比如一般为结构元素  一般为3*3的)在图像上进行逐点的运动并比较,根据比较的结果做出相应的处理。

膨胀算法:用3*3的结构元素,扫描二值图像的每一个像素,用结构元素与其覆盖的二值图像做“与”运行,如果都为“0”结构图像的该元素就为0  否则就为1   结果会使得二值图像扩大一圈

腐蚀算法:用3*3的结果元素,扫描二值图像的每一个像素,用结构元素与其覆盖的二值图像做“与”运算,结构都为1  结构图像的该元素就为1  否则就为0   结果使二值图像减小一圈

OpenCV里面的腐蚀膨胀都是针对 白色 目标区域的。说膨胀使图像 变大一圈, 那是指 图像中的 白色目标区域 扩大了一圈

源码

  1. #include "opencv2/imgproc/imgproc.hpp"
  2. #include "opencv2/highgui/highgui.hpp"
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5.  
  6. using namespace cv;
  7.  
  8. /// Global variables 全局变量
  9. Mat src, erosion_dst, dilation_dst;
  10.  
  11. int erosion_elem = 0;
  12. int erosion_size = 0;
  13. int dilation_elem = 0;
  14. int dilation_size = 0;
  15. int const max_elem = 2;
  16. int const max_kernel_size = 21;
  17.  
  18. //函数申明
  19. void Erosion( int, void* );
  20. void Dilation( int, void* );
  21.  
  22. int main( int, char** argv )
  23. {
  24. /// Load an image
  25. src = imread( argv[1] );
  26.  
  27. if( !src.data )
  28. { return -1; }
  29.  
  30. /// Create windows
  31. namedWindow( "Erosion Demo", WINDOW_AUTOSIZE );
  32. namedWindow( "Dilation Demo", WINDOW_AUTOSIZE );
  33. moveWindow( "Dilation Demo", src.cols, 0 );
  34.  
  35. /// Create Erosion Trackbar
  36. createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo",
  37. &erosion_elem, max_elem,
  38. Erosion );
  39.  
  40. createTrackbar( "Kernel size:\n 2n +1", "Erosion Demo",
  41. &erosion_size, max_kernel_size,
  42. Erosion );
  43.  
  44. /// Create Dilation Trackbar
  45. createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",
  46. &dilation_elem, max_elem,
  47. Dilation );
  48.  
  49. createTrackbar( "Kernel size:\n 2n +1", "Dilation Demo",
  50. &dilation_size, max_kernel_size,
  51. Dilation );
  52.  
  53. /// Default start
  54. Erosion( 0, 0 );
  55. Dilation( 0, 0 );
  56.  
  57. waitKey(0);
  58. return 0;
  59. }
  60.  
  61. /*
  62. 内核选择三种形状之一:
  63. 矩形: MORPH_RECT
  64. 交叉形: MORPH_CROSS
  65. 椭圆形: MORPH_ELLIPSE
  66. */
  67. void Erosion( int, void* )
  68. {
  69. int erosion_type = 0;
  70. if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; }
  71. else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; }
  72. else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }
  73.  
  74. Mat element = getStructuringElement( erosion_type,
  75. Size( 2*erosion_size + 1, 2*erosion_size+1 ),
  76. Point( erosion_size, erosion_size ) );
  77. /// Apply the erosion operation
  78. erode( src, erosion_dst, element );
  79. imshow( "Erosion Demo", erosion_dst );
  80. }
  81.  
  82. void Dilation( int, void* )
  83. {
  84. int dilation_type = 0;
  85. if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; }
  86. else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; }
  87. else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }
  88.  
  89. Mat element = getStructuringElement( dilation_type,
  90. Size( 2*dilation_size + 1, 2*dilation_size+1 ),
  91. Point( dilation_size, dilation_size ) );
  92. /// Apply the dilation operation
  93. dilate( src, dilation_dst, element );
  94. imshow( "Dilation Demo", dilation_dst );
  95. }

更改Trackbars的位置就会产生不一样的输出图像

更多的形态学变换

开运算(opening):是通过对图像先腐蚀后膨胀实现  , 能够排除小团块物体(假设物体较背景明亮)

闭运算:(closing):使用过先膨胀后腐蚀实现的,  能够排除小型黑洞(黑色区域)

形态梯度(morphological Gradient):膨胀图与腐蚀图之差 , 能够保留物体的边缘轮廓

顶帽(Top Hat):原图像与开运算结果图之差   

黑帽(black Hat):闭运算结果图与原图像之差

源码

  1. #include "opencv2/imgproc/imgproc.hpp"
  2. #include "opencv2/highgui/highgui.hpp"
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5.  
  6. using namespace cv;
  7.  
  8. /// Global variables
  9. Mat src, dst;
  10.  
  11. int morph_elem = 0;
  12. int morph_size = 0;
  13. int morph_operator = 0;
  14. int const max_operator = 4;
  15. int const max_elem = 2;
  16. int const max_kernel_size = 21;
  17.  
  18. const char* window_name = "Morphology Transformations Demo";
  19.  
  20. /** Function Headers */
  21. void Morphology_Operations( int, void* );
  22.  
  23. int main( int, char** argv )
  24. {
  25. /// 载入图像
  26. src = imread( argv[1] );
  27.  
  28. if( !src.data )
  29. { return -1; }
  30.  
  31. /// Create window
  32. namedWindow( window_name, WINDOW_AUTOSIZE );
  33.  
  34. /// Create Trackbar to select Morphology operation
  35. createTrackbar("Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat", window_name, &morph_operator, max_operator, Morphology_Operations );
  36.  
  37. /// Create Trackbar to select kernel type
  38. createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name,
  39. &morph_elem, max_elem,
  40. Morphology_Operations );
  41.  
  42. /// Create Trackbar to choose kernel size
  43. createTrackbar( "Kernel size:\n 2n +1", window_name,
  44. &morph_size, max_kernel_size,
  45. Morphology_Operations );
  46.  
  47. /// Default start
  48. Morphology_Operations( 0, 0 );
  49.  
  50. waitKey(0);
  51. return 0;
  52. }
  53.  
  54. /**
  55. * @function Morphology_Operations
  56. */
  57. void Morphology_Operations( int, void* )
  58. {
  59.  
  60. // Since MORPH_X : 2,3,4,5 and 6
  61. int operation = morph_operator + 2;
  62.  
  63. Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
  64.  
  65. /// Apply the specified morphology operation
  66. morphologyEx( src, dst, operation, element );
  67. imshow( window_name, dst );
  68. }

图像处理_imgproc笔记(1)的更多相关文章

  1. OpenCV图像处理学习笔记-Day1

    OpenCV图像处理学习笔记-Day1 目录 OpenCV图像处理学习笔记-Day1 第1课:图像读入.显示和保存 1. 读入图像 2. 显示图像 3. 保存图像 第2课:图像处理入门基础 1. 基本 ...

  2. OpenCV图像处理学习笔记-Day03

    OpenCV图像处理学习笔记-Day03 目录 OpenCV图像处理学习笔记-Day03 第31课:Canny边缘检测原理 第32课:Canny函数及使用 第33课:图像金字塔-理论基础 第34课:p ...

  3. OpenCV图像处理学习笔记-Day4(完结)

    OpenCV图像处理学习笔记-Day4(完结) 第41课:使用OpenCV统计直方图 第42课:绘制OpenCV统计直方图 pass 第43课:使用掩膜的直方图 第44课:掩膜原理及演示 第45课:直 ...

  4. 数字图像处理学习笔记之一 DIP绪论与MATLAB基础

    写在前面的话 数字图像处理系列的学习笔记是作者结合上海大学计算机学院<数字图像处理>课程的学习所做的笔记,使用参考书籍为<冈萨雷斯数字图像处理(第二版)(MATLAB版)>,同 ...

  5. 深刻认识shift_ram IP core——图像处理学习笔记

    在进行图像处理算法中,往往需要生成图像像素矩阵,这对于C语言来说可以直接用数据表示,但是对于verilog来说便不是那么容易了,硬件描述语言不比软件,它的核心不再算法,而是在于设计思想,加速硬件.在进 ...

  6. MATLAB数字图像处理学习笔记

    我们都知道一幅图片就相当于一个二维数组,可以用一个矩阵来表示,而MATLAB可以说就是为矩阵运算而生的,所以学习图像处理,学习MATLAB势在必行! 一. MATLAB基础知识 1. 读取图像 %im ...

  7. CS131&Cousera图像处理学习笔记 - L4&W2滤波和卷积

    cs131: http://vision.stanford.edu/teaching/cs131_fall1617/ coursera: https://www.coursera.org/learn/ ...

  8. OpenCV 图像处理学习笔记(一)

    解读IplImage结构 typedef struct _IplImage { int nSize;                    /* IplImage大小 */ int ID;       ...

  9. CS131&Cousera图像处理学习笔记 - L5边缘

    cs131: http://vision.stanford.edu/teaching/cs131_fall1617/ coursera: https://www.coursera.org/learn/ ...

随机推荐

  1. ios学习笔记之UIViewControl生命周期

    提到UIViewcontrol,每个人都不会陌生吧!平时实际开发中,每天的实际开发应该都少不了它.学过android的各位亲,也对生命周期这四个字并不陌生,无论是activity,还是service, ...

  2. 序列化和反序列化的几种方式(DataContractSerializer)

    序列化和反序列化的几种方式(DataContractSerializer) DataContractSerializer 类 使用提供的数据协定,将类型实例序列化和反序列化为 XML 流或文档. 无法 ...

  3. UIButton根据不同的状态设置layer

    这需要用到KVO,监听button的highlighted属性的变化,在监听回调里根据监听到得属性值设置layer 设置监听如下 [button  addObserver:self forKeyPat ...

  4. 为通过ClickOnce部署的应用程序进行数字签名

    为通过ClickOnce部署的应用程序进行数字签名 ClickOnce是.NET用于Windows应用程序的一种便捷部署方式.不过由于便捷,导致缺少自定义操作的空间.比如需要对通过ClickOnce部 ...

  5. Operation not permitted引发的惊魂72小时

    0.问题及描述 在测试产品的时候,莫名其妙发现了我们的主进程VPNd会出现以下的报错: 2013-07-18 13:05:13  www.1.com/192.168.200.220:65527 wri ...

  6. JAX-WS创建和处理SOAP消息

    JAX-WS规范是一组XML web services的JAVA API,在 JAX-WS中,一个远程调用可以转换为一个基于XML的协议例如SOAP,在使用JAX-WS过程中,开发者不需要编写任何生成 ...

  7. windows窗体继承问题

    窗体继承什么时候用的到呢?当我们使用三层架构来编写我们的cs程序时,我们的U层大部分是windows窗体.这个时候如果我们有一些公共变量,或者是一个窗体需要使用另一个窗体的数据.或者是有一些用于判断的 ...

  8. java ArrayList的序列化分析

    一.绪论 所谓的JAVA序列化与反序列化,序列化就是将JAVA 对象以一种的形式保持,比如存放到硬盘,或是用于传输.反序列化是序列化的一个逆过程. JAVA规定被序列化的对象必须实现java.io.S ...

  9. 一张图让你快速学会UML(聚合、组合、依赖、继承、接口、类)

    有朋友反映,一上来直接讲设计模式就算理解了,也不知道如何画出类图,那么我们就通过一张图,来图解如何应用UML正确表示类与类之间的关系. 这张图完整讲述了鸟类的生存. 首先是类:在UML中,我们用分成三 ...

  10. mysql数据库 触发器简单实例

    触发器(trigger):监视某种情况,并触发某种操作. 触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/befo ...