使用PYTHON PIL去除验证码图像中的背景噪声线
我有一张处理过的验证码图片(放大后),看起来像这样:
从图中可以看到,“TEXT”的字体大小比那些杂乱线条的宽度要大一些。
所以我需要一个算法或代码来去掉这张图片上的杂乱线条。
我尝试使用Python的PIL库和下面提到的切割算法,但最终得到的图片还是不容易被OCR(光学字符识别)识别。
这是我尝试过的Python代码:
import PIL.Image
import sys
# python chop.py [chop-factor] [in-file] [out-file]
chop = int(sys.argv[1])
image = PIL.Image.open(sys.argv[2]).convert('1')
width, height = image.size
data = image.load()
# Iterate through the rows.
for y in range(height):
for x in range(width):
# Make sure we're on a dark pixel.
if data[x, y] > 128:
continue
# Keep a total of non-white contiguous pixels.
total = 0
# Check a sequence ranging from x to image.width.
for c in range(x, width):
# If the pixel is dark, add it to the total.
if data[c, y] < 128:
total += 1
# If the pixel is light, stop the sequence.
else:
break
# If the total is less than the chop, replace everything with white.
if total <= chop:
for c in range(total):
data[x + c, y] = 255
# Skip this sequence we just altered.
x += total
# Iterate through the columns.
for x in range(width):
for y in range(height):
# Make sure we're on a dark pixel.
if data[x, y] > 128:
continue
# Keep a total of non-white contiguous pixels.
total = 0
# Check a sequence ranging from y to image.height.
for c in range(y, height):
# If the pixel is dark, add it to the total.
if data[x, c] < 128:
total += 1
# If the pixel is light, stop the sequence.
else:
break
# If the total is less than the chop, replace everything with white.
if total <= chop:
for c in range(total):
data[x, y + c] = 255
# Skip this sequence we just altered.
y += total
image.save(sys.argv[3])
所以,基本上我想知道有没有更好的算法或代码,能够去掉这些噪声,从而让图片能够被OCR(比如Tesseract或pytesser)识别。
3 个回答
0
我个人使用扩张和腐蚀这两个方法,正如上面提到的,但我还会结合一些基本的统计数据,比如宽度和高度,尝试找出异常值,并根据需要去掉那些不合适的线条。接下来,我会用一个过滤器,它会找出一个小区域内的最小值,并把这个最小值的颜色应用到临时图像的中心像素上(这个过程是对旧图像进行逐步处理),然后再用这个临时图像替换原来的图像。在Pillow/PIL库中,可以通过img.filter(ImageFilter.MINFILTER)来完成这个最小值的操作。
如果这样还不够,应该能生成一个可以识别的集合,这样就可以使用OpenCV的轮廓和最小边界旋转框来旋转字母进行比较(在这个阶段,我推荐使用Tesseract或者一些商业的OCR工具,因为它们支持很多字体,并且有像聚类和清理这样的额外功能)。
0
你可以使用自己写的膨胀和腐蚀函数,这样可以去掉最细的线条。一个不错的实现方法可以在这里找到。
1
为了快速去掉大部分的线条,你可以把周围只有两个或更少黑色像素的黑色像素变成白色。这样就能解决那些多余的线条问题。然后,当你有很多“块”的时候,可以把小的那些去掉。
这里假设你放大了样本图像,并且线条只有一个像素宽。