zoukankan      html  css  js  c++  java
  • 一次简单粗暴的验证码识别经历

      最近爬取一个网站时,遇到了验证码的情况。验证码形式是计算题,10以内的数字(可能有少量十以上),加减乘计算。

      开始懒得搞,第一批需要的数据量并不大,想着直接平台打码。

      原因是以前登录新浪微博的时候也是直接打码的,比较熟练,也简便。但打码成本比较高,后续需求量大,所以最好自己能识别。

      看了几篇识别验证码的文章,基本处理流程如下:

        1.去掉颜色;灰度处理,二值化等

        2.去掉干扰,降噪;噪点,线等的处理

        3.切割字符,单独识别

        4.训练字体

        5.自动识别

      我需要识别的验证码形式如下:

      

      经过反复试验,定了以下几个步骤:

        1.去除干扰,将图片中的干扰点线等删除

        2.识别图片,使用pytesseract识别图片

        3.计算结果,使用识别出来的字符数字计算结果

      以上是代码的流程,实际操作中还需要训练字体,这里留在最后说明。

      使用这张图片为例,简要介绍一下流程:

      以上几个步骤的基本操作思想:

        1.去噪。通常的思想是根据像素点的相邻关系等去除,我在识别的过程中发现,这里的图片像素值比较单一,

                      噪点的颜色比数字的颜色要浅。简单打印一下RGB值,可以发现除了(255,255,255)表示的白色以外,大致颜色值有以下几种:

          (140,140,140)

          (112,112,112)

             (117,117,117)

                       于是,我通过判断像素点的RGB值,把以上几种点用白色替换(即去掉该点),示例图片转换后得到图像如下

             

                       可以看到这个结果,基本上就可以拿去识别了。这也是为什么我称这次验证码识别为简单粗暴。

        2.识别。识别使用的是tesseract直接识别,没什么好讲的,贴几个链接自己看。

                 关于数据训练,也是直接照着教程做的,连文件名都没改,所幸过程中并未出错。

    from pytesseract import image_to_string
    im = Image.open("1_no_noise.png")
    str_img = image_to_string(im, lang='eng', config='-psm 6')
    print('识别为:%s' % str_img)

                       使用原装英文库识别结果如下:

    识别为:7x3:?
    

                  使用训练过的库识别:

    from pytesseract import image_to_string
    im = Image.open("1_no_noise.png")
    str_img = image_to_string(im, lang='fontyp', config='-psm 70')
    print('识别为:%s' % str_img)
    
    # 识别为:7x3=?

                      ※在使用过程中,尝试修改config的配置,可以帮助更准确地识别。

        3.计算结果。计算结果就是拿识别出来的字符串,简单拆分,分析操作符,做出对应计算,因为识别的时候没有切图,所以直接切割字符串。

                   在切割字符串之后的数字转换做了简单的矫正。

      整体代码如下:

    # encoding=utf-8
    __author__ = 'Masako'
    
    from PIL import Image
    from io import BytesIO
    from pytesseract import image_to_string
    
    NOISE_RGB_LIST = [117, 140, 112]    # 噪点像素值列表
    OPERATE_LIST = ['+', 'x', 'X',  '-', '']
    
    # 去除噪点 def del_point(img): pix = img.load() width = img.size[0] height = img.size[1] for x in range(width): for y in range(height): r, g, b = pix[x, y] # print(r, g, b) if r in NOISE_RGB_LIST: pix[x, y] = 255, 255, 255 return img # 数字识别 def data_ident(data_str): num = None if data_str == 'q': num = 9 elif data_str == 'z' or data_str == 'Z': num = 2 elif data_str == 'G': num = 6 else: try: num = int(data_str) except Exception as e: print("can't identify:" + data_str) return num # 计算结果 def deal_img_str(img_str): # str_list = img_str.split(' ') # print(str_list) calculate_result = None try: data_str = img_str[:img_str.rindex('=')] except Exception as e: print(img_str) return # print(data_str) for operate in OPERATE_LIST: if operate in data_str: # 判断操作符 data_list = data_str.split(operate) if len(data_list) == 2: # 正确分割时的处理 data_left = data_ident(data_list[0]) data_right = data_ident(data_list[1]) if data_left and data_right: if operate == '+': calculate_result = data_left + data_right elif operate == 'x' or operate == 'X': calculate_result = data_left * data_right else: calculate_result = data_left - data_right if calculate_result != None: break return calculate_result def img_to_captcha_code(img_content): image_data = BytesIO(img_content) im = Image.open(image_data) im = del_point(im) str_img = image_to_string(im, lang='fontyp', config='-psm 70') result = deal_img_str(str_img) return result if __name__ == "__main__": im = Image.open("a.jpg") im = del_point(im) im.save('a_no.jpg') str_img = image_to_string(im, lang='fontyp', config='-psm 70') print('识别为:%s' % str_img)

      参考文章链接:

        https://www.cnblogs.com/qqandfqr/p/7866650.html

        http://www.cnblogs.com/cnlian/p/5765871.html

  • 相关阅读:
    今天解决了一个很郁闷的问题!
    解决了安装golive后html文件图标显示错误的问题
    [转载]Asp.Net 2.0 发布问题
    使用 Visual Studio 2005 构建“WPFE”项目
    Ajax学习网址备忘录
    [原创首发]深圳博客问测系统正式发布啦!
    如何在用户控件里联动Dropdownlist
    [转载]在ASP.NET中值得注意的两个地方
    [转]Prototype 1.5 Ajax 使用教程
    1038 Recover the Smallest Number (30 分)(贪心)
  • 原文地址:https://www.cnblogs.com/masako/p/9319109.html
Copyright © 2011-2022 走看看