1. 项目概述
这个基于YOLOv11的食物检测系统是我最近完成的一个深度学习应用项目。它能够识别30种常见食物和饮品,从水果到主食再到各种饮料都能准确检测。系统最让我满意的地方在于它不仅实现了高精度的检测模型,还配套开发了完整的用户界面,包括登录注册功能和多种检测模式切换。
在实际测试中,这个系统对复杂场景下的食物识别表现相当不错。比如在厨房环境中,即使有多个食物堆叠或者部分遮挡的情况,模型也能保持较高的识别准确率。这得益于我们精心准备的数据集——包含了14,661张标注图像,涵盖了各种光照条件和拍摄角度。
2. 系统架构设计
2.1 整体架构
系统采用典型的三层架构:
- 前端界面层:基于PyQt5实现的用户界面,包含登录注册、参数配置和结果显示等功能模块
- 业务逻辑层:处理用户请求,调度检测任务,管理多线程运行
- 算法模型层:YOLOv11检测模型,负责实际的图像分析和目标识别
这种分层设计使得系统各模块职责明确,便于后期维护和功能扩展。比如要增加新的检测类别,只需要更新模型层,其他部分几乎不需要改动。
2.2 技术选型考量
选择YOLOv11作为基础模型主要基于以下几点考虑:
- 实时性:相比其他目标检测算法,YOLO系列以速度快著称,适合需要实时反馈的应用场景
- 准确性:v11版本在保持速度优势的同时,通过结构优化提升了小目标检测能力
- 社区支持:Ultralytics维护的YOLO生态有完善的文档和活跃的社区,遇到问题容易找到解决方案
UI框架选择PyQt5而非更现代的PySide6,主要是考虑到:
- 项目组成员对PyQt5更熟悉,开发效率更高
- PyQt5的成熟度和稳定性已经过大量项目验证
- 需要的一些特定控件在PyQt5中实现起来更方便
3. 数据集准备
3.1 数据收集与标注
我们构建的数据集包含30个精细标注的食物类别,具体包括:
- 水果类:草莓、蓝莓、黑莓、菠萝等
- 主食类:面包、披萨、意大利面等
- 饮品类:酒精、牛奶、乳基饮料等
- 其他:鸡蛋、巧克力、奶酪等
数据分布如下:
- 训练集:12,802张(87.3%)
- 验证集:1,220张(8.3%)
- 测试集:639张(4.4%)
标注采用YOLO格式,每个图像对应一个.txt文件,包含物体类别和边界框坐标。我们特别注重了数据的多样性,确保每种食物在不同光照、角度和背景条件下都有充分样本。
3.2 数据增强策略
为了提高模型鲁棒性,训练时应用了多种数据增强技术:
- 颜色变换:调整亮度、对比度和饱和度
- 几何变换:随机旋转、缩放和裁剪
- Mosaic增强:四张图像拼接训练,提升小目标检测能力
- MixUp:图像混合增强,提高模型泛化性
这些增强手段使我们的模型在面对实际场景中的各种变化时表现更加稳定。
4. 模型训练与优化
4.1 训练配置
我们使用以下关键参数进行模型训练:
python复制model = YOLO('yolo11s.pt') # 使用预训练权重初始化
results = model.train(
data='data.yaml',
epochs=100,
batch=8,
device='0', # 使用GPU 0
workers=0, # 数据加载线程数
project='runs',
name='exp'
)
选择yolov11s模型是因为它在速度和精度之间取得了良好平衡。对于需要更高精度的场景,可以考虑使用yolov11m或yolov11l,但会牺牲一些推理速度。
4.2 训练过程监控
训练过程中我们密切关注以下指标:
- 损失函数变化(box_loss, cls_loss, dfl_loss)
- 验证集mAP(mean Average Precision)
- 推理速度(FPS)
通过TensorBoard可以直观看到这些指标的变化趋势。典型的训练过程约需6-8小时(使用RTX 3060显卡),最终在验证集上达到的mAP@0.5约为0.89。
实际训练中发现,当epoch达到80左右时,模型性能基本趋于稳定,继续训练带来的提升有限。这时可以适当降低学习率或提前终止训练。
5. 系统功能实现
5.1 用户认证模块
登录注册系统采用本地JSON文件存储账户信息,实现了以下功能:
- 用户名密码验证
- 密码长度检查(至少6位)
- 简单的账户信息加密存储
核心代码如下:
python复制def handle_login(self):
username = self.username_input.text().strip()
password = self.password_input.text().strip()
if not username or not password:
QMessageBox.warning(self, "警告", "用户名和密码不能为空!")
return
if username in self.accounts and self.accounts[username] == password:
self.accept() # 验证通过
else:
QMessageBox.warning(self, "错误", "用户名或密码错误!")
5.2 检测功能实现
系统支持三种检测模式:
- 图片检测:支持常见图片格式(JPG/PNG等)
- 视频检测:处理MP4/AVI等视频文件
- 实时摄像头:使用默认摄像头进行实时检测
检测线程的核心逻辑:
python复制class DetectionThread(QThread):
frame_received = pyqtSignal(np.ndarray, np.ndarray, list)
def run(self):
if isinstance(self.source, int) or self.source.endswith(('.mp4', '.avi')):
cap = cv2.VideoCapture(self.source)
while self.running:
ret, frame = cap.read()
if not ret: break
results = self.model(frame, conf=self.conf, iou=self.iou)
annotated_frame = results[0].plot()
detections = []
for box in results[0].boxes:
detections.append((
self.model.names[int(box.cls)],
float(box.conf),
*box.xywh[0].tolist()
))
self.frame_received.emit(
cv2.cvtColor(frame, cv2.COLOR_BGR2RGB),
cv2.cvtColor(annotated_frame, cv2.COLOR_BGR2RGB),
detections
)
cap.release()
5.3 结果可视化
系统提供双画面显示:
- 左侧显示原始图像
- 右侧显示检测结果(带边界框和标签)
同时以表格形式列出检测到的物体信息,包括:
- 类别名称
- 置信度分数
- 物体中心坐标(x,y)
6. 系统部署与使用
6.1 环境配置
推荐使用Anaconda创建独立的Python环境:
bash复制conda create -n yolov11 python=3.9
conda activate yolov11
pip install -r requirements.txt
requirements.txt包含的主要依赖:
code复制torch==2.0.1
torchvision==0.15.2
ultralytics==8.0.0
opencv-python==4.7.0
PyQt5==5.15.7
6.2 使用指南
- 启动系统:
bash复制python main.py
-
登录或注册新账户
-
选择检测模式:
- 图片检测:点击"图片"按钮选择图像文件
- 视频检测:点击"视频"按钮选择视频文件
- 实时检测:点击"摄像头"按钮开启摄像头
- 调整参数(可选):
- 置信度阈值(默认0.5)
- IoU阈值(默认0.45)
- 查看检测结果,可选择保存结果到本地
7. 性能优化技巧
7.1 模型推理加速
通过以下方法可以提升系统运行效率:
- 使用TensorRT加速:将模型转换为TensorRT格式可获得显著速度提升
- 启用半精度推理:在支持FP16的GPU上可以减少计算量
- 调整检测参数:适当降低置信度阈值和IoU阈值可以提高速度,但会牺牲一些准确率
7.2 内存管理
在处理大尺寸图像或长视频时,注意:
- 及时释放不再使用的资源
- 使用生成器而非列表处理大量数据
- 设置合理的batch size避免内存溢出
8. 常见问题排查
8.1 检测结果不准确
可能原因及解决方法:
- 光线条件差 → 调整图像亮度或使用图像增强
- 物体遮挡严重 → 尝试调整置信度阈值
- 训练数据不足 → 增加相关类别的训练样本
8.2 系统运行缓慢
优化建议:
- 检查是否使用了GPU加速
- 降低输入图像分辨率
- 关闭不必要的后台程序
8.3 界面卡顿问题
多线程处理是关键:
- 确保检测任务在独立线程中运行
- 避免在UI线程中进行耗时操作
- 使用信号槽机制进行线程间通信
9. 项目扩展方向
这个系统还有很大的改进空间:
- 增加营养分析功能:根据检测到的食物计算卡路里和营养成分
- 支持多语言界面:增加英语等语言支持
- 云端部署:将模型部署到服务器,支持移动端访问
- 食谱推荐:基于检测结果推荐合适的食谱
在实际使用过程中,我发现系统对透明容器中的液体(比如玻璃杯中的饮料)识别准确率还有提升空间。这可能需要收集更多此类场景的训练数据,或者尝试在数据增强时特别关注这类情况。
