PHP前端开发

python如何识别验证码

百变鹏仔 3个月前 (01-23) #Python
文章标签 验证码

在python爬虫爬取某些网站的验证码的时候可能会遇到验证码识别的问题,现在的验证码大多分为四类:1、计算验证码2、滑块验证码3、识图验证码4、语音验证码

这里主要是识别验证码,识别的是简单的验证码,要想让识别率更高,识别的更加准确就需要花很多的精力去训练自己的字体库。

识别验证码通常是这几个步骤:

1、灰度处理

立即学习“Python免费学习笔记(深入)”;

2、二值化

3、去除边框(如果有的话)

4、降噪

5、切割字符或者倾斜度矫正

6、训练字体库

7、识别

这6个步骤中前三个步骤是基本的,4或者5可根据实际情况选择是否需要,并不一定切割验证码,识别率就会上升很多有时候还会下降

用到的几个主要的python库: Pillow(python图像处理库)、OpenCV(高级图像处理库)、pytesseract(识别库)

下面案例使用方法:

1、将要识别的验证码图片放入与脚本同级的img文件夹中,创建out_img文件夹

2、python3 filename

3、二值化、降噪等各个阶段的图片将存储在out_img文件夹中,最终识别结果会打印到屏幕上

完整的二维码识别代码:

from PIL import Imagefrom pytesseract import *from fnmatch import fnmatchfrom queue import Queueimport matplotlib.pyplot as pltimport cv2import timeimport osdef clear_border(img,img_name):  '''去除边框  '''  filename = './out_img/' + img_name.split('.')[0] + '-clearBorder.jpg'  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  w -4:        img[x, y] = 255      # if x == 0 or x == h - 1 or x == h - 2:      if x  h - 4:        img[x, y] = 255  cv2.imwrite(filename,img)  return imgdef interference_line(img, img_name):  '''  干扰线降噪  '''  filename =  './out_img/' + img_name.split('.')[0] + '-interferenceline.jpg'  h, w = img.shape[:2]  # !!!opencv矩阵点是反的  # img[1,2] 1:图片的高度,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  cv2.imwrite(filename,img)  return imgdef interference_point(img,img_name, x = 0, y = 0):    """点降噪    9邻域框,以当前点为中心的田字框,黑点个数    :param x:    :param y:    :return:    """    filename =  './out_img/' + img_name.split('.')[0] + '-interferencePoint.jpg'    # 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  minL + minL * 0.7):        maxL_index = im_position[0].index(maxL)        minL_index = im_position[0].index(minL)        # 设置字符的宽度        im_position[0][maxL_index] = maxL // 2        im_position[0].insert(maxL_index + 1, maxL // 2)        # 设置字符X轴[起始,终点]位置        im_position[1][maxL_index][1] = im_position[1][maxL_index][0] + maxL // 2        im_position[1].insert(maxL_index + 1, [im_position[1][maxL_index][1] + 1, im_position[1][maxL_index][1] + 1 + maxL // 2])        # 设置字符的Y轴[起始,终点]位置        im_position[2].insert(maxL_index + 1, im_position[2][maxL_index])      # 切割字符,要想切得好就得配置参数,通常 1 or 2 就可以      cutting_img(im,im_position,img_name,1,1)      # 识别验证码      cutting_img_num = 0      for file in os.listdir('./out_img'):        str_img = ''        if fnmatch(file, '%s-cutting-*.jpg' % img_name.split('.')[0]):          cutting_img_num += 1      for i in range(cutting_img_num):        try:          file = './out_img/%s-cutting-%s.jpg' % (img_name.split('.')[0], i)          # 识别验证码          str_img = str_img + image_to_string(Image.open(file),lang = 'eng', config='-psm 10') #单个字符是10,一行文本是7        except Exception as err:          pass      print('切图:%s' % cutting_img_num)      print('识别为:%s' % str_img)if __name__ == '__main__':  main()