# Python怎么通过Pillow识别动态验证码 ## 引言 在当今互联网应用中,验证码(CAPTCHA)被广泛用于防止自动化脚本攻击。动态验证码因其不断变化的特性(如扭曲文字、干扰线、背景噪点等)对传统OCR技术提出了更高挑战。本文将详细介绍如何利用Python的Pillow库结合其他技术实现对动态验证码的识别。 --- ## 一、环境准备 ### 1.1 安装必要库 ```bash pip install pillow numpy opencv-python scikit-image pytesseract
from PIL import Image def load_image(image_path): try: return Image.open(image_path) except Exception as e: print(f"加载失败: {e}") return None
操作类型 | 代码示例 | 作用说明 |
---|---|---|
灰度转换 | img.convert('L') | 减少颜色维度 |
二值化 | img.point(lambda x: 0 if x<128 else 255) | 增强字符对比度 |
降噪处理 | 见3.2节 | 去除干扰像素 |
import cv2 import numpy as np def remove_lines(image): # 使用霍夫线变换检测直线 gray = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2GRAY) edges = cv2.Canny(gray, 50, 150) lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=50, minLineLength=30, maxLineGap=10) # 绘制白色线段覆盖干扰线 if lines is not None: for line in lines: x1, y1, x2, y2 = line[0] cv2.line(gray, (x1,y1), (x2,y2), (255,255,255), 2) return Image.fromarray(gray)
from skimage import restoration def denoise_image(image): img_array = np.array(image) # 非局部均值降噪 denoised = restoration.denoise_nl_means(img_array, patch_size=5) return Image.fromarray((denoised*255).astype(np.uint8))
def segment_chars(image): # 垂直投影法分割字符 vertical_projection = np.sum(np.array(image) == 0, axis=0) char_positions = [] start = None for i, val in enumerate(vertical_projection): if val > 0 and start is None: start = i elif val == 0 and start is not None: char_positions.append((start, i)) start = None return [image.crop((start, 0, end, image.height)) for start, end in char_positions]
graph TD A[原始图片] --> B[灰度处理] B --> C[降噪处理] C --> D[干扰线消除] D --> E[二值化] E --> F[字符分割] F --> G[OCR识别]
def recognize_captcha(image_path): # 1. 图像加载 img = load_image(image_path) if not img: return None # 2. 预处理流程 img = img.convert('L') # 灰度化 img = denoise_image(img) # 降噪 img = remove_lines(img) # 去干扰线 img = img.point(lambda x: 0 if x<128 else 255) # 二值化 # 3. 字符分割 char_imgs = segment_chars(img) # 4. 使用Tesseract识别 import pytesseract result = "" for char_img in char_imgs: char_img.save("temp_char.png") # 临时保存单个字符 text = pytesseract.image_to_string(char_img, config='--psm 10 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') result += text.strip() return result
建议收集1000+样本进行模型训练:
from pytesseract import image_to_data def train_tesseract(samples_dir): for img_path in os.listdir(samples_dir): img = Image.open(f"{samples_dir}/{img_path}") # 生成box文件用于训练 image_to_data(img, output_type=pytesseract.Output.DICT)
当传统方法效果不佳时,可考虑CNN模型:
import tensorflow as tf model = tf.keras.Sequential([ tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(50, 150, 1)), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Flatten(), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dense(36, activation='softmax') # 26字母+10数字 ])
通过Pillow结合图像处理技术,我们可以有效应对大多数动态验证码。但需要注意: 1. 本方法仅适用于学习研究 2. 实际商业系统建议使用专业验证码服务 3. 尊重网站的使用条款
完整项目代码可参考:GitHub示例仓库 “`
注:本文示例代码需要根据实际验证码特征调整参数,动态验证码的识别本质上是一个对抗升级的过程,需要持续优化算法。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。