zoukankan      html  css  js  c++  java
  • [转载+原创]Emgu CV on C# (四) —— Emgu CV on 全局固定阈值二值化

    重点介绍了全局二值化原理及数学实现,并利用emgucv方法编程实现。

    一、理论概述(转载,如果懂图像处理,可以略过,仅用作科普,或者写文章凑字数) 

    1、概述

        图像二值化是图像处理中的一项基本技术,也是很多图像处理技术的预处理过程。

        图像的预处理在进行图像二值化操作前要对图像进行预处理,包括彩色图像灰化和增强。由于选取阈值需要参照直方图,因此在图像进行处理后,我们再获取图像的直方图以帮助选取阈值。整个流程如下所示:  

        读取图像→灰度图像→图像增强→图像直方图→二值化处理 

    2、数学原理(转载,基本可以不用看,具体参灰度图像二值化方法研究

        图像二值化是指用灰度变换来研究灰度图像的一种常用方法,即设定某一阈值将灰度图像的像素分成大于阈值的像素群和小于阈值的像素群两部分。例如输人灰度图像函数为,输出二值图像函数为,则 

        

         阈值(threshold )是把目标和背景区分开的标尺,选取适当的阈值就是既要尽可能保存图像信息,又要尽可能减少背景和噪声的干扰,这是选择阈值的原则。

         图像的二值化处理就是将图像上的点的灰度置为0或255,也就是使整个图像呈现出明显的黑白效果。即将256个亮度等级的灰度图像通过适当的阀值选取而获得仍然可以反映图像整体和局部特征的二值化图像。  

         灰度图像的二值化处理有很多种方法,主要分为全局阈值法和局部阈值法。

    全局阈值法

        全局阈值法是指在二值化过程中只使用一个全局阈值的方法。它将图像的每个像素的灰度值与进行比较,若大于,则取为前景色(白色);否则,取为背景色。根据文本图像的直方图或灰度空间分布确定一个阈值,以此实现灰度文本图像到二值图像的转化。其中全局阈值法又可分为基于点的阈值法和基于区域的阈值法。阈值分割法的结果很大程度上依赖于对阈值的选择,因此该方法的关键是如何选择合适的阈值。

        典型的全局阈值方法包括Otsu方法、最大熵方法等。全局阈值法算法简单,对于目标和背景明显分离、直方图分布呈双峰的图像效果良好,但对于由于光照不均匀、噪声干扰较大等原因使直方图分布不呈双峰的图像,二值化效果明显变差。若目标与背景之间灰度差不明显,可能出现大块黑色区域,甚至丢失整幅图像的信息;仅利用一维灰度直方图分布,没有结合图像的空间相关信息,处理效果不好;当图像中有断裂现象或者背景有一定噪声时,无法得到预期效果。 

        为了满足图像处理应用系统自动化及实时性要求,图像二值化的阈值的选择最好由计算机自动来完成。下面列举几个阈值的自动选择算法:

           (1) 平均灰度值法:以图像中所有像素灰度值的平均值为阈值。

           (2) 大津法:又称最大类间差法,是基于整幅图像的统计特性,实现阈值的自动选取。其原理是把图像直方图用某一灰度值分割成两类,分别计算这两类的像素点数和灰度平均值,然后计算它们的类间方差。当被分割成的两类类间方差最大时,此灰度值就作为图像二值化处理的阈值。大津法的使用范围比较广,不论图像的直方图有无明显的双峰,都能得到较满意的结果,在很多领域得到了应用和发展。但此方法依然存在一些不足,主要表现在:若目标与背景之间灰度差不明显,可能出现大块黑色区域,甚至丢失整幅图像的信息;仅利用一维灰度直方图分布,没有结合图像的空间相关信息,处理效果不好;当图像中有断裂现象或者背景有一定噪声时,无法得到预期效果。

           (3) 边缘算子法:采用Laplace算子、Robert算子、Sober算子等对像素点进行灰度级增强或减弱的变换。对于灰度均匀分布的区域内的像素点,这些算子对其进行灰度减弱;对于在边缘附近的像素点,这些算子对其进行灰度增强。

    局部阈值法

        由当前像素灰度值与该像素周围点局部灰度特征来确定像素的阈值。例如可以将原图像划分为一些不相交的小块,将各块图像的灰度均值作为该部块图像的阈值,在局部上采用上面的整体阈值法。

        对于目标和背景比较清楚的图像,全局阈值化方法可以取得较好结果。但是如果图像的背景不均匀,或目标灰度变化率比较大,全局方法便不再适用。局部阈值法是用像素灰度值和此像素邻域的局部灰度特性来确定该像素的阈值的。当照明不均匀、有突发噪声,或者背景灰度变化较大时,局部阈值确定技术必须根据像素的坐标位置关系自动确定不同阈值,实施动态的自适应二值化处理。局部阈值选取一般将图像划分为若干子图像,在每个子图像区域上使用整体阈值法,从而可以构成整幅图像的局部阈值法(根据每个子图像确定相应的阈值,具体的阈值确定方法同全局阈值的确定类似)。用这种方法分割后的图像在不同子图像的边界处有灰度的不连续分布,因此必须采用平滑技术来消除灰度的不连续性。  

        局部阈值法一般用于识别干扰比较严重、品质较差的图像,相对整体阈值方法有更广泛的应用,但也存在缺点和问题,如实现速度慢、不能保证字符笔画连通性以及容易出现伪影现象(即在背景域受到噪音干扰得到笔画结果)等。比较典型的局部二值化算法有Bernsen方法、多阈值的梯度强度法、基于纹理图像的方法、最大方差法等。

        本文重点介绍全局固定阈值二值化,局部自适应阈值可参见下一篇文章。

    3、优点

        在数字图像处理中,二值图像占有非常重要的地位,特别是在实用的图像处理中,以二值图像处理实现而构成的系统是很多的,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像,这样子有利于再对图像做进一步处理时,图像的集合性质只与像素的值为0或255的点的位置有关,不再涉及像素的多级值,使处理变得简单,而且数据的处理和压缩量小。二值图像在图像分析中应用非常广泛,二值图像就是指只有两个灰度级的图像,二值图像具有存储空间小,处理速度快,可以方便地对图像进行布尔逻辑运算等特点。更重要的是,在二值图像的基础上,还可以进一步对图像处理,获得该图像的一些几何特征或者其他更多特征。

    二、程序实现

     opencv编程方法可参看《图像的二值化和灰度化》和《【OpenCV入门指南】第四篇 图像的二值化

     emgucv编程方法可参看《C# OpenCV学习笔记四之图像二值化

    1、关键函数

    根据《C# OpenCV学习笔记四之图像二值化》提供的方法,emgucv可以用两种函数实现二值化。

    一种是cvThreshold,另一种是ThresholdBinary,下面分别介绍。

    cvThreshold方法 

    函数功能:采用Canny方法对图像进行边缘检测 

    函数原型:

    C#
    public static double cvThreshold(
    	IntPtr src,
    	IntPtr dst,
    	double threshold,
    	double maxValue,
    	THRESH thresholdType
    )

    函数说明:

    第一个参数表示输入图像,必须为单通道灰度图。

    第二个参数表示输出的边缘图像,为单通道黑白图。

    第三个参数表示阈值

    第四个参数表示最大值。

    第五个参数表示运算方法。

    Emgu.CV.CvEnum.THRESH中可以找到运算方法。

     ValueDescription
      CV_THRESH_BINARY 0 value = value > threshold ? max_value : 0
      CV_THRESH_BINARY_INV 1 value = value > threshold ? 0 : max_value
      CV_THRESH_TRUNC 2 value = value > threshold ? threshold : value
      CV_THRESH_TOZERO 3 value = value > threshold ? value : 0
      CV_THRESH_TOZERO_INV 4 value = value > threshold ? 0 : value
      CV_THRESH_MASK 7  
      CV_THRESH_OTSU 8 use Otsu algorithm to choose the optimal threshold value; combine the flag with one of the above CV_THRESH_* values

    值得一说的是threshold_type可以使用CV_THRESH_OTSU类型,这样该函数就会使用大律法OTSU得到的全局自适应阈值来进行二值化图片,而参数中的threshold不再起作用。比如:cvThreshold( dst, dst,300 , 255,   CV_THRESH_OTSU | CV_THRESH_BINARY_INV);这种方法对于灰度直方图呈现二峰特征的图片处理起来效果很好。当然你也可以使用已有的OTSU算法来计算该阈值。

    给窗体添加第四个PictureBox,并将SizeModel设置为Zoom

    在均衡化功能函数后直接添加下段程序函数,阈值为30,so easy。

    //二值化
    Image<Gray, Byte> threshimg = new Image<Gray, Byte>(histmi.width, histmi.height);
    CvInvoke.cvThreshold(histimage, threshimg, 30, 255, Emgu.CV.CvEnum.THRESH.CV_THRESH_BINARY);
    pictureBox4.Image = threshimg.ToBitmap();

    ThresholdBinary函数

    emgucv提供的方法解释:Threshold the image such that: dst(x,y) = max_value, if src(x,y)>threshold; 0, otherwise。其实和cvThreshold函数中的第一种运算方法,即CV_THRESH_BINARY一样。

    Image<Gray, Byte> threshimg= grayimg.ThresholdBinary(new Gray(128), new Gray(255));

    三、结果分析

    与文章《【OpenCV入门指南】第四篇 图像的二值化》算法进行比对,不同方法下图片的处理结果。

    原文章取阈值为111,实现的二值化效果。

    利用emgucv编程,设定阈值为111获取的二值化效果图。

    由于未能获取原始图像,只是通过截图获取的图片,不知截图过程中是否有图片损失。

    通过肉眼比较,部分细节还是有些差别。

    根据应用需要,调整阈值,从而获取最优效果。

    转载请标明出处,原文地址:http://www.cnblogs.com/MobileBo/p/3918119.html

    四、遗憾

    阈值自适应调整目前还木有时间学习,抽时间看看吧。

  • 相关阅读:
    Html禁止粘贴 复制 剪切
    表单标签
    自构BeanHandler(用BeansUtils)
    spring配置中引入properties
    How Subcontracting Cockpit ME2ON creates SD delivery?
    cascadia code一款很好看的微软字体
    How condition value calculated in sap
    Code in SAP query
    SO Pricing not updated for partial billing items
    Javascript learning
  • 原文地址:https://www.cnblogs.com/MobileBo/p/3918119.html
Copyright © 2011-2022 走看看