使用深度学习破解图像验证码:详细教程与代码实现
验证码(CAPTCHA)是"Completely Automated Public Turing test to tell Computers and Humans Apart"的缩写,用于区分人类用户和自动化程序。本文将详细介绍如何使用深度学习技术来识别包含文字、英文和数字的图像验证码。
- 准备工作
1.1 环境配置
首先需要安装必要的Python库:
bash
pip install tensorflow keras opencv-python numpy matplotlib pillow
1.2 数据集准备
你可以使用以下方式获取验证码数据集:
网站地址www.tmocr.com或联系q1092685548
自己收集验证码图片并手动标注
使用生成器自动生成验证码(推荐初学者使用)
从公开数据集中下载
- 验证码生成器(可选)
如果你没有现成的验证码数据集,可以使用以下代码生成:
python
from captcha.image import ImageCaptcha
import random
import string
def generate_captcha(text, save_path=None):
# 创建ImageCaptcha实例
image = ImageCaptcha(width=160, height=60)
# 生成验证码图像
data = image.generate(text)
if save_path:
image.write(text, save_path)
return data
生成随机字符(数字+大写字母)
def random_captcha_text(char_set=None, size=4):
if char_set is None:
char_set = string.digits + string.ascii_uppercase
return ''.join(random.choice(char_set) for _ in range(size))
生成1000个验证码样本
for i in range(1000):
text = random_captcha_text()
generate_captcha(text, f'captchas/{text}.png')
3. 数据预处理
3.1 加载和预处理数据
python
import os
import cv2
import numpy as np
from sklearn.model_selection import train_test_split
字符集定义
CHAR_SET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
CHAR_SET_LEN = len(CHAR_SET)
CAPTCHA_LEN = 4 # 验证码长度
将文本转换为one-hot编码
def text2vec(text):
vector = np.zeros(CAPTCHA_LEN * CHAR_SET_LEN)
for i, c in enumerate(text):
idx = CHAR_SET.index(c)
vector[i * CHAR_SET_LEN + idx] = 1
return vector
将one-hot编码转换回文本
def vec2text(vec):
text = []
for i in range(CAPTCHA_LEN):
char_vec = vec[iCHAR_SET_LEN:(i+1)CHAR_SET_LEN]
idx = np.argmax(char_vec)
text.append(CHAR_SET[idx])
return ''.join(text)
加载数据集
def load_data(data_dir='captchas'):
X = []
y = []
for filename in os.listdir(data_dir):
if filename.endswith('.png'):
# 读取图像并转为灰度图
img = cv2.imread(os.path.join(data_dir, filename), cv2.IMREAD_GRAYSCALE)
# 归一化
img = img / 255.0
# 调整大小(如果需要)
img = cv2.resize(img, (160, 60))
# 添加通道维度
img = np.expand_dims(img, axis=-1)
X.append(img)
# 从文件名获取标签
label = filename.split('.')[0]
y.append(text2vec(label))
return np.array(X), np.array(y)
X, y = load_data()
划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
4. 构建深度学习模型
我们将使用CNN+RNN的混合架构来识别验证码:
python
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, BatchNormalization
from tensorflow.keras.layers import Reshape, Dense, LSTM, Bidirectional, Add, Activation
def build_model(input_shape=(60, 160, 1), num_chars=CHAR_SET_LEN, captcha_len=CAPTCHA_LEN):
# 输入层
input_tensor = Input(shape=input_shape)
# 卷积层1
x = Conv2D(32, (3, 3), activation='relu', padding='same')(input_tensor)
x = MaxPooling2D((2, 2))(x)
# 卷积层2
x = Conv2D(64, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2))(x)
# 卷积层3
x = Conv2D(128, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2))(x)
# 将特征图展平为序列
x = Reshape((15, 20*128))(x) # 经过3次2x2池化,高度60→30→15→7,但我们取15
# 双向LSTM
x = Bidirectional(LSTM(128, return_sequences=True))(x)
x = Bidirectional(LSTM(128, return_sequences=True))(x)
# 输出层
x = Dense(num_chars * captcha_len)(x)
output = Activation('softmax')(x)
# 定义模型
model = Model(inputs=input_tensor, outputs=output)
return model
model = build_model()
model.summary()
5. 模型训练
python
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
编译模型
model.compile(loss='categorical_crossentropy',
optimizer=Adam(learning_rate=0.001),
metrics=['accuracy'])
定义回调
callbacks = [
EarlyStopping(patience=5, restore_best_weights=True),
ModelCheckpoint('best_model.h5', save_best_only=True)
]
训练模型
history = model.fit(
X_train, y_train,
validation_data=(X_test, y_test),
batch_size=64,
epochs=50,
callbacks=callbacks
)
6. 模型评估与预测
6.1 评估模型
python
import matplotlib.pyplot as plt
绘制训练曲线
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.legend()
plt.title('Loss Curve')
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'], label='Train Accuracy')
plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
plt.legend()
plt.title('Accuracy Curve')
plt.show()
评估模型
loss, accuracy = model.evaluate(X_test, y_test)
print(f'Test Loss: {loss:.4f}')
print(f'Test Accuracy: {accuracy:.4f}')
6.2 预测验证码
python
def predict_captcha(model, image_path):
# 读取并预处理图像
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
img = img / 255.0
img = cv2.resize(img, (160, 60))
img = np.expand_dims(img, axis=-1)
img = np.expand_dims(img, axis=0)
# 预测
pred = model.predict(img)
pred_text = vec2text(pred[0])
# 显示结果
plt.imshow(img[0, :, :, 0], cmap='gray')
plt.title(f'Predicted: {pred_text}')
plt.axis('off')
plt.show()
return pred_text
测试预测
test_image = 'captchas/AB12.png' # 替换为你的测试图片路径
predicted = predict_captcha(model, test_image)
print(f'Predicted CAPTCHA: {predicted}')

浙公网安备 33010602011771号