当前位置: 首页 > news >正文

206-基于深度学习的胸部CT肺癌诊断项目的设计与实现

基于深度学习的胸部 CT 肺癌诊断项目 — 设计与实现(含Web端)

一套从模型推理到网页交互的完整应用:上传胸部 CT 图像,返回四类诊断结果(肺腺癌/大细胞未分化癌/正常/鳞状细胞癌),并支持历史记录、批量预测与可视化扩展。

项目亮点

  • 端到端:模型加载、预测推理、Flask Web 界面、历史记录一体化。
  • 高可用回退:权重加载失败时,自动切换至 ImageNet 预训练 EfficientNetB3 作为备选,保证服务可运行。
  • 易扩展:已预留仪表盘/可视化挂点,便于后续接入 ECharts 等前端图表。
  • 跨平台路径处理:上传文件以相对 static 路径生成 URL,避免 Windows 路径导致的 404。

目录结构

code/app.py                        # Flask 应用后端(模型加载/预测/API/页面路由)requirements.txt              # 依赖列表efficientnetb3_notop.h5       #(可选)完整模型文件(若为整模型)efficientnetb3_base_best_weights.h5    #(可选)训练权重efficientnetb3_base_best_weights2.h5   #(可选)备用训练权重Data/                         # 数据集(train/valid/test)static/                       # 前端静态资源(CSS/JS/图片等)img/predict_test/           # 上传预测图片存放目录templates/                    # Jinja2 页面模板(index、dashboard、history 等)test_*.py                     # 若干测试脚本(模型/接口测试)README.md                     # 本文档

提示:static/img/predict_test/ 用于存放上传的预测图片,后端会生成 /static/... 形式的可访问 URL。


技术栈

  • 后端框架:Flask
  • 深度学习:TensorFlow 2.x、Keras(EfficientNetB3)
  • 图像处理:Pillow、OpenCV(可选)
  • 前端:Bootstrap、jQuery、ECharts(已包含依赖,可直接扩展)
  • 数据库存储:SQLite(用户与预测历史)

环境准备

1) Conda 环境(推荐)

conda create -n lungct python=3.8 -y
conda activate lungct

2) 安装依赖

pip install -r requirements.txt

如未包含全部依赖,可补充安装:

pip install tensorflow pillow numpy opencv-python flask

启动与使用

演示图片

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

启动服务

python app.py
# 输出类似:Running on http://127.0.0.1:5000

访问页面

  • 首页与单图预测:http://127.0.0.1:5000/
  • 批量预测:http://127.0.0.1:5000/batch_predict_page
  • 历史记录:http://127.0.0.1:5000/history
  • 仪表盘(可视化预留):http://127.0.0.1:5000/dashboard

模型与加载策略

项目默认使用 EfficientNetB3 作为特征提取骨干,输入大小为 (224\times224\times3)。

模型头(分类层)

# 伪代码展示(推理端结构需与训练端保持一致)
from tensorflow.keras.applications import EfficientNetB3
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D
from tensorflow.keras.models import Model as KerasModelheight, width = 224, 224
base_model = EfficientNetB3(weights=None, include_top=False, input_shape=(height, width, 3))
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
x = Dense(512, activation='relu')(x)
predictions = Dense(4, activation='softmax')(x)
model = KerasModel(inputs=base_model.input, outputs=predictions)

加载策略(多级回退)

  1. 尝试加载整模型 efficientnetb3_notop.h5(若它确为 model.save(...) 导出的整模型)。
  2. 若失败,构建相同结构后加载权重 efficientnetb3_base_best_weights.h5
  3. 若仍失败,尝试备用权重 efficientnetb3_base_best_weights2.h5
  4. 最终回退:加载 weights='imagenet' 的 EfficientNetB3 冻结骨干,添加同样分类头并编译,以保证服务可用。

可选增强:当层名一致但层数不完全匹配时,尝试按名加载并跳过不匹配层:

model = build_same_structure_model()
model.load_weights('efficientnetb3_base_best_weights.h5', by_name=True, skip_mismatch=True)

核心后端逻辑(节选)

路由概览

  • /:首页,上传单图预测
  • /test_predict:测试页面
  • /history:历史记录
  • /batch_predict_page:批量预测页面
  • /dashboard:仪表盘(可插入可视化图表)

单图预测接口

@app.route('/submit_and_predict', methods=['POST'])
def submit_and_predict():# 1) 保存上传图片到 static/img/predict_test/# 2) PIL 读取与预处理(RGB、resize 到 224x224)# 3) model.predict 得到 4 类概率,取最大值和标签# 4) 结果写入 SQLite(若用户已登录)# 5) 以 url_for('static', filename=...) 返回可访问图片 URLreturn jsonify(result)

返回示例:

{"upload_image": "/static/img/predict_test/000109 (4).png","predict": "鳞状细胞癌 Squamous cell carcinoma","confidence": 26.11,"all_predictions": {"肺腺癌 Adenocarcinoma": 23.92,"大细胞未分化癌 Large-cell undifferentiated carcinoma": 24.32,"正常 Normal": 25.64,"鳞状细胞癌 Squamous cell carcinoma": 26.11}
}

批量预测接口

@app.route('/batch_predict', methods=['POST'])
def batch_predict():# 多文件循环保存、读取、预测# 为每张图片生成 image_path 的静态 URL,前端即可直接展示return jsonify({'results': results, 'status': 'ok'})

代码详解与关键片段解释

1) 模型加载的多级回退机制

目的:保证在不同部署环境中仍能运行,即便权重/整模型不可用。

def load_model_safely():# 方案1:优先尝试加载整模型(若 h5 确实是整模型)base_model = load_model('efficientnetb3_notop.h5', compile=False)# 方案2:构建相同结构后加载权重(与训练端保持一致)model = create_model()model.load_weights('efficientnetb3_base_best_weights.h5')# 方案3:备用权重model.load_weights('efficientnetb3_base_best_weights2.h5')# 方案4:最终回退,使用 ImageNet 预训练骨干,冻结后添加分类头return create_working_model()

关键点:

  • 整模型与仅权重的区别:整模型包含结构+权重;仅权重需要先构建完全相同的结构。
  • 若层数量不匹配但层名基本一致,可尝试 by_name=True, skip_mismatch=True 按名加载。

2) 上传图片路径与可访问 URL 的生成

目的:避免 Windows 绝对路径导致浏览器 404,统一返回可访问的 /static/... URL。

test_file_path = os.path.join(current_dir, 'static', 'img', 'predict_test', filename)# 关键转换:把磁盘路径转为相对 static 的路径,再用 url_for 生成 URL
static_dir = os.path.join(current_dir, 'static')
rel_path = os.path.relpath(test_file_path, static_dir).replace('\\', '/')
image_url = url_for('static', filename=rel_path)

要点:

  • relpath 将绝对路径转相对 staticreplace('\\','/') 统一分隔符。
  • 返回 image_url 给前端直接 <img src="..."> 使用。

3) 预测输出与标签映射

predictions = model.predict(test_X)        # shape: (1, 4)
pred_labels = np.argmax(predictions, 1)[0] # 取最大概率的类别索引
confidence = float(np.max(predictions[0])) * 100
predict_class = class_name_dict[pred_labels]all_predictions = {class_name_dict[i]: round(float(predictions[0][i]) * 100, 2)for i in range(len(class_name_dict))
}

要点:

  • 置信度输出为百分比;all_predictions 便于前端做可视化或表格展示。

4) 历史记录写入(SQLite)

目的:记录用户最近的预测行为,便于回溯与数据分析。

# 若不存在则创建表
CREATE TABLE prediction_history(id INTEGER PRIMARY KEY AUTOINCREMENT,username CHAR(256),filename CHAR(256),prediction CHAR(256),confidence REAL,timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);# 插入记录(当用户已登录)
INSERT INTO prediction_history (username, filename, prediction, confidence)
VALUES (?, ?, ?, ?)

要点:

  • timestamp 默认当前时间,前端可按时间倒序展示最近 20 条。
  • 可扩展字段:如模型版本、推理耗时、图像来源等。

5) 批量预测流程

for file in files:# 保存 → 读取(PIL) → 预处理(resize 到 224x224) → model.predict# 生成 image_url → 追加到 results
return jsonify({'results': results, 'status': 'ok'})

要点:

  • 对每张图片独立生成 image_url,前端可预览每张预测结果。
  • 若单张失败,记录 status='error' 与错误信息,不影响其他图片处理。

前端可视化(预留)

本项目已包含 ECharts 等前端依赖,可在 templates/dashboard.html 中挂载图表:

<!-- 在 dashboard.html 中添加占位 div -->
<div id="prediction-distribution" style="height:360px;"></div><script>const chart = echarts.init(document.getElementById('prediction-distribution'));fetch('/get_system_stats').then(r => r.json()).then(stats => {const dist = stats.prediction_distribution || {};const data = Object.keys(dist).map(k => ({ name: k, value: dist[k] }));chart.setOption({title: { text: '预测结果分布' },tooltip: { trigger: 'item' },series: [{ type: 'pie', radius: '55%', data }]});});window.addEventListener('resize', () => chart.resize());// 可继续添加:今日预测趋势、用户增长、词云等
</script>

你也可以在 history.html 中用表格展示最近 20 条预测记录,或结合 ECharts Timeline 展现时间序列。


数据与预处理

  • 输入:胸部 CT 切片图像(PNG/JPG)
  • 预处理:
    • PIL 读取,确保 RGB 模式
    • resize 到 (224\times224)
    • 堆叠 batch 维度后进入模型 model.predict

如需归一化/标准化,请与训练阶段保持一致,并在推理前加入同样的预处理步骤。


常见问题(FAQ)

1. 权重无法加载,日志提示 Layer count mismatch 或 UTF-8 解码失败?

  • 确认 efficientnetb3_notop.h5 是否为整模型(model.save('xxx.h5')),若不是请重新导出整模型或仅提供权重并构建相同结构后再 load_weights
  • 若结构基本一致但不完全匹配,可尝试 by_name=True, skip_mismatch=True 按名加载跳过不匹配层。

2. Windows 上传图片后 404?

  • 已修复:返回的图片链接统一为 url_for('static', filename=...) 生成的 /static/... 相对 URL,避免 GET /f:/... 的绝对路径访问。

3. GPU/CPU 运行问题?

  • 代码已兼容 CPU 运行;若有 GPU,默认按需分配显存。必要时可在启动前设置 TF_CPP_MIN_LOG_LEVEL 来减少日志噪音。

4. 如何评估模型质量?

  • test_*.py 中可扩展:单图/批量评测、混淆矩阵、ROC 曲线等;前端仪表盘亦可接入可视化评估结果。

测试与示例

单图预测(cURL 示例)

curl -X POST \-F "file=@static/img/predict_test/your_ct.png" \http://127.0.0.1:5000/submit_and_predict

批量预测(cURL 示例)

curl -X POST \-F "files=@static/img/predict_test/a.png" \-F "files=@static/img/predict_test/b.png" \http://127.0.0.1:5000/batch_predict

部署建议

  • 生产环境建议使用 gunicorn/uwsgi + nginx 部署,关闭 Flask 调试模式。
  • 静态资源建议由 nginx 托管,后端仅提供 API。
  • 将权重/模型文件挂载到只读目录,并对上传目录设置最小可写权限。

维护规划(可选)

  • 加入模型版本管理(e.g., v1, v2 目录分版),热更新模型。
  • 引入统一的配置文件(YAML/JSON),管理端口、模型路径、阈值等。
  • 增加日志与监控:接口耗时、模型推理耗时、错误率监控等。

版权与鸣谢

  • 模型骨干:EfficientNetB3(ImageNet 预训练)
  • 前端框架与资源:Bootstrap、ECharts 等

如使用本项目进行科研或产品化,请遵守相关依赖的开源许可。


联系方式

码界筑梦坊各大平台同名

http://www.dtcms.com/a/449286.html

相关文章:

  • 二叉树进阶面试题:最小栈 栈的压入·弹出序列 二叉树层序遍历
  • 【大模型LLMs】LangGraph实战:引入网络搜索tool和Memory机制的对话Agent案例
  • 企业网站开发毕业报告网络营销的推广工具
  • 手机网站开发需要哪些人百度广告联盟怎么加入
  • 书生浦语实战营第六期 L1-G3000
  • 前端IM应用开发中的难点解析与总结
  • Web 服务器 UserDir(~username)功能解析:从原理到安全实践
  • 25新三年级上册数学混合运算应用题八大专项+三年级上数学混合运算练习/八大考点(复合问题/倍数问题)+完整电子版可下载打印
  • Linux基础IO(下):文件重定向和缓冲区
  • Flink 高级配置发行版剖析、Scala 版本、Table 依赖与 Hadoop 集成实战
  • 半成品公司 网站专业公司网站建设
  • 【数据结构】二叉搜索树 C++ 简单实现:增删查改全攻略
  • 深度学习(十七):全批量梯度下降 (BGD)、随机梯度下降 (SGD) 和小批量梯度下降 (MBGD)
  • 实验十九 GaussDB三权分立实验
  • C++微基础备战蓝桥杯string篇10.5
  • 基于脚手架微服务的视频点播系统-脚手架开发部分-brpc中间件介绍与使用及二次封装
  • 网站建设需求登记表 免费下载软件开发公司企业简介
  • 北京城乡建设网站网站建设都是用什么软件
  • C++分布式语音识别服务实践
  • 轻松理解智能体设计模式(1/6):提示链(Prompt Chaining)
  • ARM TrustZone技术如何守护你的隐私
  • 北京恒伟网站建设wordpress 新页面打开空白
  • 从 0 到 1 搭建 Python 语言 Web UI自动化测试学习系列 8--基础知识 4--常用函数 2
  • 在 Python 项目中构建可靠的 CI/CD 流水线:从设计到实战(面向开发与运维的实用指南)
  • Linux基本指令(中)
  • 郑州服装网站建设公司php做电商网站安全性如何
  • 响应式网站 翻译网站关键词排名如何提升
  • python爬虫(二) ---- JS动态渲染数据抓取
  • 国庆回来的css
  • 廊坊做网站的电话公司网站外包