MonitorSystem 摄像头检测系统 — 调研报告¶
项目来源:用户通过 SCP 上传的
MonitorSystem.zip调研日期:2026-05-14 调研环境:Ubuntu 24.04 (LXD 容器)
一、项目概述¶
1.1 基本信息¶
| 项目 | 内容 |
|---|---|
| 项目名称 | 摄像头检测系统 (MonitorSystem) |
| 版本 | v1.0.0 |
| 技术栈 | Python 3.7+ / Tkinter / OpenCV / PyTorch / EfficientNet-B3 |
| 运行平台 | Windows 10/11(设计目标),Linux 可适配 |
| 打包方式 | PyInstaller |
| 项目规模 | ~1,500 行 Python 代码 + 220MB 模型权重 |
1.2 功能定位¶
工业场景下的实时视觉检测系统,包含两个独立模块:
- 膨胀检测模块(swellcamera)— 判断物料是否发生膨胀(二分类)
- 含水量检测模块(watercamera)— 判断物料含水量区间(三分类:30-35% / 35-40% / 40-45%)
二、项目结构¶
MonitorSystem/
├── main.py # 主程序(Tkinter GUI,848 行)
├── README.md # 项目说明文档
├── requirements.txt # 依赖清单
├── CameraMonitorSystem.spec # PyInstaller 打包配置
├── add_hidden_imports.py # PyInstaller 隐藏导入辅助
├── hook-tkinter.py # PyInstaller Tkinter 钩子
├── logo.ico # 程序图标
├── fonts/
│ └── simhei.ttf # 中文字体(黑体)
├── models/ # AI 模型定义与权重
│ ├── model1.py # 含水量分类器 1(35-40 vs 30-35)
│ ├── model2.py # 含水量分类器 2(40-45 vs 35-40)
│ ├── model3.py # 含水量分类器 3(40-45 vs 30-35)
│ ├── model4.py # 膨胀分类器(膨胀 vs 不膨胀)
│ ├── __init__.py
│ ├── best_model1.pth # 训练权重(43MB)
│ ├── best_model2.pth # 训练权重(43MB)
│ ├── best_model3.pth # 训练权重(43MB)
│ ├── best_model4.pth # 训练权重(43MB)
│ └── efficientnet_b3_pytorch.pth # EfficientNet-B3 backbone(48MB)
├── swellcamera/ # 膨胀检测模块
│ ├── swellcamera.py # 膨胀检测主逻辑(208 行)
│ ├── __main__.py # 模块入口
│ └── __init__.py
├── watercamera/ # 含水量检测模块
│ ├── watercamera.py # 含水量检测主逻辑(221 行)
│ ├── __main__.py # 模块入口
│ └── __init__.py
└── utils/
└── model_loader.py # 动态模型加载器
三、架构分析¶
3.1 整体架构¶
┌─────────────────────────────────────────────────┐
│ main.py (GUI) │
│ Tkinter + threading │
├─────────────────┬───────────────────────────────┤
│ ModuleManager │ CameraDetectionApp │
│ (线程管理) │ (界面 + 状态同步) │
├─────────┬───────┴───────────────────────────────┤
│ swellcamera │ watercamera │
│ (膨胀检测) │ (含水量检测) │
├─────────────┴───────────────────────────────────┤
│ models/ (PyTorch) │
│ EfficientNet-B3 + 分类头 │
├─────────────────────────────────────────────────┤
│ OpenCV + PIL (图像处理) │
└─────────────────────────────────────────────────┘
3.2 数据流¶
膨胀检测流程:
含水量检测流程:
摄像头(索引1) → 每 5 秒采集 1 帧 → 写入临时文件 → PIL 打开 →
model1/model2/model3 各自推理 → 置信度过滤(>0.1) → 加权投票 →
最终含水量区间 → PIL 绘制中文 → OpenCV 显示
3.3 模型架构¶
所有模型共享同一个 backbone:
- Backbone: EfficientNet-B3(通过
efficientnet_pytorch库的from_name加载,不加载 ImageNet 预训练) - 输入尺寸: 300×300 RGB
- 分类头: 替换最终全连接层为
Linear(1536→256) → BatchNorm → Linear(256→1)+ Sigmoid
| 模型 | 用途 | 分类任务 | 分类头特点 |
|---|---|---|---|
| model1 | 含水量 | 35-40% vs 30-35% | Identity 占位层 |
| model2 | 含水量 | 40-45% vs 35-40% | Identity 占位层 |
| model3 | 含水量 | 40-45% vs 30-35% | Identity 占位层 |
| model4 | 膨胀 | 膨胀 vs 不膨胀 | Dropout(0.45/0.55) + ReLU |
注意: model1-3 使用 Identity 层占位(训练时可能有 Dropout,推理时被替换),model4 保留了 Dropout 和 ReLU。两者分类头结构不一致。
四、问题清单¶
4.1 严重问题(🔴 必须修复)¶
P0-1:模块停止机制失效¶
位置: main.py ModuleManager + swellcamera.py / watercamera.py
问题: stop_swell_module() 仅设置 self.swell_stop_event,但 swellcamera.main() 的检测循环中完全没有检查该事件。用户点击"停止"按钮后,检测线程继续运行,只有在 OpenCV 窗口按 'q' 才能真正退出。
影响: GUI 状态与实际运行状态不同步,用户误以为已停止但摄像头仍在占用。
修复建议: 在检测循环中添加 stop_event.is_set() 检查,或改用共享的 threading.Event 控制循环退出。
P0-2:每帧写入临时文件¶
位置: swellcamera.py:66 / watercamera.py:73
问题:
每一帧都先把 OpenCV 画面写成 JPG 文件,再用 PIL 读回来。影响:
- 性能极差(磁盘 I/O 成为瓶颈)
- 膨胀检测每帧都写,约 30fps → 每秒 30 次磁盘写入
- 两个模块同时运行时,写同一个 temp_frame.jpg,产生文件冲突
修复建议: 使用内存转换:
P0-3:摄像头索引硬编码¶
位置: swellcamera.py:15 / watercamera.py:16
问题: camera_index = 1(非默认的 0),没有 fallback 逻辑。
影响: 在只有一台摄像头的设备上可能找不到摄像头;在无摄像头设备上直接崩溃。
修复建议: 改为可配置参数,添加 fallback(先试 1,失败试 0),或提供摄像头选择界面。
4.2 中等问题(🟡 建议修复)¶
P1-1:模型类名错误¶
位置: models/model1.py ~ model4.py
问题: 所有模型类都叫 AgeClassifier(年龄分类器),明显是从其他项目复制粘贴而来。
影响: 代码可读性差,维护时容易混淆。
P1-2:模型接口不统一¶
问题:
- model1-3 的 predict() 返回 (pred_label, class_probs) 元组
- model4 的 predict() 返回 dict {class, probabilities, confidence}
影响: 调用方式不一致,增加维护成本。
P1-3:字体路径仅支持 Windows¶
位置: swellcamera.py / watercamera.py
问题: 字体搜索只列了 C:/Windows/Fonts/,watercamera.py 硬编码 simhei.ttf。
影响: 在 Linux/macOS 上运行时,中文显示会失败。
P1-4:torch.load 安全风险¶
位置: models/model1.py ~ model4.py
问题:
未指定weights_only=True,存在 pickle 反序列化攻击风险。
4.3 轻微问题(🟢 可选优化)¶
| 编号 | 问题 | 说明 |
|---|---|---|
| P2-1 | 裸 except: pass |
main.py:800,吞掉所有异常,调试困难 |
| P2-2 | 无日志系统 | 全用 print(),无法控制级别、无法持久化 |
| P2-3 | 模型无延迟加载 | import 时就加载权重,启动慢 |
| P2-4 | 硬编码 Windows 路径 | 测试代码中有 E:\kingtask\... |
| P2-5 | 无 requirements.txt 实质内容 | 大部分依赖被注释,缺少 opencv-python、torch、efficientnet_pytorch 等关键依赖 |
| P2-6 | .idea/ 目录未清理 |
PyCharm 配置文件被打包进了 zip |
| P2-7 | tempCodeRunnerFile.py |
VS Code/PyCharm 临时文件,不应出现在项目中 |
| P2-8 | 无训练代码 | 只有推理代码,无法复现训练过程 |
五、代码质量评估¶
| 维度 | 评分 | 说明 |
|---|---|---|
| 功能完整性 | ⭐⭐⭐ | 两个检测模块基本可用,推理流程完整 |
| 代码质量 | ⭐⭐ | 大量复制粘贴、命名混乱、无注释规范、临时文件滥用 |
| 架构设计 | ⭐⭐ | 模块停止机制失效、接口不统一、无配置化 |
| 可维护性 | ⭐⭐ | 硬编码多、无日志、无文档注释 |
| 可部署性 | ⭐⭐⭐ | 有 PyInstaller 支持,但字体/摄像头硬编码 |
| 安全性 | ⭐⭐ | torch.load 无 weights_only、无输入验证 |
综合评价: 学生课程项目水平。核心功能(模型推理 + 摄像头采集)流程完整,但工程质量粗糙,存在多个影响实际使用的 bug。
六、下一步修改建议¶
6.1 优先级排序¶
| 优先级 | 任务 | 预计工作量 | 说明 |
|---|---|---|---|
| P0 | 修复模块停止机制 | 1h | 检测循环中添加 stop_event 检查 |
| P0 | 消除临时文件写入 | 0.5h | 改用内存中的 numpy→PIL 转换 |
| P0 | 摄像头索引可配置化 | 0.5h | 添加参数 + fallback 逻辑 |
| P1 | 统一模型 predict() 接口 | 1h | 统一返回 dict 格式 |
| P1 | 修复字体路径(跨平台) | 0.5h | 添加 Linux/macOS 字体搜索路径 |
| P1 | torch.load 安全修复 | 0.5h | 添加 weights_only=True |
| P2 | 清理项目文件 | 0.5h | 删除 .idea/、tempCodeRunnerFile.py、pycache/ |
| P2 | 补全 requirements.txt | 0.5h | 列出所有实际依赖及版本 |
| P2 | 添加日志系统 | 1h | 用 logging 替代 print |
| P2 | 修复裸 except | 0.5h | 改为具体异常类型 |
总预估工作量: 约 6-7 小时
6.2 建议的修改方案¶
阶段一:修复核心 Bug(P0)¶
-
停止机制:在
swellcamera.py和watercamera.py的主循环中添加: -
消除临时文件:替换
cv2.imwrite+Image.open为: -
摄像头配置化:
阶段二:统一接口(P1)¶
-
统一 predict 返回值:所有模型返回统一的 dict 格式:
-
跨平台字体:
阶段三:工程优化(P2)¶
- 清理临时文件和 IDE 配置
- 补全 requirements.txt
- 添加 logging 日志系统
- 修复异常处理
七、测试方案¶
7.1 在当前环境(无摄像头 LXD 容器)可执行的测试¶
| 测试项 | 可行性 | 方法 |
|---|---|---|
| 模型权重加载 | ✅ | 验证 4 个 .pth 文件能正确加载 |
| 模型推理流程 | ✅ | 用随机 300×300 图片测试 predict() |
| 模型结构一致性 | ✅ | 对比 model1-3 和 model4 的分类头 |
| Tkinter GUI | ❌ | 需要 DISPLAY |
| 摄像头采集 | ❌ | 需要摄像头设备 |
| OpenCV 窗口显示 | ❌ | 需要 GUI 环境 |
7.2 建议的测试脚本¶
# test_models.py — 验证模型加载和推理
import torch
from PIL import Image
import numpy as np
# 测试 model4(膨胀检测)
from models.model4 import AgeClassifier
classifier = AgeClassifier("models/best_model4.pth")
dummy_image = Image.fromarray(np.random.randint(0, 255, (300, 300, 3), dtype=np.uint8))
dummy_image.save("test_input.jpg")
result = classifier.predict("test_input.jpg")
print(f"膨胀检测结果: {result}")
八、附录¶
8.1 文件清单(排除 pycache 和 .idea)¶
共 31 个文件:
- Python 源码: 13 个 (.py)
- 模型权重: 5 个 (.pth, 共 220MB)
- 配置/打包: 3 个 (.spec, .txt, .bat)
- 资源文件: 2 个 (.ico, .ttf)
- 文档: 2 个 (.md)
- 其他: 6 个 (.idea/, tempCodeRunnerFile.py)
8.2 依赖清单(从代码推断)¶
# requirements.txt(实际需要的依赖)
torch>=1.9.0
torchvision>=0.10.0
efficientnet_pytorch>=0.7.0
opencv-python>=4.5.0
Pillow>=8.0.0
numpy>=1.20.0
pyinstaller>=5.0.0
8.3 已知训练信息¶
- 训练日期:2025 年 6-7 月
- Backbone:EfficientNet-B3(300×300 输入)
- 训练数据:未包含在项目中
- 训练代码:未包含在项目中
- 训练日志:未包含在项目中
报告生成时间:2026-05-14