Python爬虫笔记【一】模拟用户访问之Tesseract-ocr验证码训练(5)

验证码处理之后就需要对处理的验证码进行识别训练,这里用Tesseract-ocr工具进行识jTessBoxeditor进行训练生成模板。

一,对图片进行处理

 

 

 用上一篇代码对图片进行降噪处理,得到较为清晰地图片。

 

 

这里需要你在需要登入的网站中提取大量的验证码图片,在获取图片时,查看网站的登入框是否在iframe标签中,已经图片是否有需要点击输入框才会出现,若是如此,可以用selenium中driver来跳转iframe标签,用点击事件来显示验证码,然后再获取src属性进行下载。

 

二,生成tif文件

 

在获取一定数量验证码后(储存在images中),打开jTessBoxeditor,Tools>Merge TIFF

 

选择之前保存图片的文件,shift将文件全选,注意文件显示的格式

 

 

 

之后选择生成fift路径以及设置名称此处名称要设置为这样的格式[lang].[fontname].exp[num].tif

其中lang为语言名称,fontname为字体名称,num为序号,可以随便定义。

 三,生成box文件

 这样遍将多个jpg文件合成一个tif文件(可能显示的是一个验证码),然后我们需要利用tif文件来生成box文件。

再打开jTessBoxEditor(如果之前有其他好点的模板就选择其他的,这样自动识别的会多一点,省之后的人力)。

 这一步之后就会在 tif 文件目录下生成一个box文件,在jTessBoxEditor中打开(如图 ↓ )

四,调整位置

如果模板较好的话会出现这样的文件(也许位置可能没有识别的这么准,那个就需要人工调节,记得保存,下面可以翻页)

 

 也有可能是这样

 

 如果是这样的话,你需要用文本方式打开box文件(六列分别对应,值,位置*4,页码值-1),我们需要创建的1~7页的那四行,随便找四行复制一下,然后改一下页码,没有框的几个验证码有了,然后再调整位置。(注意最后的一列为  页码数-1 )

 

 在调整完所有验证码后,在tif文件目录下建立一个新建名为下xxx.font_properties的文本文件(xxx与自定义语言名称相同)内容为 font 0 0 0 0 0
之后再去txt后缀

五,训练

这样 tif,box,font_properties文件都有了,就可以生成模板了

 

 训练完之后就在tif文件下生成了tessdata文件夹,里面便是训练完成模板mob.traineddata,将模板移动到Tesseract—ocr>tessdata目录下,这样便可以用Tesseract-ocr识别验证码

from PIL import Image
from pytesseract import *
from fnmatch import fnmatch
from queue import Queue
import matplotlib.pyplot as plt
import cv2
import time
import os


def clear_border(img,img_name):
  '''去除边框
  '''

  h, w = img.shape[:2]
  for y in range(0, w):
    for x in range(0, h):
      # if y ==0 or y == w -1 or y == w - 2:
      if y < 4 or y > w -4:
        img[x, y] = 255
      # if x == 0 or x == h - 1 or x == h - 2:
      if x < 4 or x > h - 4:
        img[x, y] = 255


  return img

def interference_line(img, img_name):
  '''
  干扰线降噪
  '''

  h, w = img.shape[:2]
  # !!!opencv矩阵点是反的
  # img[1,2] 1:图片的高度,2:图片的宽度
  for r in range(0,2):
    for y in range(1, w - 1):
      for x in range(1, h - 1):
        count = 0
        if img[x, y - 1] > 245:
          count = count + 1
        if img[x, y + 1] > 245:
          count = count + 1
        if img[x - 1, y] > 245:
          count = count + 1
        if img[x + 1, y] > 245:
          count = count + 1
        if count > 2:
          img[x, y] = 255

  return img

def interference_point(img,img_name, x = 0, y = 0):
    """点降噪
    9邻域框,以当前点为中心的田字框,黑点个数
    :param x:
    :param y:
    :return:
    """
    # todo 判断图片的长宽度下限
    cur_pixel = img[x,y]# 当前像素点的值
    height,width = img.shape[:2]

    for y in range(0, width - 1):
      for x in range(0, height - 1):
        if y == 0:  # 第一行
            if x == 0:  # 左上顶点,4邻域
                # 中心点旁边3个点
                sum = int(cur_pixel) \
                      + int(img[x, y + 1]) \
                      + int(img[x + 1, y]) \
                      + int(img[x + 1, y + 1])
                if sum <= 2 * 245:
                  img[x, y] = 0
            elif x == height - 1:  # 右上顶点
                sum = int(cur_pixel) \
                      + int(img[x, y + 1]) \
                      + int(img[x - 1, y]) \
                      + int(img[x - 1, y + 1])
                if sum <= 2 * 245:
                  img[x, y] = 0
            else:  # 最上非顶点,6邻域
                sum = int(img[x - 1, y]) \
                      + int(img[x - 1, y + 1]) \
                      + int(cur_pixel) \
                      + int(img[x, y + 1]) \
                      + int(img[x + 1, y]) \
                      + int(img[x + 1, y + 1])
                if sum <= 3 * 245:
                  img[x, y] = 0
        elif y == width - 1:  # 最下面一行
            if x == 0:  # 左下顶点
                # 中心点旁边3个点
                sum = int(cur_pixel) \
                      + int(img[x + 1, y]) \
                      + int(img[x + 1, y - 1]) \
                      + int(img[x, y - 1])
                if sum <= 2 * 245:
                  img[x, y] = 0
            elif x == height - 1:  # 右下顶点
                sum = int(cur_pixel) \
                      + int(img[x, y - 1]) \
                      + int(img[x - 1, y]) \
                      + int(img[x - 1, y - 1])

                if sum <= 2 * 245:
                  img[x, y] = 0
            else:  # 最下非顶点,6邻域
                sum = int(cur_pixel) \
                      + int(img[x - 1, y]) \
                      + int(img[x + 1, y]) \
                      + int(img[x, y - 1]) \
                      + int(img[x - 1, y - 1]) \
                      + int(img[x + 1, y - 1])
                if sum <= 3 * 245:
                  img[x, y] = 0
        else:  # y不在边界
            if x == 0:  # 左边非顶点
                sum = int(img[x, y - 1]) \
                      + int(cur_pixel) \
                      + int(img[x, y + 1]) \
                      + int(img[x + 1, y - 1]) \
                      + int(img[x + 1, y]) \
                      + int(img[x + 1, y + 1])

                if sum <= 3 * 245:
                  img[x, y] = 0
            elif x == height - 1:  # 右边非顶点
                sum = int(img[x, y - 1]) \
                      + int(cur_pixel) \
                      + int(img[x, y + 1]) \
                      + int(img[x - 1, y - 1]) \
                      + int(img[x - 1, y]) \
                      + int(img[x - 1, y + 1])

                if sum <= 3 * 245:
                  img[x, y] = 0
            else:  # 具备9领域条件的
                sum = int(img[x - 1, y - 1]) \
                      + int(img[x - 1, y]) \
                      + int(img[x - 1, y + 1]) \
                      + int(img[x, y - 1]) \
                      + int(cur_pixel) \
                      + int(img[x, y + 1]) \
                      + int(img[x + 1, y - 1]) \
                      + int(img[x + 1, y]) \
                      + int(img[x + 1, y + 1])
                if sum <= 4 * 245:
                  img[x, y] = 0
              
    return img

def _get_dynamic_binary_image(filedir,img_name):
  '''
  自适应阀值二值化
  '''
  filename =   './easy_code/' + img_name.split('.')[0] + '-binary.jpg'
  img_name = filedir + '/' + img_name
  im = cv2.imread(img_name)
  im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)

  th1 = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 1)

  return th1

def recognize():
  i = 0
  filedir = './images'  #验证码路jing
  for file in os.listdir(filedir):
    if fnmatch(file, '*.jpg'):
      img_name = file
      # 自适应阈值二值化
      im = _get_dynamic_binary_image(filedir,img_name)
      # 去除边框
      im = clear_border(im,img_name)
      # 对图片进行干扰线降噪
      im = interference_line(im,img_name)
      # 对图片进行点降噪
      im = interference_point(im,img_name)
      # easy_code为图片清理后保存路径
      filename =  './easy_code/' + img_name.split('.')[0] + '-interferencePoint.jpg'
      cv2.imwrite(filename,im)
      # 'mob'为模板
      str_img = pytesseract.image_to_string(im, lang='mob')
      code = str_img.encode("GBK","ignore").decode('GBK')
      if code.replace(' ','') == img_name.split('.')[0]:
        i = i + 1
      print(code)
      print('---' + str(i))
recognize()
View Code

 

from PIL import Image
from pytesseract import *
from fnmatch import fnmatch
from queue import Queue
import matplotlib.pyplot as plt
import cv2
import time
import os


def clear_border(img,img_name):
  '''去除边框
  '''

  h, w = img.shape[:2]
  for y in range(0, w):
    for x in range(0, h):
      # if y ==0 or y == w -1 or y == w - 2:
      if y < 4 or y > w -4:
        img[x, y] = 255
      # if x == 0 or x == h - 1 or x == h - 2:
      if x < 4 or x > h - 4:
        img[x, y] = 255


  return img

def interference_line(img, img_name):
  '''
  干扰线降噪
  '''

  h, w = img.shape[:2]
  # !!!opencv矩阵点是反的
  # img[1,2] 1:图片的高度,2:图片的宽度
  for r in range(0,2):
    for y in range(1, w - 1):
      for x in range(1, h - 1):
        count = 0
        if img[x, y - 1] > 245:
          count = count + 1
        if img[x, y + 1] > 245:
          count = count + 1
        if img[x - 1, y] > 245:
          count = count + 1
        if img[x + 1, y] > 245:
          count = count + 1
        if count > 2:
          img[x, y] = 255

  return img

def interference_point(img,img_name, x = 0, y = 0):
    """点降噪
    9邻域框,以当前点为中心的田字框,黑点个数
    :param x:
    :param y:
    :return:
    """
    # todo 判断图片的长宽度下限
    cur_pixel = img[x,y]# 当前像素点的值
    height,width = img.shape[:2]

    for y in range(0, width - 1):
      for x in range(0, height - 1):
        if y == 0:  # 第一行
            if x == 0:  # 左上顶点,4邻域
                # 中心点旁边3个点
                sum = int(cur_pixel) \
                      + int(img[x, y + 1]) \
                      + int(img[x + 1, y]) \
                      + int(img[x + 1, y + 1])
                if sum <= 2 * 245:
                  img[x, y] = 0
            elif x == height - 1:  # 右上顶点
                sum = int(cur_pixel) \
                      + int(img[x, y + 1]) \
                      + int(img[x - 1, y]) \
                      + int(img[x - 1, y + 1])
                if sum <= 2 * 245:
                  img[x, y] = 0
            else:  # 最上非顶点,6邻域
                sum = int(img[x - 1, y]) \
                      + int(img[x - 1, y + 1]) \
                      + int(cur_pixel) \
                      + int(img[x, y + 1]) \
                      + int(img[x + 1, y]) \
                      + int(img[x + 1, y + 1])
                if sum <= 3 * 245:
                  img[x, y] = 0
        elif y == width - 1:  # 最下面一行
            if x == 0:  # 左下顶点
                # 中心点旁边3个点
                sum = int(cur_pixel) \
                      + int(img[x + 1, y]) \
                      + int(img[x + 1, y - 1]) \
                      + int(img[x, y - 1])
                if sum <= 2 * 245:
                  img[x, y] = 0
            elif x == height - 1:  # 右下顶点
                sum = int(cur_pixel) \
                      + int(img[x, y - 1]) \
                      + int(img[x - 1, y]) \
                      + int(img[x - 1, y - 1])

                if sum <= 2 * 245:
                  img[x, y] = 0
            else:  # 最下非顶点,6邻域
                sum = int(cur_pixel) \
                      + int(img[x - 1, y]) \
                      + int(img[x + 1, y]) \
                      + int(img[x, y - 1]) \
                      + int(img[x - 1, y - 1]) \
                      + int(img[x + 1, y - 1])
                if sum <= 3 * 245:
                  img[x, y] = 0
        else:  # y不在边界
            if x == 0:  # 左边非顶点
                sum = int(img[x, y - 1]) \
                      + int(cur_pixel) \
                      + int(img[x, y + 1]) \
                      + int(img[x + 1, y - 1]) \
                      + int(img[x + 1, y]) \
                      + int(img[x + 1, y + 1])

                if sum <= 3 * 245:
                  img[x, y] = 0
            elif x == height - 1:  # 右边非顶点
                sum = int(img[x, y - 1]) \
                      + int(cur_pixel) \
                      + int(img[x, y + 1]) \
                      + int(img[x - 1, y - 1]) \
                      + int(img[x - 1, y]) \
                      + int(img[x - 1, y + 1])

                if sum <= 3 * 245:
                  img[x, y] = 0
            else:  # 具备9领域条件的
                sum = int(img[x - 1, y - 1]) \
                      + int(img[x - 1, y]) \
                      + int(img[x - 1, y + 1]) \
                      + int(img[x, y - 1]) \
                      + int(cur_pixel) \
                      + int(img[x, y + 1]) \
                      + int(img[x + 1, y - 1]) \
                      + int(img[x + 1, y]) \
                      + int(img[x + 1, y + 1])
                if sum <= 4 * 245:
                  img[x, y] = 0
              
    return img

def _get_dynamic_binary_image(filedir,img_name):
  '''
  自适应阀值二值化
  '''
  filename =   './easy_code/' + img_name.split('.')[0] + '-binary.jpg'
  img_name = filedir + '/' + img_name
  im = cv2.imread(img_name)
  im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)

  th1 = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 1)

  return th1

def recognize():
  i = 0
  filedir = './images'  #验证码路jing
  for file in os.listdir(filedir):
    if fnmatch(file, '*.jpg'):
      img_name = file
      # 自适应阈值二值化
      im = _get_dynamic_binary_image(filedir,img_name)
      # 去除边框
      im = clear_border(im,img_name)
      # 对图片进行干扰线降噪
      im = interference_line(im,img_name)
      # 对图片进行点降噪
      im = interference_point(im,img_name)
      # easy_code为图片清理后保存路径
      filename =  './easy_code/' + img_name.split('.')[0] + '-interferencePoint.jpg'
      cv2.imwrite(filename,im)
      # 'mob'为模板
      str_img = pytesseract.image_to_string(im, lang='mob')
      code = str_img.encode("GBK","ignore").decode('GBK')
      if code.replace('

查阅过的博客:

  《Python Tesseract识别验证码》:https://blog.csdn.net/u011457798/article/details/84063963

  《使用Tesseract破解验证码并训练字库的方法》:https://blog.csdn.net/makesibushuohua/article/details/52058310

转载于:https://www.cnblogs.com/dfy-blog/p/11563839.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值