位置: 文档库 > Python > python入门级识别验证码

python入门级识别验证码

CrystalDragon 上传于 2023-01-18 13:25

《Python入门级识别验证码》

验证码(CAPTCHA)作为互联网安全中防止自动化程序恶意操作的常见手段,其识别技术一直是计算机视觉和人工智能领域的热门话题。对于Python初学者而言,通过实现简单的验证码识别项目,既能巩固图像处理基础知识,又能了解机器学习的基本流程。本文将从验证码的分类、图像预处理、特征提取到模型训练,逐步讲解如何使用Python完成入门级验证码识别任务。

一、验证码的分类与特点

验证码根据表现形式可分为数字字母混合型、汉字型、计算题型、滑动拼图型等。对于初学者,建议从结构简单的数字字母混合型验证码入手,这类验证码通常具有以下特点:

1. 字符数量固定(如4-6位)

2. 字符间存在间隔或干扰线

3. 背景可能包含噪点或扭曲变形

4. 字体颜色与背景形成对比

示例验证码图片(需自行准备):包含4位数字字母的PNG图像,字符为黑色,背景为白色,带有轻微噪点。

二、环境准备与依赖库安装

在开始前,需安装以下Python库:


pip install opencv-python numpy pillow scikit-learn tensorflow keras

各库作用:

- OpenCV:图像处理与预处理

- NumPy:数值计算

- Pillow(PIL):图像加载与保存

- scikit-learn:机器学习工具

- TensorFlow/Keras:深度学习模型构建

三、验证码图像预处理

预处理是验证码识别的关键步骤,目的是消除噪声、增强字符特征。以下是典型预处理流程:

1. 图像二值化

将彩色图像转换为黑白图像,突出字符轮廓:


import cv2
import numpy as np

def binary_image(img_path):
    img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
    _, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
    return binary

2. 降噪处理

使用高斯模糊或中值滤波消除噪点:


def denoise_image(img):
    denoised = cv2.medianBlur(img, 3)  # 3x3中值滤波
    return denoised

3. 字符分割

通过投影法或连通区域分析分割单个字符:


def split_characters(img):
    contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    characters = []
    for cnt in contours:
        x, y, w, h = cv2.boundingRect(cnt)
        if w > 10 and h > 20:  # 过滤小区域
            char = img[y:y+h, x:x+w]
            characters.append(char)
    return sorted(characters, key=lambda x: x.shape[1])  # 按宽度排序

四、特征提取与数据准备

1. 手动特征提取(传统方法)

提取字符的HOG特征或像素统计特征:


from skimage.feature import hog

def extract_hog_features(img):
    features = hog(img, orientations=8, pixels_per_cell=(16, 16),
                   cells_per_block=(1, 1), visualize=False)
    return features

2. 数据集准备

需收集大量验证码样本,并按字符分类存储。例如:


import os
from PIL import Image

def prepare_dataset(dataset_dir):
    X = []
    y = []
    for char_dir in os.listdir(dataset_dir):
        char_path = os.path.join(dataset_dir, char_dir)
        if os.path.isdir(char_path):
            for img_file in os.listdir(char_path):
                img_path = os.path.join(char_path, img_file)
                img = Image.open(img_path).convert('L')  # 转为灰度
                img_array = np.array(img).flatten()  # 展平为向量
                X.append(img_array)
                y.append(char_dir)  # 假设目录名为字符标签
    return np.array(X), np.array(y)

五、传统机器学习方法

1. SVM分类器

使用支持向量机进行字符分类:


from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder

X, y = prepare_dataset('captcha_dataset')
le = LabelEncoder()
y_encoded = le.fit_transform(y)
X_train, X_test, y_train, y_test = train_test_split(X, y_encoded, test_size=0.2)

svm = SVC(kernel='rbf', C=1.0, gamma='scale')
svm.fit(X_train, y_train)
print("Accuracy:", svm.score(X_test, y_test))

2. 随机森林

替代方案:


from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_estimators=100)
rf.fit(X_train, y_train)
print("RF Accuracy:", rf.score(X_test, y_test))

六、深度学习方法(CNN)

卷积神经网络(CNN)在图像分类中表现优异,适合验证码识别。

1. 数据预处理调整

将字符图像调整为统一大小(如32x32):


def resize_image(img, size=(32, 32)):
    return cv2.resize(img, size)

2. CNN模型构建


from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense

def build_cnn_model(num_classes):
    model = Sequential([
        Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 1)),
        MaxPooling2D((2, 2)),
        Conv2D(64, (3, 3), activation='relu'),
        MaxPooling2D((2, 2)),
        Flatten(),
        Dense(128, activation='relu'),
        Dense(num_classes, activation='softmax')
    ])
    model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])
    return model

3. 训练与评估


import numpy as np
from sklearn.preprocessing import LabelEncoder

# 假设已加载数据X_images(形状为(n_samples, 32, 32)),y_labels
X_images = np.array([resize_image(img) for img in X_images])
X_images = X_images.reshape(-1, 32, 32, 1)  # 添加通道维度

le = LabelEncoder()
y_encoded = le.fit_transform(y_labels)
num_classes = len(le.classes_)

model = build_cnn_model(num_classes)
model.fit(X_images, y_encoded, epochs=10, batch_size=32)

# 评估
test_loss, test_acc = model.evaluate(X_test_images, y_test_encoded)
print(f"Test Accuracy: {test_acc:.4f}")

七、完整验证码识别流程

结合预处理、分割、识别步骤的完整代码:


import cv2
import numpy as np
from tensorflow.keras.models import load_model

def recognize_captcha(img_path, model_path):
    # 1. 预处理
    img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
    _, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
    denoised = cv2.medianBlur(binary, 3)
    
    # 2. 字符分割
    contours, _ = cv2.findContours(denoised, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    chars = []
    for cnt in contours:
        x, y, w, h = cv2.boundingRect(cnt)
        if w > 10 and h > 20:
            char = denoised[y:y+h, x:x+w]
            char_resized = cv2.resize(char, (32, 32))
            chars.append(char_resized)
    
    # 3. 加载模型并预测
    model = load_model(model_path)
    chars_sorted = sorted(chars, key=lambda x: x.shape[1])  # 假设按宽度排序
    predictions = []
    for char in chars_sorted:
        char_input = char.reshape(1, 32, 32, 1)
        pred = model.predict(char_input)
        pred_class = np.argmax(pred)
        # 假设模型输出对应字符的顺序(需根据实际训练调整)
        predictions.append(str(pred_class))  # 实际应为字符映射
    
    return ''.join(predictions[:4])  # 假设验证码为4位

八、优化方向与注意事项

1. 数据增强:通过旋转、缩放、添加噪声增加样本多样性

2. 模型优化:调整CNN结构、使用预训练模型(如MobileNet)

3. 端到端识别:直接训练包含字符定位和分类的模型(如YOLO+CNN)

4. 反爬虫对策:实际网站验证码可能包含更复杂的干扰(如扭曲、重叠字符)

九、总结与扩展

本文通过Python实现了从验证码预处理到字符识别的完整流程。初学者可在此基础上:

1. 尝试更复杂的验证码类型(如汉字、计算题)

2. 结合Tesseract OCR等开源工具

3. 部署为Web服务(使用Flask/Django)

4. 研究对抗样本对验证码识别的影响

关键词:Python验证码识别OpenCV图像处理机器学习分类卷积神经网络特征提取、数据预处理、SVM模型深度学习入门

简介:本文详细介绍了使用Python实现入门级验证码识别的完整流程,涵盖图像预处理、字符分割、传统机器学习(SVM/随机森林)和深度学习(CNN)方法,适合Python初学者学习计算机视觉与机器学习基础。