通过复制TesserCap的斩波滤波器来消除验证码图像的背景噪声

Nic*_*las 10 python imagemagick image-processing python-imaging-library

我有一个看起来像这样的验证码图像:

使用McAfee的TesserCap实用程序,我可以对图像应用"斩波"过滤器.(在运行之前,我确保图像中只有两种颜色,白色和黑色.)我对在文本框中使用值为2的滤镜的结果印象深刻.它准确地删除了大部分噪音,但保留了正文,导致:

我想在我自己的一个脚本上实现类似的东西,所以我试图找出TesserCap使用的图像处理库.我找不到任何东西; 事实证明它使用自己的代码来处理图像.然后我读了这篇白皮书,它解释了该程序的确切运作方式.它给了我以下对这个斩波滤波器的作用:

如果给定灰度值的连续像素数小于数字框中提供的数量,则斩波滤波器根据用户选择用0(黑色)或255(白色)替换这些序列.在水平和垂直方向上分析CAPTCHA并进行相应的改变.

我不确定我明白它在做什么.我的脚本是用Python编写的,所以我尝试使用PIL来操纵类似于所描述的引用的像素.这听起来很简单,但我失败了,可能是因为我真的不知道过滤器到底在做什么:

(这是使用稍微不同的使用圆形图案的验证码制作的.)

我也试过看看是否可以用ImageMagick的convert.exe轻松完成.他们的-chop选项完全不同.使用-median和一些形态命令有助于减少一些噪音,但出现了令人讨厌的点,字母变得非常扭曲.它不像使用TesserCap进行斩波过滤器那么简单.

所以,我的问题如下:如何使用PIL或ImageMagick在Python中实现TesserCap的斩波过滤器?切碎过滤器比我尝试过的任何替代方案都要好得多,但我似乎无法复制它.我已经工作了好几个小时,还没有想出任何东西.

kbh*_*mes 10

该算法基本上检查一行中是否存在多个目标像素(在这种情况下,非白色像素),并且如果像素的数量小于或等于斩波因子,则改变这些像素.

例如,在像素的一行样本中,其中#黑色-是白色,应用切换因子2将变换--#--###-##---#####---#-#------###-------#####-------.这是因为存在小于或等于2个像素的黑色像素序列,并且这些序列被白色替换.保留大于2个像素的连续序列.

这是我的Python代码(下面)在帖子上的原始图像中实现的chop算法的结果:

'切碎'的形象

为了将其应用于整个图像,您只需在每一行和每一列上执行此算法.这是完成以下内容的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])
Run Code Online (Sandbox Code Playgroud)

  • @JohnSmith 好吧...“while x &lt; width:”,然后在循环开始时使用“x += 1”,显然 x 需要初始化为某个值(例如“-1”)。 (2认同)