通过复制TesserCap的斩波滤波器来消除验证码图像的背景噪声 [英] Removing the background noise of a captcha image by replicating the chopping filter of TesserCap

查看:87
本文介绍了通过复制TesserCap的斩波滤波器来消除验证码图像的背景噪声的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一张如下所示的验证码图片:





使用名为它解释了程序的确切运作方式。它给了我以下对这个斩波滤镜的作用的描述:


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


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




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



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



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

解决方案

算法基本上检查是否有一行中有多个目标像素(在本例中为非白色像素),如果像素数小于或等于斩波因子,则更改这些像素。



例如,在一个像素行示例中,为黑色且 - 为白色,应用切割因子 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])$ ​​b $ b image = PIL.Image.open( sys.argv [2])。convert('1')
width,height = image.size
data = image.load()

#遍历行。
表示范围内的y(高度):
表示范围内的宽度(宽度):

#确保我们处于黑暗像素上。
如果数据[x,y]> 128:
继续

#保持总共非白色连续像素。
total = 0

#检查从x到image.width的序列。
表示范围内的c(x,宽度):

#如果像素较暗,请将其添加到总数中。
如果数据[c,y]< 128:
总计+ = 1

#如果像素很亮,请停止序列。
else:
break

#如果总数小于印章,则用白色替换所有东西。
如果总计< = chop:
for c in range(total):
data [x + c,y] = 255

#跳过这个序列我们只是改变了。
x + =总


#迭代列。
for x in range(width):
for y in range(height):

#确保我们处于一个暗像素。
如果数据[x,y]> 128:
继续

#保持总共非白色连续像素。
total = 0

#检查从y到image.height的序列。
表示范围内的c(y,height):

#如果像素是暗的,请将其添加到总数中。
如果数据[x,c]< 128:
总计+ = 1

#如果像素很亮,请停止序列。
else:
break

#如果总数小于印章,则用白色替换所有东西。
如果总计< = chop:
for c in range(total):
data [x,y + c] = 255

#跳过此序列我们只是改变了。
y + =总计

image.save(sys.argv [3])


I have a captcha image that looks like this:

Using a utility called TesserCap from McAfee, I could apply a "chopping" filter to the image. (Before running it, I made sure there were only two colors in the image, white and black.) I was very impressed with the results of using that filter with a value of 2 in the text box. It accurately removed most of the noise but kept the main text, resulting in this:

I wanted to implement something like this on one of my own scripts, so I tried to find out what image processing library TesserCap used. I couldn't find anything; it turns out it uses its own code to process the image. I then read this whitepaper that explains exactly how the program works. It gave me the following description of what this chopping filter does:

If the contiguous number of pixels for given grayscale values are less than the number provided in the numeric box, the chopping filter replaces these sequences with 0 (black) or 255 (white) as per user choice. The CAPTCHA is analyzed in both horizontal and vertical directions and corresponding changes are made.

I am not sure I understand what it is doing. My script is in Python, so I tried using PIL to manipulate the pixels kind of like that quote described. It sounds kind of simple, but I failed, probably because I didn't really know what exactly the filter was doing:

(This is made from a slightly different captcha that uses a circular pattern.)

I also tried seeing if it could easily be done with ImageMagick's convert.exe. Their -chop option is something completely different. Using -median along with some -morphology commands helped to reduce some of the noise, but nasty dots appeared and the letters became very distorted. It wasn't nearly as simple as doing the chopping filter with TesserCap.

So, my question is as follows: how do I implement the chopping filter of TesserCap in Python, be it using PIL or ImageMagick? That chopping filter works much better than any of the alternatives I've tried, but I can't seem to replicate it. I've been working on this for hours and haven't figured anything out yet.

解决方案

The algorithm essentially checks if there are multiple target pixels (in this case, non-white pixels) in a row, and changes those pixels if the number of pixels is less than or equal to the chop factor.

For example, in a sample row of pixels, where # is black and - is white, applying a chop factor of 2 would transform --#--###-##---#####---#-# into ------###-------#####-------. This is because there sequences of black pixels that are smaller than or equal to 2 pixels, and these sequences are replaced with white. The continuous sequences of greater than 2 pixels remain.

This is the result of the chop algorithm as implemented in my Python code (below) on the original image on your post:

In order to apply this to the whole image, you simply perform this algorithm on every row and on every column. Here's Python code that accomplishes that:

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])

这篇关于通过复制TesserCap的斩波滤波器来消除验证码图像的背景噪声的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆