返回介绍

7.2 光学字符识别

发布于 2024-02-05 23:37:18 字数 3696 浏览 0 评论 0 收藏 0

光学字符识别Optical Character RecognitionOCR )用于从图像中抽取文本。本节中,我们将使用开源的Tesseract OCR引擎。该引擎最初由惠普公司开发,目前由Google主导。Tesseract的安装说明可以从https://code. google.com/p/tesseract-ocr/wiki/ReadMe 获取。然后,可以使用pip 安装其Python封装版本pytesseract 。

pip install pytesseract

如果直接把验证码原始图像传给pytesseract ,解析结果一般都会很糟糕。

>>> import pytesseract
>>> img = get_captcha(html)
>>> pytesseract.image_to_string(img)
''

上面的代码在执行后,会返回一个空字符串 [1] ,也就是说Tesseract在抽取输入图像中的字符时失败了。这是因为Tesseract的设计初衷是抽取更加典型的文本,比如背景统一的书页。如果我们想要更加有效地使用Tesseract,需要先修改验证码图像,去除其中的背景噪音,只保留文本部分。为了更好地理解我们将要处理的验证码系统,图7.3中又给出了几个示例验证码。

图7.3

从图7.3中的例子可以看出,验证码文本一般都是黑色的,背景则会更加明亮,所以我们可以通过检查像素是否为黑色将文本分离出来,该处理过程又被称为阈值化 。通过Pillow 可以很容易地实现该处理过程。

>>> img.save('captcha_original.png')
>>> gray = img.convert('L')
>>> gray.save('captcha_gray.png')
>>> bw = gray.point(lambda x: 0 if x < 1 else 255, '1')
>>> bw.save('captcha_thresholded.png')

此时,只有阈值小于1的像素才会保留,也就是说,只有全黑的像素才会保留下来。这段代码片段保存了3张图像,分别是原始验证码图像、转换后的灰度图以及阈值化处理后的图像。图7.4所示为每个阶段保存的图像。

图7.4

最终,经过阈值化处理的图像中,文本更加清晰,此时我们就可以将其传给Tesseract进行处理了。

>>> pytesseract.image_to_string(bw)
'strange'

成功了!验证码中的文本已经被成功抽取出来了。在我测试的100张图片中,该方法正确解析了其中的84个验证码图像。由于示例文本总是小写的ASCII字符,因此我们可以将结果限定在这些字符中,从而进一步提高性能。

>>> import string
>>> word = pytesseract.image_to_string(bw)
>>> ascii_word = ''.join(c for c in word if c in
    string.letters).lower()

在对相同的100张图片的测试中,其识别率提高到了88%。下面是目前注册脚本的完整代码。

import cookielib
import urllib
import urllib2
import string
import pytesseract
REGISTER_URL = 'http://example.webscraping.com/user/register'

def register(first_name, last_name, email, password):
    cj = cookielib.CookieJar()
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
    html = opener.open(REGISTER_URL).read()
    form = parse_form(html)
    form['first_name'] = first_name
    form['last_name'] = last_name
    form['email'] = email
    form['password'] = form['password_two'] = password
    img = extract_image(html)
    captcha = ocr(img)
    form['recaptcha_response_field'] = captcha
    encoded_data = urllib.urlencode(form)
    request = urllib2.Request(REGISTER_URL, encoded_data)
    response = opener.open(request)
    success = '/user/register' not in response.geturl()
    return success

def ocr(img):
    gray = img.convert('L')
    bw = gray.point(lambda x: 0 if x < 1 else 255, '1')
    word = pytesseract.image_to_string(bw)
    ascii_word = ''.join(c for c in word if c in
        string.letters).lower()
    return ascii_word

register() 函数下载注册页面,抓取其中的表单,并在表单中设置新账号的名称、邮箱地址和密码。然后抽取验证码图像,传给OCR函数,并将OCR函数产生的结果添加到表单中。接下来提交表单数据,检查响应URL,确认注册是否成功。如果注册失败,响应URL仍然会是注册页,这既可能是因为验证码图像解析不正确,也可能是注册账号的邮箱地址已经存在。现在,只需要使用新账号信息调用register() 函数,就可以注册账号了。

>>> register(first_name, last_name, email, password)
True

7.2.1 进一步改善

要想进一步改善验证码OCR的性能,下面还有一些可能会使用到的方法:

实验不同阈值;

腐蚀阈值文本,突出字符形状;

调整图像大小(有时增大尺寸会起到作用);

根据验证码字体训练OCR工具;

限制结果为字典单词。

如果你对改善性能的实验感兴趣,可以使用该链接中的示例数据:https://bitbucket.org/wswp/code/src/tip/chapter07/samples/ 。不过,对于我们注册账号这一目的,目前88%的准确率已经足够了,这是因为即使是真实用户也会在输入验证码文本时出现错误。实际上,即使1%的准确率也是足够的,因为脚本可以运行多次直至成功,不过这样做对服务器不够友好,甚至可能会导致IP被封禁。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文