博主介绍:✌全网粉丝10W+,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业项目实战6年之久,选择我们就是选择放心、选择安心毕业✌
> 🍅想要获取完整文章或者源码,或者代做,拉到文章底部即可与我联系了。🍅

点击查看作者主页,了解更多项目!

🍅感兴趣的可以先收藏起来,点赞、关注不迷路,大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助同学们顺利毕业 。🍅

1、毕业设计:2026年计算机专业毕业设计选题汇总(建议收藏)✅

2、大数据毕业设计:2026年选题大全 深度学习 python语言 JAVA语言 hadoop和spark(建议收藏)✅

1、项目介绍

技术栈:
python验证码检测识别系统 CNN算法 卷积神经网络 Django框架 深度学习 毕业设计

该项目是一款聚焦验证码自动识别需求的毕业设计,以 Python 为开发核心,融合深度学习技术与 Web 开发框架,通过搭建 CNN 卷积神经网络模型实现高精度验证码识别,并依托 Django 构建网页端操作平台,让用户无需掌握技术细节,即可通过简单上传操作完成验证码识别,兼具技术创新性与实际应用价值,可辅助解决自动化场景中验证码人工识别效率低的痛点。

一、介绍
验证码识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法。并通过对数据集进行训练,最后得到一个识别精度较高的模型。并基于Django框架,开发网页端操作平台,实现用户上传一张图片识别其名称。

二、实现步骤
首先收集需要识别的种类数据集
然后基于TensorFlow搭建CNN卷积神经网络算法模型,并通过多轮迭代训练,最终得到一个精度较高的模型,并将其保存为h5格式的本地文件。
基于Django开发网页端可视化操作平台,HTML、CSS、BootStrap等技术搭建前端界面。Django作为后端逻辑处理框架。Ajax实现前后端的数据通信。

2、项目界面

(1)首页
在这里插入图片描述

(2)上传图片进行检测识别

在这里插入图片描述

(3)后台管理(识别记录管理)

在这里插入图片描述

在这里插入图片描述

3、项目说明

基于 CNN 与 Django 的 Python 验证码检测识别系统介绍
该项目是一款聚焦验证码自动识别需求的毕业设计,以 Python 为开发核心,融合深度学习技术与 Web 开发框架,通过搭建 CNN 卷积神经网络模型实现高精度验证码识别,并依托 Django 构建网页端操作平台,让用户无需掌握技术细节,即可通过简单上传操作完成验证码识别,兼具技术创新性与实际应用价值,可辅助解决自动化场景中验证码人工识别效率低的痛点。
从技术栈架构来看,各技术模块分工明确、协同支撑核心功能:Python 作为基础开发语言,凭借其在数据处理、模型开发领域的丰富库资源,为后续 CNN 模型搭建与 Django 后端开发提供统一技术底座;TensorFlow 深度学习框架是模型构建的核心,其高效的神经网络计算能力与成熟的训练工具链,能快速实现 CNN 模型的搭建、训练与优化,保障验证码识别精度;CNN 卷积神经网络算法则是识别能力的关键 —— 相较于传统识别算法,CNN 擅长提取图像局部特征(如验证码中的字符边缘、纹理),能有效应对验证码常见的干扰线、扭曲变形等问题,提升复杂场景下的识别准确率;Django 作为后端框架,负责整合模型调用逻辑、处理用户请求与数据存储,同时支持与前端技术无缝对接;前端通过 HTML 构建页面结构、CSS 与 BootStrap 实现界面美化,确保操作平台直观易用,Ajax 则实现前后端异步通信,避免用户上传识别时页面刷新,提升交互流畅度。
项目实现遵循 “数据 - 模型 - 平台” 的递进流程,步骤清晰可复现:第一步是数据集准备,需针对性收集目标验证码种类的数据集(如数字、字母混合验证码,或特定风格的图形验证码),并进行预处理(如尺寸统一、灰度化、去噪),为模型训练提供高质量数据基础;第二步是 CNN 模型开发与训练,基于 TensorFlow 搭建包含卷积层、池化层、全连接层的网络结构,通过多轮迭代调整超参数(如学习率、迭代次数、 batch size),以损失函数下降趋势与识别准确率为指标,优化模型性能,最终将训练完成的高精度模型保存为 h5 格式本地文件,便于后续网页平台调用;第三步是 Web 平台开发,以 Django 为核心构建后端服务,设计接口实现 “接收用户上传图片 - 调用本地 h5 模型进行识别 - 返回识别结果” 的业务逻辑,前端则通过 BootStrap 搭建响应式界面,确保在不同设备上均有良好显示效果,同时利用 Ajax 实现上传图片与获取结果的异步交互,提升用户体验。
项目界面设计聚焦 “易用性” 与 “功能性”,核心界面各有侧重:首页(对应界面 1)作为用户入口,采用简洁的导航式设计,清晰呈现 “验证码识别” 核心功能入口与平台说明,降低用户操作门槛;上传图片检测识别界面(对应界面 2)是核心功能区,布局分为 “图片上传区”“识别结果展示区”—— 用户点击上传按钮选择本地验证码图片,提交后系统快速调用模型处理,识别结果(如验证码字符)会实时显示在界面中,整个过程无需跳转页面,操作流畅;后台管理界面(识别记录管理)则为管理员提供数据管理功能,可按时间、用户等维度查看历史识别记录,便于统计平台使用情况与追溯识别结果,保障系统运维与数据可控。
综上,该项目作为毕业设计,成功整合了深度学习(CNN、TensorFlow)与 Web 开发(Django、前端技术)两大技术领域,既验证了技术应用能力,又开发出具备实际使用价值的验证码识别工具,可有效替代人工识别,提升自动化场景下的工作效率,是一款技术与功能兼备的优秀毕业设计作品。

4、核心代码


import tensorflow as tf

gpus = tf.config.list_physical_devices("GPU")

if gpus:
    tf.config.experimental.set_memory_growth(gpus[0], True)  #设置GPU显存用量按需使用
    tf.config.set_visible_devices([gpus[0]],"GPU")
导入数据
import matplotlib.pyplot as plt
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

import os,PIL,random,pathlib

# 设置随机种子尽可能使结果可以重现
import numpy as np
np.random.seed(1)

# 设置随机种子尽可能使结果可以重现
import tensorflow as tf
tf.random.set_seed(1)
data_dir = "./captcha"
data_dir = pathlib.Path(data_dir)

all_image_paths = list(data_dir.glob('*'))
all_image_paths = [str(path) for path in all_image_paths]

# 打乱数据
random.shuffle(all_image_paths)

# 获取数据标签
all_label_names = [path.split("\\")[1].split(".")[0] for path in all_image_paths]

image_count = len(all_image_paths)
print("图片总数为:",image_count)
图片总数为: 1070
3.数据可视化
plt.figure(figsize=(10,5))
plt.suptitle("验证码原始数据")

for i in range(20):
    plt.subplot(5,4,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    
    # 显示图片
    images = plt.imread(all_image_paths[i])
    plt.imshow(images)
    # 显示标签
    plt.xlabel(all_label_names[i])

plt.show()

标签数字化
number   = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
char_set       = number + alphabet
char_set_len   = len(char_set)
label_name_len = len(all_label_names[0])


# 将字符串数字化
def text2vec(text):
    vector = np.zeros([label_name_len, char_set_len])
    for i, c in enumerate(text):
        idx = char_set.index(c)
        vector[i][idx] = 1.0
    return vector


all_labels = [text2vec(i) for i in all_label_names]
vector = np.zeros([label_name_len, char_set_len])
for i,c in enumerate("6dmx7"):
    idx = char_set.index(c)
    vector[i][idx] = 1.0
    print(idx)
vector
    
    
6
13
22
33
7
array([[0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 1., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0.]])
预处理函数-构建一个tf.data.Dataset
def preprocess_image(image):
    image = tf.image.decode_jpeg(image, channels=1)
    image = tf.image.resize(image, [50, 200])
    return image/255.0

def load_and_preprocess_image(path):
    image = tf.io.read_file(path)
    return preprocess_image(image)
加载数据
AUTOTUNE = tf.data.experimental.AUTOTUNE

path_ds  = tf.data.Dataset.from_tensor_slices(all_image_paths)
image_ds = path_ds.map(load_and_preprocess_image, num_parallel_calls=AUTOTUNE)
label_ds = tf.data.Dataset.from_tensor_slices(all_labels)

image_label_ds = tf.data.Dataset.zip((image_ds, label_ds))
train_ds = image_label_ds.take(1000)  # 前1000个batch
val_ds   = image_label_ds.skip(1000)  # 跳过前1000,选取后面的
配置数据
BATCH_SIZE = 16

train_ds = train_ds.batch(BATCH_SIZE)
train_ds = train_ds.prefetch(buffer_size=AUTOTUNE)

val_ds = val_ds.batch(BATCH_SIZE)
val_ds = val_ds.prefetch(buffer_size=AUTOTUNE)
<PrefetchDataset element_spec=(TensorSpec(shape=(None, 50, 200, 1), dtype=tf.float32, name=None), TensorSpec(shape=(None, 5, 36), dtype=tf.float64, name=None))>
搭建网络模型
from tensorflow.keras import datasets, layers, models

model = models.Sequential([
    
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(50, 200, 1)),#卷积层1,卷积核3*3
    layers.MaxPooling2D((2, 2)),                   #池化层1,2*2采样
    layers.Conv2D(64, (3, 3), activation='relu'),  #卷积层2,卷积核3*3
    layers.MaxPooling2D((2, 2)),                   #池化层2,2*2采样
    
    layers.Flatten(),                              #Flatten层,连接卷积层与全连接层
    layers.Dense(1000, activation='relu'),         #全连接层,特征进一步提取
    
    layers.Dense(label_name_len * char_set_len),
    layers.Reshape([label_name_len, char_set_len]),
    layers.Softmax()                               #输出层,输出预期结果
])
# 打印网络结构
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 48, 198, 32)       320       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 24, 99, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 22, 97, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 11, 48, 64)        0         
_________________________________________________________________
flatten (Flatten)            (None, 33792)             0         
_________________________________________________________________
dense (Dense)                (None, 1000)              33793000  
_________________________________________________________________
dense_1 (Dense)              (None, 180)               180180    
_________________________________________________________________
reshape (Reshape)            (None, 5, 36)             0         
_________________________________________________________________
softmax (Softmax)            (None, 5, 36)             0         
=================================================================
Total params: 33,991,996
Trainable params: 33,991,996
Non-trainable params: 0
_________________________________________________________________
模型编译
model.compile(optimizer="adam",
              loss='categorical_crossentropy',
              metrics=['accuracy'])
模型训练
epochs = 20

history = model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=epochs
)
Epoch 1/20
63/63 [==============================] - 4s 21ms/step - loss: 3.2998 - accuracy: 0.0934 - val_loss: 2.2876 - val_accuracy: 0.2943
Epoch 2/20
63/63 [==============================] - 1s 9ms/step - loss: 1.7016 - accuracy: 0.5195 - val_loss: 1.2014 - val_accuracy: 0.6314
Epoch 3/20
63/63 [==============================] - 1s 10ms/step - loss: 0.5267 - accuracy: 0.8379 - val_loss: 0.9039 - val_accuracy: 0.7286
Epoch 4/20
63/63 [==============================] - 1s 10ms/step - loss: 0.1911 - accuracy: 0.9442 - val_loss: 0.8609 - val_accuracy: 0.7457
Epoch 5/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0916 - accuracy: 0.9714 - val_loss: 0.8937 - val_accuracy: 0.7886
Epoch 6/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0680 - accuracy: 0.9798 - val_loss: 0.5842 - val_accuracy: 0.8429
Epoch 7/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0443 - accuracy: 0.9900 - val_loss: 0.6235 - val_accuracy: 0.8200
Epoch 8/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0203 - accuracy: 0.9947 - val_loss: 0.7697 - val_accuracy: 0.8029
Epoch 9/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0131 - accuracy: 0.9975 - val_loss: 0.6660 - val_accuracy: 0.8314
Epoch 10/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0227 - accuracy: 0.9940 - val_loss: 0.6018 - val_accuracy: 0.8229
Epoch 11/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0093 - accuracy: 0.9985 - val_loss: 0.5714 - val_accuracy: 0.8429
Epoch 12/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0010 - accuracy: 1.0000 - val_loss: 0.5793 - val_accuracy: 0.8571
Epoch 13/20
63/63 [==============================] - 1s 10ms/step - loss: 2.6284e-04 - accuracy: 1.0000 - val_loss: 0.5920 - val_accuracy: 0.8571
Epoch 14/20
63/63 [==============================] - 1s 10ms/step - loss: 1.8502e-04 - accuracy: 1.0000 - val_loss: 0.6031 - val_accuracy: 0.8571
Epoch 15/20
63/63 [==============================] - 1s 10ms/step - loss: 1.4164e-04 - accuracy: 1.0000 - val_loss: 0.6120 - val_accuracy: 0.8571
Epoch 16/20
63/63 [==============================] - 1s 10ms/step - loss: 1.1334e-04 - accuracy: 1.0000 - val_loss: 0.6198 - val_accuracy: 0.8571
Epoch 17/20
63/63 [==============================] - 1s 10ms/step - loss: 9.4027e-05 - accuracy: 1.0000 - val_loss: 0.6269 - val_accuracy: 0.8571
Epoch 18/20
63/63 [==============================] - 1s 10ms/step - loss: 8.0025e-05 - accuracy: 1.0000 - val_loss: 0.6335 - val_accuracy: 0.8514
Epoch 19/20
63/63 [==============================] - 1s 9ms/step - loss: 6.9294e-05 - accuracy: 1.0000 - val_loss: 0.6396 - val_accuracy: 0.8486
Epoch 20/20
63/63 [==============================] - 1s 10ms/step - loss: 6.0775e-05 - accuracy: 1.0000 - val_loss: 0.6448 - val_accuracy: 0.8486
保存和加载模型
# 保存模型
model.save('model.h5')
# 加载模型
model = tf.keras.models.load_model('model.h5')
预测
number   = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
char_set       = number + alphabet
def vec2text(vec):
    """
    还原标签(向量->字符串)
    """
    text = []
    for i, c in enumerate(vec):
        text.append(char_set[c])
    return "".join(text)

def load_and_preprocess_image(path):
    image = tf.io.read_file(path)
    image = tf.image.decode_jpeg(image, channels=1)
    image = tf.image.resize(image, [50, 200])
    image = tf.cast(image, tf.float32)
    image = image/255.0  # normalize to [0,1] range
    return image

test_img = './captcha/24pew.png'
test_tensor = load_and_preprocess_image(test_img)
test_tensor = tf.expand_dims(test_tensor, axis=0)
pred = model.predict(test_tensor)
vec2text(np.argmax(pred, axis=2)[0])
'24pew'

5、源码获取方式

🍅由于篇幅限制,获取完整文章或源码、代做项目的,查看我的【用户名】、【专栏名称】、【顶部选题链接】就可以找到我啦🍅

感兴趣的可以先收藏起来,点赞、关注不迷路,下方查看👇🏻获取联系方式👇🏻

在这里插入图片描述

更多推荐