Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / OpenCV 之 图像平滑

1  图像平滑  图像平滑,可用来对图像进行去噪 (noise reduction) 或 模糊化处理 (blurring),实际上图像平滑仍然属于图像空间滤波的一种 (低通滤波)  既然是滤波,则图像中任一点 (x, y),经过平滑滤波后的输出 g(x, y) 如下:g(x,y)=∑ s=−a a ∑ t=−b b w(s,t)f(x+s,y+t)  g(x,y)=∑s=−aa∑t=−bbw(s,t)f(x+s,y+t)  以 3X3 的滤波器为例 (即 a=b=1),则矩阵 Mx 和 Mf 对应的元素乘积之和,就是 g(x, y)  其中,M x =? ? ? w(−1,−1)w(0,−1)w(1,−1) w(−1,0)w(0,0)w(1,0) w(−1,1)w(1,1)w(1,1) ? ? ? M f =? ? ? f(x−1,y−1)f(x,y−1)f(x+1,y−1) f(x−1,y)f(x,y)f(x+1,y) f(x−1,y+1)f(x+1,y+1)f(x+1,y+1) ? ? ?  Mx=[w(−1,−1)w(−1,0)w(−1,1)w(0,−1)w(0,0)w(1,1)w(1,−1)w(1,0)w(1,1)]Mf=[f(x−1,y−1)f(x−1,y)f(x−1,y+1)f(x,y−1)f(x,y)f(x+1,y+1)f(x+1,y−1)f(x+1,y)f(x+1,y+1)]2  OpenCV 函数  OpenCV 中主要有四个函数涉及到图像平滑,分别是盒式滤波 (box),高斯滤波 (Gaussian),中值滤波 (median),双边滤波 (bilateral)2.1  盒式滤波  输出图像的任一像素灰度值,等于其所有邻域像素灰度值的平均值  模糊化核为,K=α? ? ? ? ? 111 111 ............ 111 111  ? ? ? ? ?  K=α[11...1111...11...11...11]   其中,α={1ksize.weidth∗ksize.height 1 when normalize = trueotherwise  α={1ksize.weidth∗ksize.heightwhen normalize = true1otherwisevoid cv::boxFilter ( InputArray src, // 输入图像OutputArraydst, // 输出图像intddepth,// 输出图像深度,-1 表示等于 src.depth()Size ksize, // 模糊化核 (kernel) 的大小Pointanchor = Point(-1,-1), // 锚点位置,缺省值表示 anchor 位于模糊核的正中心bool normalize = true,// 是否归一化处理intborderType = BORDER_DEFAULT// 边界模式)  取 ddepth = 1,normalize = true,则可以得到模糊化函数 (blur)boxFilter( src, dst, -1, ksize, anchor, true, borderType );  模糊化函数 (blur),本质上是一个输入和输出图像深度 (ddepth) 相同,并且做归一化处理的盒式滤波器void cv::blur (InputArraysrc,OutputArray dst,
Size ksize,Point anchor = Point(-1,-1),int borderType = BORDER_DEFAULT)2.2  中值滤波  中值滤波最为简单,常用来消除椒盐噪声  输出图像中 (x, y) 点处的像素值,等于输入图像以 (x, y) 为中心点的邻域像素 (ksize x ksize) 平均值void cv::medianBlur ( InputArray src,OutputArraydst,intksize // 滤波器孔径大小,一般为奇数且大于 1,比如 3, 5, 7, ...) 2.3  高斯滤波  高斯滤波最为有用,它是根据当前像素和邻域像素之间,空间距离的不同,计算得出一个高斯核 (邻域像素的加权系数),  然后,高斯核从左至右、从上到下遍历输入图像,与输入图像的像素值求卷积和,得到输出图像的各个像素值  G 0 (x,y)=Ae −(x−μ x ) 2 2σ 2 x  +−(y−μ y ) 2 2σ 2 y    G0(x,y)=Ae−(x−μx)22σx2+−(y−μy)22σy2  无须理会公式的复杂,只需要记住一点即可:邻域像素距离当前像素越远 (saptial space),则其相应的加权系数越小  为了便于直观理解,可看下面这个一维高斯核,推而广之将 G(x) 曲线以 x=0 这条轴为中心线,旋转360度可想象其二维高斯核    void cv::GaussianBlur ( InputArray src, OutputArraydst,Sizeksize, // 高斯核的大小doublesigmaX,// 高斯核在x方向的标准差doublesigmaY = 0,// 高斯核在y方向的标准差,缺省为 0,表示 sigmaY = sigmaXint borderType = BORDER_DEFAULT )    注意: 高斯核的大小 Size(width, height),w 和 h 二者不必相同但必须都是奇数,若都设为 0,则从 sigma 自动计算得出2.4  双边滤波  上面三种方法都是低通滤波,因此在消除噪声的同时,也常会将边缘信息模糊化。双边滤波和高斯滤波类似,但是它将邻域像素的加权系数分为两部分,  第一部分与高斯滤波的完全相同,第二部分则考虑当前像素和邻域像素之间灰度值的差异,从而在消除噪声的基础上,也较好的保留了图像的边缘信息void cv::bilateralFilter (InputArraysrc,OutputArray dst,int d,// 像素邻域直径,若为非正值,则从 sigmaSpace 自动计算得出doublesigmaColor,// 颜色空间的标注方差doublesigmaSpace,// 坐标空间的标准方差int borderType = BORDER_DEFAULT ) 注意 1)  双边滤波相比以上三种滤波方法,其处理速度很慢,因此,一般建议取 d=5 用于实时图像处理,d=9 适合于非实时的图像领域 注意 2)  sigmaColor 和 sigmaSpace 可取相同值,一般在 10 ~ 150 之间,小于 10,则没什么效果,大于 150,则效果太强烈,看起来明显“卡通化”3  代码示例
3.1 OpenCV  OpenCV 中的示例,通过逐渐增大像素邻域的大小 Size(w, h),将上述滤波过程动态化,非常形象的展示了邻域大小对滤波效果的影响1 /**2* file Smoothing.cpp3* brief Sample code for simple filters4* author OpenCV team5*/6 #include <iostream>7 #include <vector>8 9 #include "opencv2/imgproc/imgproc.hpp" 10 #include "opencv2/imgcodecs.hpp" 11 #include "opencv2/highgui/highgui.hpp" 12 #include "opencv2/features2d/features2d.hpp" 1314 using namespace std; 15 using namespace cv; 1617 /// Global Variables 18 int DELAY_CAPTION = 1500; 19 int DELAY_BLUR = 100; 20 int MAX_KERNEL_LENGTH = 31; 2122 Mat src; Mat dst; 23 char window_name[] = "Smoothing Demo"; 2425 /// Function headers 26 int display_caption( const char* caption ); 27 int display_dst( int delay ); 282930 /** 31* function main 32*/ 33 int main( void ) 34 { 35 namedWindow( window_name, WINDOW_AUTOSIZE ); 3637 /// Load the source image 38 src = imread( "../data/lena.jpg", 1 ); 3940 if( display_caption( "Original Image" ) != 0 ) { return 0; } 4142 dst = src.clone(); 43 if( display_dst( DELAY_CAPTION ) != 0 ) { return 0; } 444546 /// Applying Homogeneous blur 47 if( display_caption( "Homogeneous Blur" ) != 0 ) { return 0; } 4849 for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) 50 { blur( src, dst, Size( i, i ), Point(-1,-1) ); 51 if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } 525354 /// Applying Gaussian blur 55 if( display_caption( "Gaussian Blur" ) != 0 ) { return 0; } 5657 for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) 58 { GaussianBlur( src, dst, Size( i, i ), 0, 0 ); 59 if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } 606162 /// Applying Median blur 63 if( display_caption( "Median Blur" ) != 0 ) { return 0; } 6465 for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) 66 { medianBlur ( src, dst, i ); 67 if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } 686970 /// Applying Bilateral Filter 71 if( display_caption( "Bilateral Blur" ) != 0 ) { return 0; } 7273 for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 ) 74 { bilateralFilter ( src, dst, i, i*2, i/2 ); 75 if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } } 7677 /// Wait until user press a key 78 display_caption( "End: Press a key!" ); 7980 waitKey(0); 8182 return 0; 83 } 8485 /** 86* @function display_caption 87*/ 88 int display_caption( const char* caption ) 89 { 90 dst = Mat::zeros( src.size(), src.type() ); 91 putText( dst, caption, 92Point( src.cols/4, src.rows/2), 93FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) ); 9495 imshow( window_name, dst ); 96 int c = waitKey( DELAY_CAPTION ); 97 if( c >= 0 ) { return -1; } 98 return 0; 99 }100 101 /**102* @function display_dst103*/104 int display_dst( int delay )105 {106 imshow( window_name, dst );107 int c = waitKey ( delay );108 if( c >= 0 ) { return -1; }109 return 0;110 }View Code3.2  滤波对比  实际中,可直接调用以上四个滤波函数,代码如下: 1 #include "opencv2/imgproc/imgproc.hpp" 2 #include "opencv2/highgui/highgui.hpp" 34 using namespace std; 5 using namespace cv; 67 int main() 8 { 9 Mat src = imread("E:/smooth/bird.jpg");10 if(src.empty())return -1;11 12 namedWindow("original", CV_WINDOW_AUTOSIZE);13 namedWindow("blur", CV_WINDOW_AUTOSIZE);14 namedWindow("GaussianBlur", CV_WINDOW_AUTOSIZE);15 namedWindow("medianBlur", CV_WINDOW_AUTOSIZE);16 namedWindow("bilateralFilter", CV_WINDOW_AUTOSIZE);17 18 imshow("original", src);19 20 Mat dst;21 22 blur(src, dst, Size(3,3));23 imshow("blur", dst);24 25 medianBlur(src,dst,3);26 imshow("medianBlur",dst);27 28 GaussianBlur(src,dst,Size(3,3),0);29 imshow("GaussianBlur",dst);30 31 bilateralFilter(src,dst,9,50,50);32 imshow("bilateralFilter",dst);33 34 waitKey(0);35 return 0;36 }  四种滤波方法的效果图,如下所示:  参考资料 <Digital Image Processing_3rd> chapter 3 <Learning OpenCV_2nd> <OpenCV Tutorials> imgproc module - Smoothing ImagesOpenCV官方教程中文版(For Python) PDF  http://www.linuxidc.com/Linux/2015-08/121400.htmUbuntu Linux下安装OpenCV2.4.1所需包 http://www.linuxidc.com/Linux/2012-08/68184.htmUbuntu 12.04 安装 OpenCV2.4.2 http://www.linuxidc.com/Linux/2012-09/70158.htmCentOS下OpenCV无法读取视频文件 http://www.linuxidc.com/Linux/2011-07/39295.htmUbuntu 12.04下安装OpenCV 2.4.5总结 http://www.linuxidc.com/Linux/2013-06/86704.htmUbuntu 10.04中安装OpenCv2.1九步曲 http://www.linuxidc.com/Linux/2010-09/28678.htm基于QT和OpenCV的人脸识别系统 http://www.linuxidc.com/Linux/2011-11/47806.htm[翻译]Ubuntu 14.04, 13.10 下安装 OpenCV 2.4.9  http://www.linuxidc.com/Linux/2014-12/110045.htmOpenCV的详细介绍:请点这里
OpenCV的下载地址:请点这里本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-05/131280.htm