用 Keras 和深度学习实现验证码识别
在本篇文章中,我们将介绍如何利用 Keras(基于 TensorFlow 的高级深度学习框架)实现一个验证码识别系统。通过构建一个简单的卷积神经网络(CNN),我们可以有效地从验证码图像中识别出字符。CNN 在图像识别任务中非常有效,尤其适用于验证码识别这一任务。
- 环境准备
首先,确保你已经安装了以下必要的库:
pip install keras tensorflow opencv-python numpy matplotlib pillow
keras:高层次的深度学习API,基于TensorFlow。
tensorflow:深度学习框架。
opencv-python:用于图像处理。
numpy:用于数组处理和计算。
matplotlib:用于可视化。
pillow:用于图像加载和预处理。
- 数据集准备与图像预处理
我们假设你已经有一个包含验证码图像的文件夹。为了进行训练,我们需要对这些图像进行预处理,包括:灰度化、二值化、尺寸调整等操作。
(1) 图像预处理函数
import cv2
import numpy as np
import os
from tensorflow.keras.preprocessing.image import img_to_array
def preprocess_image(img_path, img_size=(64, 64)):
# 读取图像
img = cv2.imread(img_path)
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化处理
_, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# 调整图像大小
resized_img = cv2.resize(binary, img_size)
# 归一化处理
normalized_img = resized_img / 255.0
# 转换为数组
img_array = img_to_array(normalized_img)
return img_array
示例图像路径
img_path = 'captcha_images/test1.png'
processed_img = preprocess_image(img_path)
显示预处理后的图像
import matplotlib.pyplot as plt
plt.imshow(processed_img, cmap='gray')
plt.show()
在这个函数中,我们对图像进行了灰度化、二值化、尺寸调整和归一化。处理后,我们将图像转换为 NumPy 数组并准备好输入模型。
- 标签编码与数据准备
验证码标签通常由多个字符组成。在本示例中,我们假设验证码只包含数字和字母。我们将对标签进行 One-hot 编码,以便将其传递给神经网络模型。
(1) 标签编码
from tensorflow.keras.utils import to_categorical
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
假设验证码包括0-9和A-Z(总共36个字符)
def encode_labels(labels, num_classes=36):
label_encoder = LabelEncoder()
labels_encoded = label_encoder.fit_transform(labels)
labels_onehot = to_categorical(labels_encoded, num_classes=num_classes)
return labels_onehot, label_encoder
读取图像数据和标签
def load_data(image_dir, img_size=(64, 64)):
images = []
labels = []
for filename in os.listdir(image_dir):
if filename.endswith('.png'):
img_path = os.path.join(image_dir, filename)
img = preprocess_image(img_path, img_size)
images.append(img)
# 提取标签
label = filename.split('.')[0]
labels.append(label)
images = np.array(images)
labels = np.array(labels)
# 对标签进行One-hot编码
labels_onehot, label_encoder = encode_labels(labels)
return images, labels_onehot, label_encoder
加载数据集
image_dir = 'captcha_images'
X, y, label_encoder = load_data(image_dir)
这里,我们定义了一个 encode_labels 函数来进行标签的 One-hot 编码,并返回编码后的标签及标签编码器。接着,我们加载了图像数据并对每张图像的标签进行了编码。
- 构建卷积神经网络(CNN)
现在,我们来构建卷积神经网络(CNN)模型。CNN 是图像处理的基础,它通过卷积层自动提取图像中的特征,从而实现分类任务。
(1) 定义 CNN 模型
from tensorflow.keras import layers, models
def build_cnn_model(input_shape=(64, 64, 1), num_classes=36):
model = models.Sequential()
# 第一层卷积层
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=input_shape))
model.add(layers.MaxPooling2D((2, 2)))
# 第二层卷积层
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
# 扁平化层
model.add(layers.Flatten())
# 全连接层
model.add(layers.Dense(128, activation='relu'))
# 输出层
model.add(layers.Dense(num_classes, activation='softmax'))
# 编译模型
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
return model
构建CNN模型
model = build_cnn_model()
查看模型架构
model.summary()
在这个模型中,我们使用了两层卷积层,每个卷积层后跟一个最大池化层。最后,我们添加了一个全连接层和一个输出层(采用 Softmax 激活函数)来进行多类分类。模型使用 Adam 优化器,并采用 交叉熵损失函数。
- 训练模型
接下来,我们开始训练卷积神经网络。我们将数据集分成训练集和验证集,并使用训练集进行模型训练。
(1) 训练模型
拆分训练集和测试集
from sklearn.model_selection import train_test_split
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
训练模型
history = model.fit(X_train, y_train, epochs=10, batch_size=32, validation_data=(X_val, y_val))
绘制训练过程中的准确率变化
import matplotlib.pyplot as plt
plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label='val_accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')
plt.show()
这段代码会训练模型并绘制出训练过程中的准确率变化曲线。通过这些图表,我们可以观察到训练过程中模型表现的变化。
- 模型评估与测试
训练完成后,我们需要对模型的性能进行评估。我们可以在验证集上计算准确率,并评估模型的泛化能力。
(1) 评估模型
评估模型在测试集上的表现
test_loss, test_acc = model.evaluate(X_val, y_val)
print(f"验证集上的损失: {test_loss:.4f}")
print(f"验证集上的准确率: {test_acc:.4f}")
通过这段代码,我们可以获得模型在验证集上的损失和准确率,评估其表现如何。
- 对新图像进行预测
最后,我们可以利用训练好的模型对新图像进行预测。
(1) 进行预测
def predict_captcha(model, img_path, label_encoder):
img = preprocess_image(img_path)
# 扩展维度并进行预测
img = np.expand_dims(img, axis=0) # 增加批量维度
prediction = model.predict(img)
# 获取预测标签
predicted_label_encoded = np.argmax(prediction, axis=1)
predicted_label = label_encoder.inverse_transform(predicted_label_encoded)
return predicted_label[0]
预测新的验证码
new_image_path = 'captcha_images/test1.png'
predicted_label = predict_captcha(model, new_image_path, label_encoder)
print(f'预测的验证码是: {predicted_label}')
这段代码将新图像传入训练好的模型进行预测,并输出预测结果。
浙公网安备 33010602011771号