简单、直观的实现优于复杂、难懂的实现,最近开发扑克识别过程的总结

    最近开发了款通用的扑克识别程序,本文谈下心得。最开始是准备使用Shape Context或Zernike矩来识别的,写出了Shape Context,发现识别率达不到理想状态。接着准备用Zernike矩实现,查找文献发现,Zernike矩虽然理论上对旋转是不变的,但实际上,图像的旋转会导致识别率降低,加上样本不多,就放弃了这两种方法。最后,还是用最基本的模板匹配和Blob分析来解决的,在只有单一的样本的情况下,对不同字体不同印刷的扑克,对有扭曲、旋转以及轻微模糊的扑克,达到了99.9%的识别率(这0.1%还没出现,也就是说,理论上达到了100%)。由于是商业性开发,代码就不贴了,只谈原理。

    模板匹配就不详谈了,这是最最基本的识别方法,详见《车牌识别及验证码识别的一般思路》。而所谓Blob,就是一个整体连着的图像像素块。Blob有许多特征,比如,长、宽、重心、面积等等,还有些更复杂的Blob特征,这里就不详述了,反正都没用上。这里只谈最简单最基本的Blob的特征。基本识别过程是:

    (1)Blob特征识别,将图像分为几大组。

    (2)对每一组使用模板匹配,进行识别。

    (3)对于(2)中一些易混淆结果,再使用Blob特征,进行识别。

    一、Blob特征识别

    本文中的Blob指的是连通的黑色像素块。比如:

image

    这就是一个Blob。

    将这个Blob图像的颜色取反,也就是黑变成白,白变成黑,颠倒黑白,指鹿为马,得到这样一个图:

image

    数一下是几块?——8块!

    不过,这里的8块这个特征是不稳定的,因为图像可能会旋转变形。为了得到稳定的特征,将这个图像向上、下、左、右分别扩张几个像素,得到这样一个图像:

image

    这个图像有几块?——3块!这个3块的特征非常稳定,不受旋转及字体的影响。

    这样一来,根据图像的反色->扩大->Blob计数就可以将它分成几组:

    A组:有1个块的——2,3,5……

    B组:有2个块的——4,6……

    C组:有3个块的——8,Q(有时)……

    二、对每一组进行模板匹配

    详细就不讲了,网上一搜一大堆。

    三、对易混淆结果,再使用Blob特征进行识别。

    一些易混淆的字符,如3和5等…黑桃和草花…,再使用Blob特征进行识别。这里识别的方式五花八门,略举一二典型的。

    拿3和5来说,首先将它们取反,再扩张几个像素,再从中线劈开:3和5就变成了:

image image

    数一下几个Blob?3是1个,5是2个。

    再拿黑桃和草花来说:

image image

    分别取它们最左上的块。黑桃的左上块比较规则,一般都是近似三角形,而草花的就不规则,尤其是当图比较模糊时,会近似矩形:

image

    怎么分辨这两类呢?我定义了个对称因子: 以该Blob所属矩形的中心为对称中心,对矩形中的某一点A(x,y),找到它的对称点A’(w-x,h-y)。由于图像中像素是离散的,实际对称点是A’(w-x-1,h-y-1)。

image

    计算对称点的颜色相同的点的个数,然后用这个个数除以总的像素数量,就得到Blob的对称因子。这个定义简单、直接,方便计算。黑桃左上块的对称因子很小,而草花的左上块对称因子较大,两个就识别开了。当然,这里还辅助了其它的Blob特征,就不详述了。

    小结:

    简单的好啊。但由于简单的东西很多时候上不了台面,所以书上啊,论文上啊,很少谈。书上、论文上都喜欢谈些复杂的牛逼的东东。具体到开发项目上来说,还是能简单就简单最好。本文使用的就是最基本的模板匹配、最简单的Blob分析及最初级的决策树模型,在最少样本的情况下,达到了最高的识别率。

你可能感兴趣的:(总结)