使用深度学习破解图像验证码:详细教程与代码实现

验证码(CAPTCHA)是"Completely Automated Public Turing test to tell Computers and Humans Apart"的缩写,用于区分人类用户和自动化程序。本文将详细介绍如何使用深度学习技术来识别包含文字、英文和数字的图像验证码。

  1. 准备工作
    1.1 环境配置
    首先需要安装必要的Python库:

bash
pip install tensorflow keras opencv-python numpy matplotlib pillow
1.2 数据集准备
你可以使用以下方式获取验证码数据集:
网站地址www.tmocr.com或联系q1092685548
自己收集验证码图片并手动标注

使用生成器自动生成验证码(推荐初学者使用)

从公开数据集中下载

  1. 验证码生成器(可选)
    如果你没有现成的验证码数据集,可以使用以下代码生成:

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}')

posted @ 2025-05-11 20:02  tmcor  阅读(135)  评论(0)    收藏  举报