【OpenCV教程之九】平滑/模糊图片 Smooth / Blur Images及 彩色图转 灰度图和二值化

这一节,谈一谈如何对图像进行平滑,也可以叫做模糊。平滑图像的主要目的是减少噪声,这样采用平滑图像来降低噪声是是非常常见的预处理方法。

1.归一化滤波平滑-Homogeneous Smoothing

2.高斯滤波平滑-Gaussian Smoothing

3.中值滤波平滑-Median Smoothing

4.双边滤波平滑-Bilateral Smoothing

平滑是通过滑动窗口(内核或过滤器)扫描整个图像窗口,计算每个像素的基于核的值的和重叠的原始图像的像素的值的值来完成。这个过程在数学上称为具有一些内核卷积的图像。上述4种不同平滑方法唯一的区别就是内核。

例如, 5 x 5的核用来平滑(模糊)下面图片, 归一化块滤波器"Normalized box filter".

而高斯平滑(模糊)采用5x5的内核是如下。这个内核被称为“高斯核” "Gaussian kernel"

下面是关于平滑核(滤波器)比较重要的几个方面。

  • 平滑核的行像素数及列像素数必须是奇数(e.g. - 3x3, 11x5, 7x7, etc)
  • 平滑核的size越大,计算时间越长。

归一化滤波平衡 Homogeneous Smoothing

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

选择核的大小是很关键,如果选择太大,比较细微的图像特征可能被平滑掉,图像看起来很模糊。如果核选择太小,就可能无法完全删除噪声。

核定义如下:

OpenCV 代码

下面的OpenCV 的代码中,核大小从1x1增加到29x29.可以观察到图像平滑程度随着核增大的变化程度。平滑图像的核的大小显示在被平滑图像上。

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

using namespace cv;

int main( int argc, char** argv )
{
 //create 2 empty windows
 namedWindow( "Original Image" , CV_WINDOW_AUTOSIZE );
 namedWindow( "Smoothed Image" , CV_WINDOW_AUTOSIZE );

 // Load an image from file
 Mat src = imread( "MyPic.JPG", 1 );

 //show the loaded image
 imshow( "Original Image", src );

 Mat dst;
 char zBuffer[35];

 for ( int i = 1; i < 31; i = i + 2 )
 {
      //copy the text to the "zBuffer"
      _snprintf_s(zBuffer, 35,"Kernel Size : %d x %d", i, i);

      //smooth the image in the "src" and save it to "dst"
      blur( src, dst, Size( i, i ) );

      //put the text in the "zBuffer" to the "dst" image
      putText( dst, zBuffer, Point( src.cols/4, src.rows/8), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );

      //show the blurred image with the text
      imshow( "Smoothed Image", dst );

      //wait for 2 seconds
      int c = waitKey(2000);

      //if the "esc" key is pressed during the wait, return
      if (c == 27)
      {
           return 0;
      }
 }

 //make the "dst" image, black
 dst = Mat::zeros( src.size(), src.type() );

 //copy the text to the "zBuffer"
 _snprintf_s(zBuffer, 35,"Press Any Key to Exit");

 //put the text in the "zBuffer" to the "dst" image
 putText( dst, zBuffer, Point( src.cols/4,  src.rows / 2), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );

 //show the black image with the text
 imshow( "Smoothed Image", dst );

 //wait for a key press infinitely
 waitKey(0);

 return 0;

}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 
平滑图像 -可以看到随着平滑核增大,图像逐渐变得模糊

新OpenCV函数详解

  • void blur( InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType = BORDER_DEFAULT )
    • src - 源图像. (图像位深必须是; CV_8U, CV_16S, CV_16U, CV_32F or CV_64F)
    • dst - 输出图像 (必须与源图像大小及位深一致)
    • ksize - 核大小
    • anchor - 点(-1,-1)的值意味着anchor是核中心的值。如果愿意可以自己定义自己的点。
    • borderType - Y可以定义不同的边界插入方法,这个值仅仅影响边缘的像素。 (可选参数: BORDER_DEFAULT, BORDER_REFLECT, BORDER_REPLICATE, BORDER_TRANSPARENT, BORDER_REFLECT_101 )
    • void putText( Mat& img, const string& text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=8, bool bottomLeftOrigin=false )

    这个OpenCV 函数在图像上显示文字

    • img - 欲显示文字的图片
    • text - 欲在图片显示的文字
    • org - 文本字符串在图像的左下角
    • fontFace - 字体类型 (可选字体有: FONT_HERSHEY_SIMPLEX, FONT_HERSHEY_PLAIN, FONT_HERSHEY_DUPLEX, FONT_HERSHEY_COMPLEX, FONT_HERSHEY_TRIPLEX, FONT_HERSHEY_COMPLEX_SMALL, FONT_HERSHEY_SCRIPT_SIMPLEX
      or FONT_HERSHEY_SCRIPT_COMPLEX. 上面任何一个字体可以与FONT_ITALIC"按位与"(bitwise or)可以得到斜体字)
    • fontScale - 缩放因子(如果设为1,默认大小)
    • color - 文本以BGR颜色定义
    • thickness - 字粗
    • lineType - 线类型
    • bottomLeftOrigin - 如果为true,原点设置在左下角。否则原点设定在左上角
    • static MatExpr zeros(Size size, int type)

      这个OpenCV的函数将返回指定的大小和类型的数组与零值

    • size - 数组大小( e.g - Size(no. of columns, no. of rows)  )
    • type -数组元素类型

    Gaussian Smoothing

    "高斯平滑" 也叫 "高斯模糊" 或 "高斯过滤".是比较常用的一个平滑方法。是比较常见的平滑方法。也用于去除图像噪声。高斯核滑动扫描图像来对图像进行平滑。

    内核的大小和在X和Y方向上的高斯分布的标准偏差应慎重选择。

    OpenCV 代码

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/highgui/highgui.hpp"
    
    using namespace cv;
    
    int main( int argc, char** argv )
    {
     //create 2 empty windows
     namedWindow( "Original Image" , CV_WINDOW_AUTOSIZE );
     namedWindow( "Smoothed Image" , CV_WINDOW_AUTOSIZE );
    
     // Load an image from file
     Mat src = imread( "MyPic.JPG", CV_LOAD_IMAGE_UNCHANGED );
    
     //show the loaded image
     imshow( "Original Image", src );
    
     Mat dst;
     char zBuffer[35];
    
     for ( int i = 1; i  <  31; i = i + 2 )
     {
      //copy the text to the "zBuffer"
      _snprintf_s(zBuffer, 35,"Kernel Size : %d x %d", i, i);
    
      //smooth the image using Gaussian kernel in the "src" and save it to "dst"
      GaussianBlur( src, dst, Size( i, i ), 0, 0 );
    
      //put the text in the "zBuffer" to the "dst" image
      putText( dst, zBuffer, Point( src.cols/4, src.rows/8), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255), 2 );
    
      //show the blurred image with the text
      imshow( "Smoothed Image", dst );
    
      //wait for 2 seconds
      int c = waitKey(2000);
    
      //if the "esc" key is pressed during the wait, return
      if (c == 27)
      {
       return 0;
      }
     }
    
     //make the "dst" image, black
     dst = Mat::zeros( src.size(), src.type() );
    
     //copy the text to the "zBuffer"
     _snprintf_s(zBuffer, 35,"Press Any Key to Exit");
    
     //put the text in the "zBuffer" to the "dst" image
     putText( dst, zBuffer, Point( src.cols/4,  src.rows / 2), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );
    
     //show the black image with the text
     imshow( "Smoothed Image", dst );
    
     //wait for a key press infinitely
     waitKey(0);
    
     return 0;
    }
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

     
    采用高斯模糊后得到的图像

    新出现的OpenCV函数

    上面例子中OpenCV几乎都在之前例子中见到过。

    • void GaussianBlur( InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )

    这个OpenCV函数中高斯模糊的核的定义,图像的所有通道都独立的进行处理。

    • src - 源图像 (图像位深定义CV_8U, CV_16S, CV_16U, CV_32F or CV_64F)
    • dst -  输出图像 (与输入图像位深及大小必须一致)
    • ksize - 高斯平滑核大小 (核大小必须为正奇数)
    • sigmaX - 在X方向的标准偏差。如果使用0,它会自动从内核尺寸计算
    • sigmaY - 在Y方向的标准偏差。如果使用0,它会取和sigmaX一样的值.
    • borderType - 可以定义各种边界插值方法。该值只影响在边界的像素。 ( k; BORDER_DEFAULT,可选参数 BORDER_REFLECT, BORDER_REPLICATE, BORDER_TRANSPARENT, BORDER_REFLECT_101 )

    Median Smoothing

    “平均平滑处理”也被称为“中间模糊处理”或“值滤波”。这也是一种常见的平滑技术。输入图像进行卷积用中值的内核。中值滤波是广泛用于边缘检测算法,因为在某些情况下,它保留边缘的同时去除噪声。

    OpenCV Code

    代码和上面的代码只有一行不一样。

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/highgui/highgui.hpp"
    using namespace cv;
    int main( int argc, char** argv )
    {
     //create 2 empty windows
     namedWindow( "Original Image" , CV_WINDOW_AUTOSIZE );
     namedWindow( "Smoothed Image" , CV_WINDOW_AUTOSIZE );
    
     // Load an image from file
     Mat src = imread( "MyPic.JPG", CV_LOAD_IMAGE_UNCHANGED );
    
     //show the loaded image
     imshow( "Original Image", src );
    
     Mat dst;
     char zBuffer[35];
    
     for ( int i = 1; i  <  31; i = i + 2 )
     {
      //copy the text to the "zBuffer"
      _snprintf_s(zBuffer, 35,"Kernel Size : %d x %d", i, i);
    
      //smooth the image using Median kernel in the "src" and save it to "dst"
      medianBlur( src, dst, i );
    
      //put the text in the "zBuffer" to the "dst" image
      putText( dst, zBuffer, Point( src.cols/4, src.rows/8), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255), 2 );
    
      //show the blurred image with the text
      imshow( "Smoothed Image", dst );
    
      //wait for 2 seconds
      int c = waitKey(2000);
    
      //if the "esc" key is pressed during the wait, return
      if (c == 27)
      {
       return 0;
      }
     }
    
     //make the "dst" image, black
     dst = Mat::zeros( src.size(), src.type() );
    
     //copy the text to the "zBuffer"
     _snprintf_s(zBuffer, 35,"Press Any Key to Exit");
    
     //put the text in the "zBuffer" to the "dst" image
     putText( dst, zBuffer, Point( src.cols/4,  src.rows / 2), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );
    
     //show the black image with the text
     imshow( "Smoothed Image", dst );
    
     //wait for a key press infinitely
     waitKey(0);
    
     return 0;
    }
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    New OpenCV Functions

    • void medianBlur( InputArray src, OutputArray dst, int ksize )

    所有的通道图像平滑都是独立的

    • src - 输入源图像 ( images with 1, 3 or 4 channels / Image depth should be CV_8U for any value of "ksize". If "ksize" equals 3 or 5, image
      depths of CV_16U and CV_32F are also supported.
    • dst - 输出图像 (需与源图像大小和位深一致)
    • ksize - 滤波器的大小 ( 必须是奇数且大于1 ) (注意 - 滤波器的尺寸大小为ksize ksize)

    双边平滑 Bilateral Smoothing

    “双边平滑处理”也被称为“双边模糊处理”或“双边滤波”。这是最先进的过滤器,以平滑图像和减少噪音。同时去除噪声上述所有过滤器会抚平的边缘。但该过滤器能够减少图像的噪声,同时保留边缘。这种类型的过滤器的缺点是,它需要较长的时间来处理。

    OpenCV 代码

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/highgui/highgui.hpp"
    
    using namespace cv;
    
    int main( int argc, char** argv )
    {
     //create 2 empty windows
     namedWindow( "Original Image" , CV_WINDOW_AUTOSIZE );
     namedWindow( "Smoothed Image" , CV_WINDOW_AUTOSIZE );
    
     // Load an image from file
     Mat src = imread( "MyPic.JPG", CV_LOAD_IMAGE_UNCHANGED );
    
     //show the loaded image
     imshow( "Original Image", src );
    
     Mat dst;
     char zBuffer[35];
    
     for ( int i = 1; i  <  31; i = i + 2 )
     {
      //copy the text to the "zBuffer"
      _snprintf_s(zBuffer, 35,"Kernel Size : %d x %d", i, i);
    
      //smooth the image using Bilateral filter in the "src" and save it to "dst"  bilateralFilter( src, dst, i, i, i);
    
      //put the text in the "zBuffer" to the "dst" image
      putText( dst, zBuffer, Point( src.cols/4, src.rows/8), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255), 2 );
    
      //show the blurred image with the text
      imshow( "Smoothed Image", dst );
    
      //wait for 2 seconds
      int c = waitKey(2000);
    
      //if the "esc" key is pressed during the wait, return
      if (c == 27)
      {
       return 0;
      }
     }
    
     //make the "dst" image, black
     dst = Mat::zeros( src.size(), src.type() );
    
     //copy the text to the "zBuffer"
     _snprintf_s(zBuffer, 35,"Press Any Key to Exit");
    
     //put the text in the "zBuffer" to the "dst" image
     putText( dst, zBuffer, Point( src.cols/4,  src.rows / 2), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );
    
     //show the black image with the text
     imshow( "Smoothed Image", dst );
    
     //wait for a key press infinitely
     waitKey(0);
    
     return 0;
    }
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    新出现的OpenCV 函数

    • void bilateralFilter( InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT )

    此OpenCV的功能筛选使用双边内核的图像。每个通道独立进行处理。此方法不到位工作。实时应用,“d”的值建议使用一个小于5值。

    • src - 输入图像 (单通道或者三通道图像)
    • dst - 输出图像(与输入图像属性一致)
    • - 像素领域直径
    • sigmaColor - 在颜色空间的sigma
    • sigmaSpace - 在坐标空间的sigma
    • borderType - 可以定义各种边界插值方法。该值只影响在边界的像素。(可选参数如下:
      BORDER_DEFAULT, BORDER_REFLECT, BORDER_REPLICATE, BORDER_TRANSPARENT, BORDER_REFLECT_101 )
    时间: 2024-11-07 13:59:34

    【OpenCV教程之九】平滑/模糊图片 Smooth / Blur Images及 彩色图转 灰度图和二值化的相关文章

    Ubuntu 14.04 下使用 OpenCV 图片二值化处理

    参考: OpenCV - Ubuntu 14.04 64 bit 图片二值化工具 Ubuntu 14.04 下使用 OpenCV 图片二值化处理 TBD. 原文地址:https://www.cnblogs.com/qq952693358/p/8996719.html

    【数字图像】C++8位和24位BMP位图的平滑、锐化、二值化处理,以及24位真彩图的灰度化

    头文件: typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned int DWORD; typedef long LONG; //BMP文件头(14字节) typedef struct tagBITMAPFILEHEADER { //WORD bfType;//位图文件的类型,必须为BM(在结构体中读取会发生错误,所以在函数中读取) DWORD bfSize;//位图文件的大小,以字节为单位 WORD b

    ComicEnhancerPro 系列教程十七:二值化图像去毛刺

    作者:马健邮箱:[email protected] 主页:http://www.comicer.com/stronghorse/ 发布:2017.07.23 教程十七:二值化图像去毛刺 在灰度图像处理成纯黑白(二值化)图像以后,经常出现的一个问题是轮廓边缘出现毛刺.如下面这个图像: 为了看得更清楚,放大到800%并加网格线: 可以看出在"工"字的上面一横中,上边缘有几个突出点,下边缘有两个凹陷点,而在"业"字左侧竖条中有突出点,下面一横中有凹陷点. 产生毛刺的原因是

    【OPENCV】图像的预处理(灰度图、二值化、字符矫正(旋转))

    1.首先加载原始图片: 2.cvCvtColor(img, source, CV_BGR2GRAY);转化成灰度图像: 3.cvThreshold(source,source_gray,100,255,CV_THRESH_BINARY );进行二值化处理. 由于原始的图片会有一定的角度,需要进行旋转,而旋转的话可以使用OPENCV提供的函数实现,本文中采用的是自己编写的,即通过旋转360,并记录旋转某个角度的时候使得在x轴方向的投影最大化. 如图,经过处理的图片效果如下所示: 完整的工程已经上传

    [iOS OpenCV的使用,灰度和二值化]

    看网上方法很多,但版本都不够新,我看了网上一些知识,总结了下,来个最新版Xcode6.1的. 最近主要想做iOS端的车牌识别,所以开始了解OpenCV.有兴趣的可以跟我交流下哈. 一.Opencv的使用: 步骤: 1.从官网下载iOS版本的Opencv2.framework. 2.拖进工程,选择copy items if needed 3.进入building settings,设置Framework SearchPath: 设置成$(PROJECT_DIR)/Newtest,这个Newtest

    【OpenCV入门指南】第四篇 图像的二值化

    [OpenCV入门指南]第四篇 图像的二值化 在上一篇<[OpenCV入门指南]第三篇Canny边缘检测>中介绍了使用Canny算子对图像进行边缘检测.与边缘检测相比,轮廓检测有时能更好的反映图像的内容.而要对图像进行轮廓检测,则必须要先对图像进行二值化,图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出明显的黑白效果.在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓. <OpenCV入门指南>系

    python+opencv 灰度直方图及其二值化

    图像直方图(histogram)是图像的统计学特征,常用于了解图像的基本特征以便分析.不过图像的直方图不具有空间特征. 图像的灰度直方图(histogram),就是将图像转化成灰度图像之后,统计各个像素点的灰度值,绘制成直方图,其横轴是灰度值(0,255),纵轴是该灰度值所对应的像素的数目.对灰度直方图做积分=图像的size. 灰度直方图 1 def plt_hist(img): 2 plt.hist(img.ravel(), 256, [0, 256]) 3 plt.show() 三色折线图(

    c#实现图片二值化例子(黑白效果)

    C#将图片2值化示例代码,原图及二值化后的图片如下: 原图: 二值化后的图像: 实现代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 7

    验证码图片二值化问题 BitmapData 怎么解决

    对不起,这算是一篇求助啦,先上图,防止不清楚,放大了一点,下面是图片,上面是没有二值化的,下面是二值化之后的,我其实不懂什么是二值化啦,就是一定范围变黑,变白 问题: 为什么我的结果上面还是有很多彩色的小点点呢?原来都是没有的-- 谁能帮我看看代码怎么改!谢谢大牛们帮忙!! Bitmap bit1 = new Bitmap(bit); Rectangle rect1 = new Rectangle(0, 0, bit1.Width, bit1.Height); BitmapData bitd =