OCR 技术实战教程:图形验证码识别

一、OCR 技术概述
1.1 什么是 OCR?

OCR(Optical Character Recognition)通过计算机视觉技术,将图像中的文字转换为可编辑文本。核心流程包括:

  • 图像采集:获取包含文字的图像
  • 预处理:灰度化、降噪、二值化等
  • 特征提取:字符轮廓检测、分割
  • 文本识别:字符分类与序列识别
1.2 适用场景
  • 图形验证码识别(如本文案例)
  • 文档数字化(扫描件转文本)
  • 车牌识别、票据处理等工业场景
二、环境安装
2.1、安装Tesseract

python的OCR库叫做Tesserocr,但是我们需要先安装Tesseract,这是Tesserocr的核心。

  1. 下载地址:digi.bib.uni-mannheim.de/tesseract/,建议安装最新版

  2. 安装时勾选Additional language data选项,这个选项会在我们安装Tesseract时自动下载各国语言。

  3. 配置环境变量:

    • 添加系统变量PATH:值为Tesseract的安装目录,例如D:\Tesseract-OCR
    • 新增系统变量TESSDATA_PREFIX:值为tessdata的目录,例如D:\Tesseract-OCRtessdata
2.2、安装tesserocr和其他库
bash 复制代码
# pip安装
pip install tesserocr
​
# 其他库,pillow和numpy用来处理图像,retrying用来重试操作,selenium用来模拟登陆
pip install pillow numpy retrying selenium

如果tesserocr安装时一直出错,可以网上下载whl文件,地址是github.com/simonflueck...,下载对应电脑python版本的即可,比如我电脑的是python3.13,那么就下载tesserocr-2.8.0-cp313-cp313-win_amd64.whl这个包。

复制代码
pip install tesserocr-2.8.0-cp313-cp313-win_amd64.whl
2.3、验证
python 复制代码
import tesserocr
from PIL import Image
image = Image.open('test.png')
print(tesserocr.image_to_text(image))

网上随便找张简单的验证码图片,能够正常识别即成功安装。

三、图像预处理
3.1、灰度化

将彩色图像转为单通道灰度图,减少计算量

arduino 复制代码
image = image.convert('L')  # 'L' 表示 8-bit 像素,黑白模式

此外,还有其他8种像素类型,以下是这9种类型的区别:

模式 通道数 含义 适用场景 示例代码
L 1 8-bit 灰度(0-255) 灰度化处理、降噪、二值化 image.convert('L')
RGB 3 24-bit 彩色(红、绿、蓝) 彩色验证码识别 image.convert('RGB')
RGBA 4 32-bit 彩色 + 透明度通道 含透明背景的图片处理 image.convert('RGBA')
CMYK 4 印刷四色(青、品红、黄、黑) 打印文档处理 image.convert('CMYK')
YCbCr 3 电视广播色域(亮度、色度) 视频图像处理 image.convert('YCbCr')
I 1 32-bit 整数灰度 高精度灰度计算 image.convert('I')
F 1 32-bit 浮点灰度 科学计算、图像分析 image.convert('F')
RGBX 4 RGB + 填充值(X 为填充字节) 兼容某些特殊格式 image.convert('RGBX')
L (带 Alpha) 2 灰度 + 8-bit Alpha 通道 半透明效果处理 image.convert('LA')

一般用L和RGB多一些,L模式适合边缘检测、二值化等;而RGB保留完整的色彩信息,适合复杂验证码。

3.2、降噪处理
  • 中值滤波
arduino 复制代码
# 去除椒盐噪声,size为奇数,例如3、5、7
image = image.filter(ImageFilter.MedianFilter(size=3))  
  • 高斯模糊
ini 复制代码
# 平滑高斯噪声,radius控制模糊程度
image = image.filter(ImageFilter.GaussianBlur(radius=1))  

如果需要处理简单验证码的干扰点,中值滤波是比较适合的,高斯模糊更是话语背景复杂但需要保留整体结构的图像。

3.3、二值化

通过阈值分割分离前景与背景:

ini 复制代码
# 转换为灰度图像
image = image.convert('L')  
# 设置阈值
threshold = 50  
# 转换为numpy数组
array=numpy.array(image)  
# 对数组进行筛选处理,将灰度大于阈值的像素点设为255,小于阈值的设为0,255是白色,0是黑色
array = numpy.where(array > threshold, 255, 0)  
# 将处理后的数组转换为图像
image = Image.fromarray(array.astype('uint8'))  
# 显示图像
image.show()  

OpenCV 提供了一个自适应阈值化函数,用于图像二值化处理。它可以根据图像局部区域的像素值动态计算阈值,比全局阈值更适合处理光照不均的图像。

四、Tesserocr用法

Tesserocr用法很简单,使用image_to_text方法即可将处理后的图像识别成文字

arduino 复制代码
tesserocr.image_to_text(image)
五、实战

以下是一个测试网站的验证码识别,链接是captcha7.scrape.center/,我们需要识别出验证码并模拟登陆成功,这是源码:

python 复制代码
import tesserocr
from PIL import Image,ImageFilter
import numpy
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
import time
from io import BytesIO
import re
from retrying import retry  # 重试装饰器
from selenium.webdriver.chrome.options import Options
import logging



# 配置日志
logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s : %(message)s',datefmt  = '%Y-%m-%d %A %H:%M:%S')

# 识别处理
def preposser(image):
    image = image.convert('L')  # 转换为灰度图像
    # 去噪,去噪后的图像会更清晰
    image = image.filter(ImageFilter.MedianFilter(size=3))  
    # # 显示处理后的验证码图片
    # image.show()  # 显示图像

    # 去完噪后发现图片已经很清晰,不需要再进行二值化处理了
    # array = numpy.array(image)  # 转换为numpy数组
    # array = numpy.where(array > 80, 255, 0)  # 对数组进行筛选处理,将灰度大于阈值的像素点设为255,小于阈值的设为0,255是白色,0是黑色
    # image = Image.fromarray(array.astype('uint8'))  # 将处理后的数组转换为图像
    return image


# 重试装饰器,最多重试10次,重试条件是登录失败返回FALSE,每次重试间隔1秒
@retry(stop_max_attempt_number=10, retry_on_result=lambda x: x is False, wait_fixed=1000)
def main():
    brower.get('https://captcha7.scrape.center/')
    # 获取用户名输入框
    username = brower.find_element(By.CSS_SELECTOR, '.username input[type="text"]')
    username.send_keys('admin')

    # 获取密码输入框
    password = brower.find_element(By.CSS_SELECTOR, '.password input[type="password"]')
    password.send_keys('admin')

    # 获取验证码输入框
    captcha_input = brower.find_element(By.CSS_SELECTOR, '.captcha input[type="text"]')
    # 获取验证码图片
    captcha_image = brower.find_element(By.CSS_SELECTOR, '#captcha')
    image= captcha_image.screenshot_as_png  # 获取验证码图片的二进制数据
    # 将二进制数据转换为图像,这里需要用到io模块的BytesIO函数,用来读写二进制数据,二进制数据是不能直接转为文件的
    image = Image.open(BytesIO(image))
    # 处理验证码图片
    image = preposser(image)

    # 验证码识别并输入输入框
    captcha=tesserocr.image_to_text(image)
    # 去掉空格和特殊字符
    captcha=re.sub('[^A-Za-z0-9]', '', captcha)  
    
    if not captcha or len(captcha) != 4:
        logging.error("验证码识别失败")
        return False
    logging.info(f"识别的验证码:{captcha}")
    captcha_input.send_keys(captcha)
    button=brower.find_element(By.CSS_SELECTOR, '.login')
    time.sleep(1)
    # 点击登录按钮
    button.click()  


    try:
        # 显式等待,判断登录是否成功
        wait=WebDriverWait(brower,5)
        # 这里只需要判断登录成功是否出现在HTML结构中,用xpath判断,.表示当前节点的文本内容
        condition=EC.presence_of_element_located((By.XPATH,'//h2[contains(.,"登录成功")]'))
        wait.until(condition)
        logging.info("登录成功")
        time.sleep(3)
        return True
    except Exception as e:
        logging.error("登录失败")
        return False
    

if __name__ == '__main__': 
    # 配置忽略 SSL 错误
    chrome_options = Options()
    chrome_options.add_argument('--ignore-certificate-errors')
    chrome_options.add_argument('--ignore-ssl-errors')

    # 根据自己电脑的环境来定义,如果不是虚拟环境,可以不需要指定
    service = Service(r'....\myenv\Scripts\chromedriver.exe')
    brower = webdriver.Chrome(service=service)
    try:
        main()
    except Exception as e:
        logging.error(f"程序运行出错:{e}")
    finally:
        # 确保浏览器在异常情况下也能关闭
        brower.quit()  

单纯的靠Tesseract和numpy,整体的识别率其实是不高的,因此我们更多的是配合OpenCV或者其他方法来进行预处理。

相关推荐
小洛~·~16 分钟前
《深度学习入门:基于Python的理论与实现》第三章神经网络
python·深度学习·神经网络
Jackilina_Stone3 小时前
【模型量化】GPTQ 与 AutoGPTQ
人工智能·python·gptq
橙色小博4 小时前
PyTorch中的各种损失函数的详细解析与通俗理解!
人工智能·pytorch·python·深度学习·神经网络·机器学习
小森77675 小时前
(三)机器学习---线性回归及其Python实现
人工智能·python·算法·机器学习·回归·线性回归
-XWB-5 小时前
【LLM】使用MySQL MCP Server让大模型轻松操作本地数据库
人工智能·python·自然语言处理
PacosonSWJTU6 小时前
python基础-13-处理excel电子表格
开发语言·python·excel
小军要奋进7 小时前
httpx模块的使用
笔记·爬虫·python·学习·httpx
Johnny_Cheung7 小时前
字符串、列表、元组、字典
开发语言·python
独行soc7 小时前
2025年渗透测试面试题总结- 某四字大厂面试复盘扩展 一面(题目+回答)
java·数据库·python·安全·面试·职场和发展·汽车
梦回阑珊7 小时前
《QT从基础到进阶·七十四》Qt+C++开发一个python编译器,能够编写,运行python程序改进版
c++·python·qt