基于 ResNet34 的混凝土坍落度智能预测系统(前后端分离架构)

项目地址:https://github.com/crazyjack44/Concrete_Slump_Test_System

一、项目背景

在混凝土生产和施工过程中,坍落度(Slump)是衡量混凝土工作性最关键的指标之一。传统坍落度测试依赖人工现场操作,耗时耗力,且结果受人为因素影响较大。随着深度学习和工业视觉技术的发展,利用摄像头实时采集混凝土图像,通过AI模型自动分类坍落度状态,已成为一种高效、客观的替代方案。

本项目正是基于这一思路,使用 ResNet34 卷积神经网络对混凝土坍落度进行三分类预测(合适 / 偏干 / 偏稀),并构建了完整的 Web 应用系统,实现从图像采集、AI推理、数据标注到模型微调的全流程闭环。

二、系统功能一览

功能模块 说明
实时视频采集 支持本地USB摄像头和海康威视RTSP工业相机
AI智能预测 ResNet34三分类,GPU加速推理,毫秒级响应
数据采集管理 图像自动保存,元数据编码入文件名,支持人工标注
模型在线微调 一键启动训练,自动组织数据集,训练进度实时反馈
Web界面 暗色工业风UI,前后端分离,浏览器即开即用

[占位符:功能流程图]

三、技术架构

系统采用 前后端分离 的 B/S 架构,后端提供 RESTful API,前端通过 AJAX 调用接口,职责清晰、便于维护和扩展。

┌─────────────────────────────────────────────────┐
│                   浏览器前端                      │
│          (HTML + CSS + 原生JavaScript)           │
└──────────────┬──────────────────┬────────────────┘
               │  RESTful API     │
               ▼                  ▼
┌──────────────────────┐  ┌───────────────────────┐
│   Flask API 层       │  │   ML 模块层            │
│  ┌────────────────┐  │  │  ┌─────────────────┐  │
│  │ /api/camera/*  │  │  │  │ classifier.py   │  │
│  │ /api/predict/* │  │  │  │ (单例推理引擎)   │  │
│  │ /api/train/*   │  │  │  ├─────────────────┤  │
│  └────────────────┘  │  │  │ trainer.py      │  │
│                      │  │  │ (微调训练器)     │  │
└──────────────────────┘  │  ├─────────────────┤  │
                          │  │ resnet34.py     │  │
                          │  │ (模型定义)       │  │
                          │  └─────────────────┘  │
                          └───────────────────────┘

3.1 后端架构

后端基于 Flask 框架,按功能拆分为 4 个 Blueprint:

Blueprint URL前缀 职责
main / 页面路由,渲染前端HTML
camera /api/camera 摄像头开关、帧获取、RTSP配置
predict /api/predict AI预测、图片上传预测、结果保存
train /api/train 数据组织、训练启动、进度查询

核心设计决策:

  • UI与API完全分离:前端不依赖后端模板渲染逻辑,所有数据交互通过 JSON API 完成,未来可轻松替换为 Vue/React 前端或对接移动端
  • ML模块独立:模型定义、推理、训练各自为独立模块,不依赖 Flask,可单独作为 Python 包使用
  • 线程安全:相机状态、模型单例、训练任务均使用 threading.Lock 保护,避免并发问题
  • 优雅降级:缺少 PyTorch 时 Flask 仍能正常启动,API 返回友好错误信息而非崩溃

3.2 前端设计

前端采用纯 HTML/CSS/JS 实现,无需 Node.js 构建流程,一个浏览器即可运行。

设计要点:

  • 全屏Flex布局html,body 固定100%高度不滚动,三列面板各自 overflow-y:auto 独立滚动,避免页面级滚动导致操作区被遮挡
  • 暗色工业风:深蓝黑底色配亮蓝强调色,贴合工业视觉系统的使用场景
  • 实时反馈:视频帧 100ms 轮询、训练进度 1.5s 轮询、Toast 通知,操作状态一目了然
  • 响应式适配:三列 → 双列 → 单列自动响应

[占位符:前端界面三列布局截图]

3.3 ML 模块设计

这是本项目的技术核心,也是相比原版改进最大的部分。

模型单例加载
class ModelManager:
    """模型单例管理器,线程安全"""
    _instance = None
    _lock = threading.Lock()

    def __new__(cls):
        with cls._lock:
            if cls._instance is None:
                cls._instance = super().__new__(cls)
                cls._instance._model = None
        return cls._instance

    def load_model(self):
        if self._model is not None:
            return self._model  # 已加载则直接返回
        self._device = torch.device(...)
        self._model = resnet34(num_classes=3).to(self._device)
        self._model.load_state_dict(torch.load(...))
        self._model.eval()
        return self._model

为什么需要单例? 原版代码每次调用 predict_() 都会重新创建模型并加载权重文件,这意味着:

  • 每次推理都要从磁盘读取 85MB 的 .pth 文件
  • 每次都要将模型参数拷贝到 GPU 显存
  • 推理延迟从亚毫秒级暴涨到秒级

单例模式下,模型只加载一次,后续推理直接复用 GPU 上的模型实例,推理耗时回归正常水平。

训练模块修复

原版训练代码存在一个严重 bug —— 优化器在每个 batch 中重新创建

# 原版代码(有bug)
for batch, (x, y) in enumerate(train_dataloader):
    optimizer = optim.Adam(model.parameters(), lr=0.001)  # 每个batch重建!
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

这导致 Adam 优化器的一阶矩和二阶矩估计在每个 batch 被重置,动量机制完全失效,训练效果退化为普通 SGD。修复后:

# 修复后
optimizer = optim.Adam(model.parameters(), lr=0.001)  # 只创建一次
for batch, (x, y) in enumerate(train_dataloader):
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

此外还增加了:

  • 数据增强(RandomHorizontalFlip、RandomRotation),提升泛化能力
  • shuffle=True 的 DataLoader,避免批次偏差
  • 训练完成后自动保存模型并热重载推理引擎
  • 训练进度回调机制,前端可实时显示 epoch/loss/acc

四、完整API接口文档

4.1 摄像头接口

接口 方法 请求体 说明
/api/camera/open POST {"type":"local"|"rtsp","index":0} 打开摄像头
/api/camera/close POST - 关闭摄像头
/api/camera/status GET - 获取摄像头状态
/api/camera/config POST {"user":"","password":"","ip":""} 配置RTSP参数
/api/camera/frame GET - 获取当前帧(base64 JPEG)
/api/camera/capture POST - 截取当前帧

4.2 预测接口

接口 方法 请求体 说明
/api/predict/analyze POST - 对当前帧进行AI预测
/api/predict/analyze_upload POST multipart文件 上传图片预测
/api/predict/save POST {"concrete_type":"0","slump":"180","human_label":"0","pred_label":"0","timestamp":"..."} 保存结果
/api/predict/count GET - 获取采集次数

4.3 训练接口

接口 方法 请求体 说明
/api/train/organize POST - 组织采集数据到训练/测试集
/api/train/start POST {"epochs":10,"lr":0.001} 启动训练(后台线程)
/api/train/status GET - 查询训练进度

五、项目目录结构

Concrete_Slump_Test_System/
├── run.py                  # 启动入口
├── config.py               # 全局配置
├── requirements.txt        # Python依赖
├── README.md               # 项目说明
├── resNet34.pth            # 模型权重(需自行放置)
├── app/
│   ├── __init__.py         # Flask应用工厂
│   ├── api/                # API接口层
│   │   ├── main.py         # 页面路由
│   │   ├── camera.py       # 摄像头API
│   │   ├── predict.py      # 预测API
│   │   └── train.py        # 训练API
│   ├── ml/                 # 机器学习模块
│   │   ├── resnet34.py     # ResNet模型定义
│   │   ├── classifier.py   # 推理引擎(单例)
│   │   └── trainer.py      # 训练器
│   ├── templates/
│   │   └── index.html      # Web前端
│   └── static/
└── data/
    ├── saved_frames/       # 采集图像
    └── dataset/
        ├── train/          # 训练集
        └── test/           # 测试集

这种分层结构的优势:

  • api/ml/ 完全解耦,ML模块可以独立于Web服务使用
  • 配置集中管理在 config.py,修改设备/路径/端口一处搞定
  • 数据目录与代码目录分离,便于 .gitignore 管理

六、使用流程

6.1 安装与启动

# 克隆项目
git clone https://github.com/xxx/Concrete_Slump_Test_System.git
cd Concrete_Slump_Test_System

# 安装依赖
pip install -r requirements.txt

# 放置模型权重文件 resNet34.pth 到项目根目录

# 启动服务
python run.py
# 访问 http://localhost:5000

6.2 操作步骤

  1. 打开摄像头:选择相机类型,点击"打开摄像头",视频画面实时显示
  2. 截取帧:点击"截取视频帧",捕获当前画面到分析区
  3. AI预测:点击"开始预测",模型返回分类结果、置信度和推理耗时
  4. 标注与保存:选择混凝土标号、输入坍落度值、勾选人工标注,点击"保存结果"
  5. 模型训练:积累足够数据后,点击"训练模式"一键微调,训练进度实时更新

6.3 预测结果展示

模型输出三分类结果,界面以不同颜色高亮显示:

分类 颜色 含义
合适 绿色 坍落度符合标准
偏干 橙色 混凝土偏干,坍落度不足
偏稀 青色 混凝土偏稀,坍落度过大

七、相比原版的改进

本项目由一个 PySide6 桌面应用重构而来,主要改进如下:

维度 原版(PySide6桌面端) 重构版(Flask Web端)
界面技术 PySide6/Qt,需本地安装 Web浏览器,零安装
架构 UI与业务逻辑混在main.py 前后端分离,API与ML独立
模型加载 每次预测重建模型+加载权重 单例模式,一次加载持续复用
训练bug optimizer每batch重建,动量失效 optimizer正确初始化,新增数据增强
跨平台 需配置Qt环境 浏览器即可访问,支持远程部署
可扩展性 紧耦合,难扩展 API标准化,可对接移动端/其他前端
代码质量 冗余文件多,命名混乱 规范目录结构,完整文档和配置
依赖管理 requirements.txt + .gitignore

关键改进详解

1. 模型推理性能提升

原版每次调用 predict_() 都会执行 resnet34().load_state_dict(torch.load(...)),即每帧推理需从磁盘读取 85MB 权重文件并初始化模型。单例模式下只需首次加载,后续推理跳过这两步,性能提升显著。

2. 训练收敛性修复

Adam优化器的核心优势在于自适应学习率和动量积累。原版代码在每个batch中重建optimizer,导致动量向量被反复清零,训练退化为无动量的SGD。修复后收敛速度和最终精度均有明显改善。

3. 部署灵活性

Web架构支持远程部署 —— 可以将GPU服务器部署在现场,工程人员在办公室通过浏览器即可操作,无需安装任何客户端软件。

八、技术亮点总结

  1. 前后端分离:Flask提供标准化RESTful API,前端纯HTML/JS,易于维护和二次开发
  2. 模型单例推理:避免重复加载权重,推理延迟从秒级降至毫秒级
  3. 在线微调闭环:采集→标注→训练→部署,全流程在Web界面完成,无需命令行操作
  4. 多相机支持:同时兼容USB摄像头和海康威视工业相机,适配实验室和工地场景
  5. 优雅降级:缺少PyTorch时Web服务仍可启动,不会因环境问题直接崩溃
  6. 工业风UI:暗色主题、实时视频、进度反馈、日志面板,贴合工程应用场景

九、未来展望

  • 支持更多分类类别(如坍落度数值回归预测)
  • 集成检测模型,自动定位坍落度筒区域
  • 支持多用户登录和权限管理
  • 添加历史数据查询和统计报表
  • 部署为Docker容器,一键启动
  • 模型自动选择CPU/GPU,支持无GPU环境推理

十、参考与致谢


如果觉得项目有用,欢迎 Star ⭐ 和 Fork,也欢迎提出 Issue 和 PR!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐