Python+Selenium+Pytesseract实现图片验证码识别
程序员文章站
2022-06-24 16:49:30
目录一、selenium截取验证码二、安装识别环境pytesseract+tesseract-ocr验证识别环境是否正常三、处理验证码图片图片处理识别一、selenium截取验证码import jso...
一、selenium截取验证码
import json from io import bytesio import time from test.testbefore.testdriver import driver from test.util.test_pytesseract import recognize from pil import image import allure import unittest ''' /处理验证码 ''' # 要截图的元素 element = driver.find_element_by_xpath('//*[@id="imgverifycode"]') # 坐标 x, y = element.location.values() # 宽高 h, w = element.size.values() # 把截图以二进制形式的数据返回 image_data = driver.get_screenshot_as_png() # 以新图片打开返回的数据 screenshot = image.open(bytesio(image_data)) # 对截图进行裁剪 result = screenshot.crop((x, y, x + w, y + h)) # 显示图片 # result.show() # 保存验证码图片 result.save('verifycode.png') # 调用recognize方法识别验证码 code = recognize('verifycode.png') # 输入验证码 driver.find_element_by_xpath('//*[@id="txtcode"]').send_keys(code) ''' 处理验证码/ '''
注意:driver是引用我自己写的文件,可以自己随便写一个。识别图片的代码单独放在util文件夹下面的,参考标题三的代码,需要时引用。以上代码定位元素都需要根据自己的项目定位元素修改。
二、安装识别环境pytesseract+tesseract-ocr
如果没有输出,又不确定你的pytesseract环境是否安装好,可以用一张没有干扰的图片识别看看能不能有输出结果,以下样例在我的环境中可以直接输出识别结果8fnp
验证识别环境是否正常
直接使用pytesseract识别图片
001.png
text = pytesseract.image_to_string('./001.png') print(text)
三、处理验证码图片
直接截图的验证码图片存在噪点或者干扰线等,直接使用pytesseract识别可能会没有输出结果,如果环境正常,但没有输出结果,那多半是因为图片没有处理好,识别不出来,可以多尝试一些处理图片的方式,以下代码处理我截图这种类似的图片效果比较好。
图片处理识别
对图片处理的过程:
图片处理过程中可以多用im.show()看看每一步处理后的图片是不是符合预期,如果效果不好调一下参数。另外在学习过程中发现有童鞋说识别不出来把图片使用cv2.resize()这个方法放大就能识别,可以参考python中图像的缩放 resize()函数的应用
实际截取的图片
处理后的图片
test_pytesseract.py
import pytesseract from fnmatch import fnmatch import cv2 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 < 2 or y > w - 2: img[x, y] = 255 # if x == 0 or x == h - 1 or x == h - 2: if x < 1 or x > h - 1: 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 = './' + img_name.split('.')[0] + '-binary.png' img_name = filedir + '/' + filename 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(image): filedir = './' # 验证码路径 for file in os.listdir(filedir): if fnmatch(file, image): 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) filename = './' + img_name.split('.')[0] + '-interferencepoint.png' # easy_code为保存路径 cv2.imwrite(filename, im) # 保存图片 text = pytesseract.image_to_string(im, lang="eng", config='--psm 6 digits') # config=digits只识别数字 return text ''' --psm 参数含义 0:定向脚本监测(osd) 1: 使用osd自动分页 2 :自动分页,但是不使用osd或ocr(optical character recognition,光学字符识别) 3 :全自动分页,但是没有使用osd(默认) 4 :假设可变大小的一个文本列。 5 :假设垂直对齐文本的单个统一块。 6 :假设一个统一的文本块。 7 :将图像视为单个文本行。 8 :将图像视为单个词。 9 :将图像视为圆中的单个词。 10 :将图像视为单个字符。 '''
到此这篇关于python+selenium+pytesseract实现图片验证码识别的文章就介绍到这了,更多相关python图片验证码识别内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!