去噪验证码的条纹
我正在处理一种带有噪声条纹的验证码。这些条纹是随机方向的,而且都是直的。数字和条纹的颜色也是完全随机的。
下面的代码可以借助 tesseract
来识别一些验证码中的数字,具体可以参考这个链接:识别简单数字。
from pytesser.pytesser import *
from PIL import Image, ImageFilter, ImageEnhance
im = Image.open("test.tiff")
im = im.filter(ImageFilter.MedianFilter()) # blur the image, the stripes will be erased
im = ImageEnhance.Contrast(im).enhance(2) # increase the contrast (to make image clear?)
im = im.convert('1') # convert to black-white image
text = image_to_string(im)
print "text={}".format(text)
去除条纹的方法是先模糊图像,然后再锐化它。 在大多数情况下,识别的准确率是100%,但我在想是否有其他方法可以去除条纹,而不模糊数字。
任何建议都非常感谢。
3 个回答
1
在图像处理领域,有一类数学问题叫做“修复”。
你需要先得到一些条纹的遮罩,才能进行后续的操作。
这里有我整理的一些文章:http://dpaste.com/0CZ25FT。里面有很多现代的研究资料。
在OpenCV这个库里,有几个算法可以用:“Navier-Stokes”和“Telea”,不过它们在处理大面积修复时效果不太好。
你也可以在SciKit找到一些关于修复的参考资料,但那里的算法还没有完全实现。
另外,如果条纹的宽度始终是1个像素,可以通过扩张和腐蚀的方法轻松去掉。想了解更多,可以查阅Woods和Gonzalez的《数字图像处理》一书。
1
第二个例子很简单:扫描边缘,找出条纹的颜色,然后把这个颜色变成白色。(这些彩色线条并不是一个很强的验证码特征。)
第一个和第三个例子就比较复杂了,因为这些条纹的颜色和某些字符是一样的。你可以通过只去掉周围邻居少的条纹颜色的像素来解决这个问题。更好的方法是分析图像的轮廓,找出条纹的方向,并看看哪些周围的像素组合对应于条纹像素。
从技术上讲,你需要进行一种叫做“腐蚀”的操作,使用合适的形状作为结构元素。
3
为什么不试试利用这些条纹的宽度呢?我猜它们最多只有5像素。那么可以尝试做一些类似下面的伪代码:
- 把你的图片转换成一个
numpy
数组。 - 对于
方向
来说,可以是上、下、左、右
: - 创建一个新的
numpy
数组,向方向
移动5像素,并裁剪掉边缘。 - 把新数组和旧数组进行“与”运算。
- 检查左下角。如果是白色的,那就完成了,你的图片已经去噪了。如果不是,就试试下一个方向。
考虑到数字的宽度比条纹要厚,我猜去掉条纹的效果会比“与”运算带来的失真要好。