一、项目背景
随着互联网安全需求的日益提升,验证码(CAPTCHA)广泛用于验证人机身份。然而,人工识别效率低下,催生了基于机器学习和深度学习的自动识别方法。本文设计并实现了一个基于卷积神经网络(CNN)的验证码识别系统,能够高效处理扭曲字符、多干扰线的复杂图像。
二、验证码特征说明
类型:4位字符,包含大写英文字母与数字(如 "7GPA")
图像尺寸:160x60
干扰:旋转、扭曲、干扰线、噪点
三、环境依赖
pip install tensorflow keras numpy pillow matplotlib
四、验证码生成器(generate_data.py)
from captcha.image import ImageCaptcha
import random, string, os
from PIL import Image
characters = string.ascii_uppercase + string.digits
captcha = ImageCaptcha(width=160, height=60)
def generate(n=10000, path="captcha_data"):
os.makedirs(path, exist_ok=True)
for i in range(n):
text = ''.join(random.choices(characters, k=4))
img = captcha.generate_image(text)
img.save(os.path.join(path, f"{text}_{i}.png"))
generate()
五、数据预处理(data_loader.py)
import numpy as np
from PIL import Image
import os
import string
CHARS = string.ascii_uppercase + string.digits
CHAR2IDX = {c: i for i, c in enumerate(CHARS)}
IDX2CHAR = {i: c for c, i in CHAR2IDX.items()}
def one_hot(text):
vector = np.zeros((4, len(CHARS)))
for i, char in enumerate(text):
vector[i][CHAR2IDX[char]] = 1
return vector
def load_data(path, size=(160, 60), limit=None):
X, Y = [], []
files = os.listdir(path)[:limit]
for file in files:
label = file.split('_')[0]
img = Image.open(os.path.join(path, file)).convert("L")
img = img.resize(size)
X.append(np.array(img) / 255.0)
Y.append(one_hot(label))
X = np.expand_dims(np.array(X), -1)
Y = np.array(Y)
return X, Y
六、CNN模型定义(model.py)
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense
def build_model():
input_tensor = Input(shape=(60, 160, 1))
x = Conv2D(32, (3, 3), activation='relu')(input_tensor)
x = MaxPooling2D((2, 2))(x)
x = Conv2D(64, (3, 3), activation='relu')(x)
x = MaxPooling2D((2, 2))(x)
x = Flatten()(x)
x = Dense(128, activation='relu')(x)
outputs = [Dense(36, activation='softmax')(x) for _ in range(4)]
model = Model(inputs=input_tensor, outputs=outputs)
model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])
return model
七、模型训练(train.py)
from model import build_model
from data_loader import load_data
from sklearn.model_selection import train_test_split
import numpy as np
X, Y = load_data("captcha_data", limit=10000)
Y_split = [Y[:, i, :] for i in range(4)]
X_train, X_test, *Y_train_test = train_test_split(X, *Y_split, test_size=0.2)
model = build_model()
model.fit(X_train, Y_train_test[:-1],
validation_data=(X_test, Y_train_test[-1:]),
epochs=10, batch_size=64)
model.save("captcha_cnn.h5")
八、验证码识别预测(predict.py)
from tensorflow.keras.models import load_model
from PIL import Image
import numpy as np
from data_loader import CHARS
model = load_model("captcha_cnn.h5")
def predict(image_path):
img = Image.open(image_path).convert('L').resize((160, 60))
img = np.array(img) / 255.0
img = np.expand_dims(img, axis=(0, -1))
predictions = model.predict(img)
result = ''.join([CHARS[np.argmax(p)] for p in predictions])
return result
print(predict("captcha_data/7GPA_23.png"))