2015年2月11日
图像二值化效果对比_emgucv/大津法/迭代法
图像二值化应该可以提高Tessnet对图像的识别率,因此我尝试先对一些模糊化的图像进行二值化,期望二值化后的图片黑白分明,前景完整清晰,以协助Tessnet更好的辨识图片中的内容。本文对比了大津法,迭代法,emgucv的cvSmooth,cvThreshold,cvCanny等方法二值化的效果,先看验证图。
由上图可知,经典的大津法与迭代法,或者滤波+Canny边缘检测(当然,这很有可能是我参数设置的不合适)都无法将对比度低的图片执行完美的二值化。下面提供我的验证代码,请各路高手评判。
1.Emgu的cvSmooth/cvThreshold/cvCanny等函数验证源代码
如上图中所述,cvThreshold有7种二值化方法,但需要设置2个参数,我没有仔细去研究这些参数该如何设置,但我用了同样的参数去验证了每一种方法,其中OTSU是表现最好的一种。
总的来说,Emgu中的二值化与图像滤波函数很全面,但是需要设置参数这一点大大降低了其亲和力,因此这些函数我只是浅尝辄止。
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 71 72 73 74 75 76 77 78 79 80 81 |
/* -------------------------------------------------------- * 作者:livezingy * * 博客:https://www.livezingy.com * * 开发环境: * Visual Studio V2012 * .NET Framework 4.5 * * 版本历史: * V1.0 2015年02月11日 * 验证Emgu的图像二值化的功能 --------------------------------------------------------- */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using Emgu.CV; using Emgu.CV.UI;//控制台程序可不加此项 using Emgu.Util; namespace TessNetTest { class Program { static void Main(string[] args) { //cvLoadImage参数1:加载图片的路径 //cvLoadImage参数2:(-1):默认读取图像的原通道数;(0):强制转化读取图像为灰度图;(1):读取彩色图; IntPtr bmpP = CvInvoke.cvLoadImage(@"D:\CSharp\TessNetTest\ReCaptcha12.png", 0); //临时变量,cvInvoke中的相关的函数需要类似的临时变量 IntPtr tmpPtr = bmpP; //存储滤波后的图片 IntPtr smoothPtr = bmpP; //cvSmooth有5种滤波方式可以选,此处选用了高斯滤波,滤波参数参考stackOverFlow中某个最佳回答设置的,目前暂不知其具体意义 CvInvoke.cvSmooth(bmpP, smoothPtr, Emgu.CV.CvEnum.SMOOTH_TYPE.CV_GAUSSIAN, 3, 3, 0, 0); CvInvoke.cvSaveImage("ReCaptcha12_Gaussian.jpg", smoothPtr, tmpPtr); //存储大津法处理后的图片 IntPtr otsuPtr = bmpP; //cvThreshold:对图像进行二值化处理,此处选用经典的"大津法"对图像进行二值化 CvInvoke.cvThreshold(bmpP, otsuPtr, 0, 255, Emgu.CV.CvEnum.THRESH.CV_THRESH_OTSU); //cvSaveImage:将处理后的图片进行存储,第三个参数有点奇怪,该函数就指明需要一个临时的指针变量 // stackOverFlow中有人说这是程序设计的不合理 CvInvoke.cvSaveImage("ReCaptcha12_onlyOTSU.jpg", otsuPtr, tmpPtr); //存储Canny边缘检测后的图片, IntPtr cannyPtr = bmpP; //cvCanny算法需要提前设置高低两个阈值,很多相关文献中均采用Otsu的阈值和0.5倍的该阈值用来做其参数 double otsu_thresh_val = CvInvoke.cvThreshold(bmpP, otsuPtr, 0, 255,Emgu.CV.CvEnum.THRESH.CV_THRESH_TRUNC); double otsu_thresh_low = otsu_thresh_val * 0.5; CvInvoke.cvCanny(bmpP, cannyPtr, otsu_thresh_low, otsu_thresh_val, 3); CvInvoke.cvSaveImage("ReCaptcha12_onlycanny.jpg", cannyPtr, tmpPtr); //图片滤波处理后在用大津法二值化 CvInvoke.cvThreshold(smoothPtr, otsuPtr, 0, 255, Emgu.CV.CvEnum.THRESH.CV_THRESH_OTSU); CvInvoke.cvSaveImage("ReCaptcha12_smOTSU.jpg", otsuPtr, tmpPtr); //图片滤波后在使用Canny执行边缘检测 CvInvoke.cvCanny(smoothPtr, cannyPtr, otsu_thresh_low, otsu_thresh_val, 3); CvInvoke.cvSaveImage("ReCaptcha12_smCanny.jpg", cannyPtr, tmpPtr); } } |
2.大津法与迭代法源代码
这两种方案的原来码来源于http://www.firstsolver.com/wordpress/?p=1014(原链接已失效),非常感谢原作者清晰整洁的代码,让我初步了解了图像处理的基本原理,我这里就不再搬运了,有兴趣的同学可以前往原博客瞻仰。