EasyPR--开发详解(3)高斯模糊、灰度化和Sobel算子

  上篇文章中我们了解了PlateLocate的过程中的所有步骤。在本篇文章中我们对前3个步骤,分别是高斯模糊、灰度化和Sobel算子进行分析。

一、高斯模糊

 1.目标

  对图像去噪,为边缘检测算法做准备。  

 2.效果

  在我们的车牌定位中的第一步就是高斯模糊处理。

  

图1 高斯模糊效果

 3.理论 

  详细说明可以看这篇:阮一峰讲高斯模糊

  高斯模糊是非常有名的一种图像处理技术。顾名思义,其一般应用是将图像变得模糊,但同时高斯模糊也应用在图像的预处理阶段。理解高斯模糊前,先看一下平均模糊算法。平均模糊的算法非常简单。见下图,每一个像素的值都取周围所有像素(共8个)的平均值。


图2 平均模糊示意图

  在上图中,左边红色点的像素值本来是2,经过模糊后,就成了1(取周围所有像素的均值)。在平均模糊中,周围像素的权值都是一样的,都是1。如果周围像素的权值不一样,并且与二维的高斯分布的值一样,那么就叫做高斯模糊。

  在上面的模糊过程中,每个像素取的是周围一圈的平均值,也称为模糊半径为1。如果取周围三圈,则称之为半径为3。半径增大的话,会更加深模糊的效果。

 4.实践

  在PlateLocate中是这样调用高斯模糊的。

    //高斯模糊。Size中的数字影响车牌定位的效果。
    GaussianBlur( src, src_blur, Size(m_GaussianBlurSize, m_GaussianBlurSize),
        0, 0, BORDER_DEFAULT );

  其中Size字段的参数指定了高斯模糊的半径。值是CPlateLocate类的m_GaussianBlurSize变量。由于opencv的高斯模糊仅接收奇数的半径,因此变量为偶数值会抛出异常。

  这里给出了opencv的高斯模糊的API(英文,2.48以上版本)。

  高斯模糊这个过程一定是必要的么。笔者的回答是必要的,倘若我们将这句代码注释并稍作修改,重新运行一下。你会发现plateLocate过程在闭操作时就和原来发生了变化。最后结果如下。

图3 不采用高斯模糊后的结果  

  可以看出,车牌所在的矩形产生了偏斜。最后得到的候选“车牌”图块如下:

                

图4 不采用高斯模糊后的“车牌”图块

  如果不使用高斯模糊而直接用边缘检测算法,我们得到的候选“车牌”达到了8个!这样不仅会增加车牌判断的处理时间,还增加了判断出错的概率。由于得到的车牌图块中车牌是斜着的,如果我们的字符识别算法需要一个水平的车牌图块,那么几乎肯定我们会无法得到正确的字符识别效果。

 
 高斯模糊中的半径也会给结果带来明显的变化。有的图片,高斯模糊半径过高了,车牌就定位不出来。有的图片,高斯模糊半径偏低了,车牌也定位不出来。因
此、高斯模糊的半径既不宜过高,也不能过低。CPlateLocate类中的值为5的静态常量DEFAULT_GAUSSIANBLUR_SIZE,标示
着推荐的高斯模糊的半径。这个值是对于近千张图片经过测试后得出的综合定位率最高的一个值。在CPlateLocate类的构造函数
中,m_GaussianBlurSize被赋予了DEFAULT_GAUSSIANBLUR_SIZE的值,因此,默认的高斯模糊的半径就是5。如果不
是特殊情况,不需要修改它。

  在数次的实验以后,必须承认,保留高斯模糊过程与半径值为5是最佳的实践。为应对特殊需求,在CPlateLocate类中也应该提供了方法修改高斯半径的值,调用代码(假设需要一个为3的高斯模糊半径)如下:

    CPlateLocate plate;
    plate.setGaussianBlurSize(3);

  目前EasyPR的处理步骤是先进行高斯模糊,再进行灰度化。从目前的实验结果来看,基于色彩的高斯模糊过程比灰度后的高斯模糊过程更容易检测到边缘点。

二、灰度化处理

 1.目标

  为边缘检测算法准备灰度化环境。

 2.效果

  灰度化的效果如下。

图5 灰度化效果

 3.理论

  在灰度化处理步骤中,争议最大的就是信息的损失。无疑的,原先plateLocate过程面对的图片是彩色图片,而从这一步以后,就会面对的是灰度图片。在前面,已经说过这步骤是利是弊是需要讨论的。

   无疑,对于计算机而言,色彩图像相对于灰度图像难处理多了,很多图像处理算法仅仅只适用于灰度图像,例如后面提到的Sobel算子。在这种情况下,你除 了把图片转成灰度图像再进行处理别无它法,除非重新设计算法。但另一方面,转化成灰度图像后恰恰失去了最丰富的细节。要知道,真实世界是彩色的,人类对于 事物的辨别是基于彩色的框架。甚至可以这样说,因为我们的肉眼能够区别彩色,所以我们对于事物的区分,辨别,记忆的能力就非常的强。

  
车牌定位环节中去掉彩色的利弊也是同理。转换成灰度图像虽然利于使用各种专用的算法,但失去了真实世界中辨别的最重要工具---色彩的区分。举个简单的例
子,人怎么在一张图片中找到车牌?非常简单,一眼望去,一个合适大小的矩形,蓝色的、或者黄色的、或者其他颜色的在另一个黑色,或者白色的大的跟车形类似
的矩形中。这个过程非常直观,明显,而且可以排除模糊,色泽,不清楚等很多影响。如果使用灰度图像,就必须借助水平,垂直求导等方法。

 
 未来如果PlateLocate过程可以使用颜色来判断,可能会比现在的定位更清楚、准确。但这需要研究与实验过程,在EasyPR的未来版本中可能会
实现。但无疑,使用色彩判断是一种趋势,因为它不仅符合人眼识别的规律,更趋近于人工智能的本质,而且它更准确,速度更快。

 4.实践 

  在PlateLocate过程中是这样调用灰度化的。

cvtColor( src_blur, src_gray, CV_RGB2GRAY );

  这里给出了opencv的灰度化的API(英文,2.48以上版本)。

三.Sobel算子

 1.目标

  检测图像中的垂直边缘,便于区分车牌。

 2.效果

  下图是Sobel算子的效果。


图6 Sobel效果 

 3.理论  

  如果要说哪个步骤是plateLocate中的核心与灵魂,毫无疑问是Sobel算子。没有Sobel算子,也就没有垂直边缘的检测,也就无法得到车牌
的可能位置,也就没有后面的一系列的车牌判断、字符识别过程。通过Sobel算子,可以很方便的得到车牌的一个相对准确的位置,为我们的后续处理打好坚实
的基础。在上面的plateLocate的执行过程中可以看到,正是通过Sobel算子,将车牌中的字符与车的背景明显区分开来,为后面的二值化与闭操作
打下了基础。那么Sobel算子是如何运作的呢?

  Soble算子原理是对图像求一阶的水平与垂直方向导数,根据导数值的大小来判断是否是边缘。请详见CSDN小魏的博客(小心她博客里把Gx和Gy弄反了)。

  为了计算方便,Soble算子并没有真正去求导,而是使用了周边值的加权和的方法,学术上称作“卷积”。权值称为“卷积模板”。例如下图左边就是Sobel的Gx卷积模板(计算垂直边缘),中间是原图像,右边是经过卷积模板后的新图像。

  图7 Sobel算子Gx示意图

  在这里演示了通过卷积模板,原始图像红色的像素点原本是5的值,经过卷积计算(- 1 * 3 - 2 * 3 - 1 * 4 + 1 * 5 + 2 * 7 + 1 * 6 = 12)后红色像素的值变成了12。

 4.实践

  在代码中调用Soble算子需要较多的步骤。

    /// Generate grad_x and grad_y
    Mat grad_x, grad_y;
    Mat abs_grad_x, abs_grad_y;

    /// Gradient X
    //Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT );
    Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );
    convertScaleAbs( grad_x, abs_grad_x );

    /// Gradient Y
    //Scharr( src_gray, grad_y, ddepth, 0, 1, scale, delta, BORDER_DEFAULT );
    Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );
    convertScaleAbs( grad_y, abs_grad_y );

    /// Total Gradient (approximate)
    addWeighted( abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, grad );

  这里给出了opencv的Sobel的API(英文,2.48以上版本)

  在调用参数中有两个常量SOBEL_X_WEIGHT与SOBEL_Y_WEIGHT代表水平方向和垂直方向的权值,默认前者是1,后者是0,代表仅仅做水平方向求导,而不做垂直方向求导。这样做的意义是,如果我们做了垂直方向求导,会检测出很多水平边缘。水平边缘多也许有利于生成更精确的轮廓,但是由于有些车子前端太多的水平边缘了,例如车头排气孔,标志等等,很多的水平边缘会误导我们的连接结果,导致我们得不到一个恰好的车牌位置。例如,我们对于测试的图做如下实验,将SOBEL_X_WEIGHT与SOBEL_Y_WEIGHT都设置为0.5(代表两者的权值相等),那么最后得到的闭操作后的结果图为

  由于Sobel算子如此重要,可以将车牌与其他区域明显区分出来,那么问题就来了,有没有与Sobel功能类似的算子可以达到一致的效果,或者有没有比Sobel效果更好的算子?

  Sobel算子求图像的一阶导数,Laplace算子则是求图像的二阶导数,在通常情况下,也能检测出边缘,不过Laplace算子的检测不分水平和垂直。下图是Laplace算子与Sobel算子的一个对比。

图8 Sobel与Laplace示意图
  

  可以看出,通过Laplace算子的图像包含了水平边缘和垂直边缘,根据我们刚才的描述。水平边缘对于车牌的检测一般无利反而有害。经过对近百幅图像的测试,Sobel算子的效果优于Laplace算子,因此不适宜采用Laplace算子替代Sobel算子。

  除了Sobel算子,还有一个算子,Shcarr算子。但这个算子其实只是Sobel算子的一个变种,由于Sobel算子在3*3的卷积模板上计算往往不太精确,因此有一个特殊的Sobel算子,其权值按照下图来表达,称之为Scharr算子。下图是Sobel算子与Scharr算子的一个对比。

  图9 Sobel与Scharr示意图

  一般来说,Scharr算子能够比Sobel算子检测边缘的效果更好,从上图也可以看出。但是,这个“更好”是一把双刃剑。我们的目的并不是画出图像的边缘,而是确定车牌的一个区域,越精细的边缘越会干扰后面的闭运算。因此,针对大量的图片的测试,Sobel算子一般都优于Scharr算子。

  关于Sobel算子更详细的解释和Scharr算子与Sobel算子的同异,可以参看官网的介绍:Sobel与Scharr

  综上所述,在求图像边缘的过程中,Sobel算子是一个最佳的契合车牌定位需求的算子,Laplace算子与Scharr算子的效果都不如它。

  有一点要说明的:Sobel算子仅能对灰度图像有效果,不能将色彩图像作为输入。因此在进行Soble算子前必须进行前面的灰度化工作。

  

版权说明:

  本文中的所有文字,图片,代码的版权都是属于作者和博客园共同所有。欢迎转载,但是务必注明作者与出处。任何未经允许的剽窃以及爬虫抓取都属于侵权,作者和博客园保留所有权利。

参考文献:

  1.http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html

  2.http://blog.csdn.net/xiaowei_cqu/article/details/7829481

  3.http://docs.opencv.org/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.html

时间: 2024-11-02 23:22:40

EasyPR--开发详解(3)高斯模糊、灰度化和Sobel算子的相关文章

EasyPR--开发详解(6)SVM开发详解

在前面的几篇文章中,我们介绍了EasyPR中车牌定位模块的相关内容.本文开始分析车牌定位模块后续步骤的车牌判断模块.车牌判断模块是EasyPR中的基于机器学习模型的一个模块,这个模型就是作者前文中从机器学习谈起中提到的SVM(支持向量机). 我们已经知道,车牌定位模块的输出是一些候选车牌的图片.但如何从这些候选车牌图片中甄选出真正的车牌,就是通过SVM模型判断/预测得到的.   图1 从候选车牌中选出真正的车牌 简单来说,EasyPR的车牌判断模块就是将候选车牌的图片一张张地输入到SVM模型中,

Android WebView 开发详解

Android WebView 开发详解 1.概览: Android WebView 做为承载网页的载体控件,他在网页显示的过程中会产生一些事件,并回调给我们的应用程序,以便我们在网页加载过程中做应用程序想处理的事情.比如说客户端需要显示网页加载的进度.网页加载发生错误等等事件. WebView提供两个事件回调类给应用层,分别为WebViewClient,WebChromeClient开发者可以继承这两个类,接手相应事件处理.WebViewClient 主要提供网页加载各个阶段的通知,比如网页开

《Linux设备驱动开发详解(基于最新4.0内核)》前言

Linux从未停歇脚步.Linus Torvalds,世界上最伟大的程序员之一,Linux内核的创始人,Git的缔造者,仍然在没日没夜的合并补丁,升级内核.做技术,从来没有终南捷径,拼的就是坐冷板凳的傻劲. 这是一个连阅读都被碎片化的时代,在这样一个时代,人们趋向于激进.浮躁.内心的不安宁使我们极难静下心来研究什么.我见过许许多多的Linux工程师,他们的简历书写着"精通"Linux内核,有多年的工作经验,而他们的"精通"却只是把某个寄存器从0改成1,从1改成0的不

下载Zookeeper从入门到精通(开发详解,案例实战,Web界面监控)

ZooKeeper是Hadoop的开源子项目(Google Chubby的开源实现),它是一个针对大型分布式系统的可靠协调系统,提供的功能包括:配置维护.命名服务.分布式同步.组服务等. Zookeeper的Fast Fail 和 Leader选举特性大大增强了分布式集群的稳定和健壮性,并且解决了Master/Slave模式的单点故障重大隐患,这是越来越多的分布式产品如HBase.Storm(流计算).S4(流计算)等强依赖Zookeeper的原因. Zookeeper从入门到精通(开发详解,案

基于H5的微信支付开发详解

这次总结一下用户在微信内打开网页时,可以调用微信支付完成下单功能的模块开发,也就是在微信内的H5页面通过jsApi接口实现支付功能.当然了,微信官网上的微信支付开发文档也讲解的很详细,并且有实现代码可供参考,有的朋友直接看文档就可以自己实现此支付接口的开发了. 一.前言 为何我还写一篇微信支付接口的博文呢?第一,我们必须知道,所谓的工作经验很多都是靠总结出来的,你只有总结了更多知识,积累了更多经验,你才能在该行业中脱颖而出,我个人觉得如今的招聘,很多都需要工作经验(1年.3年.5年....),其

opencart 模块开发详解

opencart 模块开发详解 由 xiekanxiyang » 2013年 7月 11日 10:17 pm opencart 将页面分成若干模块, 每个模块可以有多个实例(可能这样说不是很恰当) 每个实例可以指定它出现在哪个页面 这样更好的实现了代码的可重用性,可以达到更好的页面布局的可调节性. Opencar内置了几个模块,但实际应用中我们经常要根据需要开发自己模块,现在我给大家介绍下opencart的模块开发的细节 开发步骤:首先:模块代码也分前台,后台. 后台功能是模块的安装,编辑,模块

Android相机开发详解(一)

Android相机开发详解(一) 请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的csdn博客) Android相机开发能够实现打开相机,前后摄像头切换,摄像预览,保存图片,浏览已拍照图片等相机功能. Android相机开发详解(一)主要实现打开相机,摄像预览,前后置摄像头切换,保存图片等四个功能. Android相机开发详解(二)主要实现翻页浏览相片,触控缩放浏览图片,删除图片,发送图片等四个功能. Andro

Apple Watch 开发详解

Apple Watch  开发详解 Apple Watch 开发详解 Apple Watch现在对于第三方开发者来说更多的还是一块额外的屏幕.暂时WatchKit没有能给出足够的接口.现在Watch App的主要运算逻辑需要依赖iPhone,Apple也承诺会有原生的手表App,可能要等到Apple Watch和WatchKit的完全版面世的时候. 1.两种屏幕分辨率 屏幕尺寸 38mm 42mm 分辨率 272 x 340 312 x 390 宽高比 4:5 4:5 2.三种屏幕模式 主屏模式

****基于H5的微信支付开发详解[转]

这次总结一下用户在微信内打开网页时,可以调用微信支付完成下单功能的模块开发,也就是在微信内的H5页面通过jsApi接口实现支付功能.当然了,微信官网上的微信支付开发文档也讲解的很详细,并且有实现代码可供参考,有的朋友直接看文档就可以自己实现此支付接口的开发了. 一.前言 为何我还写一篇微信支付接口的博文呢?第一,我们必须知道,所谓的工作经验很多都是靠总结出来的,你只有总结了更多知识,积累了更多经验,你才能在该行业中脱颖而出,我个人觉得如今的招聘,很多都需要工作经验(1年.3年.5年....),其