简介:面向高校计算机、人工智能及相关专业学生的YOLOv8药盒药品识别系统,是一套可直接运行的目标检测解决方案,针对药盒内常见药品的定位与识别场景,适用于毕业设计、课程设计及教学演示。压缩包共11个文件,大小约15.92MB,包含PyTorch模型权重(pt)、Python脚本(py)、说明文档(txt)及配置文件,涵盖模型训练、实时检测、可视化界面与部署指引。内置yolov8n.pt与训练好的best.pt权重,支持图片、视频及实时流输入;可视化界面可直观呈现置信度框选、标签分布,并输出F1分数曲线、精确率-召回率曲线、混淆矩阵等评估图表。数据集已完成标注,覆盖多角度、不同光照下的药盒图像,同时提供环境配置与一键启动说明,Windows/Linux均可运行。目前已有160人学习,所有代码实测通过,适合零基础入门者快速复现,也可作为教师演示案例或科研探索素材。 我之前做医疗相关的视觉项目比较多,这次干脆把整套流程沉淀成了一个可以一键复现的方案——YOLOv8药盒药品识别系统。从数据采集、模型训练到可视化界面,再到离线一键部署,全链路都跑通了。这篇文章就把我的踩坑记录和可行方案完整写出来,尤其是训练细节和部署环节,这些东西文档里通常不会写。
这套系统的适用场景很明确:药店自助结算台、医院药房自动盘点、家庭智能药箱,甚至仓库的药品出入库管理。核心就是通过摄像头拍一张照片,自动识别画面中的药盒是什么药、属于什么类别,再叠加后端的库存或用药提醒逻辑。适合准备入行目标检测的开发者,也适合医疗信息化项目里需要快速落地识别功能的朋友参考。
1. 项目整体设计与数据准备
1.1 方案选型:为什么是YOLOv8而不是YOLOv5或其他框架
做药品识别,第一步要选模型框架。我对比过YOLOv5、YOLOv8、以及更轻量的MobileNet-SSD方案,最终选了YOLOv8,原因只有两个:精度天花板高、部署生态完整。
YOLOv8相比v5有几个关键改动:一是从Anchor-Based改成了Anchor-Free,不再需要聚类预设锚框,对药盒这种尺寸差异不算极端的物体反而简化了调参;二是主干网络用C2f模块替换了C3,梯度流动更顺畅,小目标检测能力有实打实的提升;三是检测头换了解耦结构,分类和回归分支独立优化,收敛速度更快。对于药盒这种文字多、色块多、边缘细节丰富的目标,YOLOv8的特征提取能力明显更从容。
另外我特别看重的是Ultralytics官方仓库对训练、验证、导出做了完整的封装,一条命令就能跑完,后续集成到PyQt或Web服务都很方便。相比之下YOLOv5虽然生态成熟,但后续维护节奏明显放缓了。
1.2 数据集采集与标注:决定模型上限的关键环节
很多新手一上来就急着跑模型,这是错误的。我这次花在数据准备上的时间占整个项目的60%,因为药盒识别最怕两件事:外观相似、光照敏感。
数据采集我建议分三路进行:
- 第一路:自己采购或借用的实体药盒,用手机在不同角度、不同光照条件下拍摄,覆盖正面、侧面、45度俯视等常见姿态。
- 第二路:网络上爬取各大药房官网、电商平台的药品主图和详情图,严格过滤掉有水印和文字遮挡严重的图片。
- 第三路:如果项目上有条件,从药房实际货架摄像头截取视频帧,这种数据最贴近真实部署场景,但要注意隐私合规。
标注工具我用的X-AnyLabeling,它最大的优势是支持加载自己训练的模型做预标注,能省掉大量重复劳动。第一轮我先手动标注了大概500张,训练一个粗糙版本,然后用它去自动标注剩余数据,再人工修正。这个策略让标注速度提升了至少3倍。
标注时有一个原则:宁可框大一点,不要框小。药盒边缘通常有倒角和高光,如果边界框紧紧贴合边缘,模型训练时会被高光区域的像素干扰。我习惯在药盒实际轮廓外扩2到3个像素再做标注,实测mAP能提升1到2个点。
1.3 数据集增强与切分策略
药盒数据集的痛点在于样本不均衡。常见药品有几百张图,冷门药品可能只有十来张。我用了两层手段解决:
第一层是离线增强。对样本数量不足的类别,做随机旋转(±15度)、水平翻转、亮度扰动(0.8到1.2倍)、HSV色域扰动,把每类最少补齐到80张。注意旋转角度不要太大,超过30度会产生大量无效背景,反而干扰训练。
第二层是在线增强。YOLOv8自带Mosaic增强,把4张图随机拼接成一张,可以大幅提升模型对遮挡和密集场景的鲁棒性。在药盒识别场景下,Mosaic还能模拟货架上药品相互遮挡的情况,非常实用。
数据集的划分我用了train/val双目录结构,训练集85%、验证集15%。如果数据量超过5000张,可以再划出5%的测试集做最终评估。目录结构如下:
datasets/ ├── drug_box/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ ├── labels/ │ │ ├── train/ │ │ └── val/ │ └── data.yamldata.yaml里的类别名称要使用规范的药品通用名,避免同一个药在不同厂家名字不一样的问题。
2. YOLOv8训练要点与模型调优
2.1 环境搭建与预训练模型选择
训练环境我用的是单张NVIDIA GeForce RTX 3090,显存24GB,算是跑YOLOv8很舒服的配置。如果是GTX 1660 Ti这种6GB显存的老卡,建议用YOLOv8s而不是YOLOv8m,或者把batch降到4,同时开启梯度累积。
环境安装直接走Ultralytics官方流程:
conda create -n yolov8 python=3.9 conda activate yolov8 pip install ultralytics pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118版本锁定的坑我提一句:ultralytics版本升级很快,不同版本之间的API有差异,训练脚本跑不通百分之八十是版本不匹配。我的建议是锁定ultralytics==8.0.136,这个版本稳定,也能兼容后续的部署流程。
预训练权重我选择yolov8m.pt,在COCO上预训练过。m这个档位在精度和推理速度之间最均衡,适合药盒这种中等复杂度任务。如果追求极致速度,可以换yolov8s.pt,推理延迟能少30%左右,精度损失约2到3个点,这个Trade-off要看实际部署设备的算力。
2.2 关键训练参数设置与损失曲线研判
训练命令如下:
yolo detect train \ --model yolov8m.pt \ --data datasets/drug_box/data.yaml \ --epochs 150 \ --imgsz 640 \ --batch 16 \ --optimizer AdamW \ --lr0 0.001 \ --lrf 0.01 \ --patience 20参数设置有几个讲究,我逐一说明:
imgsz 640是速度和精度的平衡点。药盒上的药品名是小目标文字,分辨率太低会丢失细节,太高则占用显存且训练时间翻倍。实测640下小字体的识别效果够用,如果部署场景都是近距离拍摄,可以提升到800。
batch 16在3090上刚好吃到16GB左右的显存。batch再大,模型收敛速度提升有限,反而容易在初期震荡。
optimizer AdamW是我对比SGD后的个人偏好。SGD收敛更慢但泛化性略好,AdamW在前100个epoch内收敛更快,对药盒这种中等规模数据集体验更友好。注意如果选了AdamW,lr0要降一个量级,我用的0.001,SGD的话建议0.01。
训练过程中我会重点盯三张曲线图:train/loss、val/loss和metrics/mAP50。一个比较重要的判断标准是验证损失在某个epoch后开始上升,而训练损失仍在下降,说明过拟合已经开始了,这时候patience机制会自动停掉训练。如果mAP50在80%以下震荡上不去,九成是数据问题,要么标签错误,要么类别定义模糊。
2.3 增量训练与模型迭代
药品包装更新换代非常快,药盒识别系统的维护核心就是增量训练。我的做法是:
- 在线上系统收集识别置信度低于0.6的图片,人工筛选后补充到数据集。
- 使用之前的权重作为预训练模型,只调整最后几层的学习率,其他层冻结或设低学习率。
- 增量训练只需要跑30到50个epoch,就能显著提升新药品类别的召回率。
执行增量训练时,注意要把原始的data.yaml中的类别顺序保持不变,新增类别追加在最后。YOLO模型的输出维度跟类别数强绑定,如果类别顺序错乱,之前的训练成果全部作废。这个坑我踩过,第一版迭代时直接把新类别插到了前面,导致所有旧类别预测错乱。
3. 可视化界面设计与推理集成
3.1 界面方案选型:PyQt5还是Web前端
药品识别系统的使用人群,要么是药房店员,要么是家庭用户,不考虑极客场景的话,桌面应用比Web应用更合适。没有浏览器部署成本,不用起服务,双击就能运行。
我用的PyQt5,原因在于Python生态跟YOLOv8无缝衔接,不需要像C++ Qt那样做复杂的TensorRT封装。实际开发界面时,我参考了很多开源项目的设计,最终把界面拆成三个区域:
- 左侧:功能操作区,包括打开图片、打开摄像头、开始识别、导出结果四个按钮。
- 中间:实时画面显示区,用QLabel承载摄像头帧或图片。
- 右侧:检测结果列表区,显示识别到的药品名称、置信度、数量,并提供导出CSV按钮。
界面代码的核心逻辑是,通过QTimer定时从摄像头读取帧,将BGR图像传递给YOLO模型推理,然后把绘制了边界框和标签的结果传回显示区。关键代码结构如下:
import cv2 import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtCore import QTimer from ultralytics import YOLO class DrugDetector(QMainWindow): def __init__(self): super().__init__() self.model = YOLO("best.pt") self.cap = cv2.VideoCapture(0) self.timer = QTimer() self.timer.timeout.connect(self.update_frame) def update_frame(self): ret, frame = self.cap.read() if not ret: return results = self.model.predict(frame, conf=0.5, verbose=False) annotated = results[0].plot() self.show_image(annotated) def show_image(self, img): rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) h, w, ch = rgb.shape bytes_per_line = ch * w qt_img = QImage(rgb.data, w, h, bytes_per_line, QImage.Format_RGB888) self.label.setPixmap(QPixmap.fromImage(qt_img))3.2 推理性能优化:从模型侧和代码侧同时入手
药盒识别这种场景,用户最直接的体感就是识别响应快不快。模型推理时间主要受网络结构和输入分辨率影响,但我发现很多人忽略了一个点:推理引擎的选择。
纯PyTorch推理,YOLOv8m在3090上大概8到10毫秒一张图,看似很快,但部署到旧电脑的CPU上,一张640x640的图可能要500毫秒以上,严重影响体验。我的优化策略是:
- 优先导出ONNX格式,用
onnxruntime-gpu进行推理,比PyTorch原生推理快20%到30%。 - 如果部署机器有NVIDIA显卡且显存充足,可以进一步用TensorRT导出FP16精度模型,速度提升最明显,能达到五倍以上。
- 对CPU部署场景,开启
int8量化,精度损失控制在2%以内,速度提升三倍。
另外在代码层面,可以开启多线程异步推理,摄像头采帧和模型预测并行,避免画面卡顿。实测下来,界面的流畅度提升非常可观。
4. 一键部署:从Python环境到免配置运行的完整封装
4.1 依赖打包与模型文件组织
给客户部署系统,最忌讳的就是让对方手动装Python环境、装CUDA、装PyTorch。我的方案是提供一个一键部署脚本,自动完成环境检测、依赖安装、模型文件校验三个步骤。
第一步,写一个setup.bat(Windows)或setup.sh(Linux),核心逻辑是:
echo 检查Python环境... python --version 2>NUL || (echo 未检测到Python,开始安装... && powershell -Command "Invoke-WebRequest ...") echo 创建虚拟环境... python -m venv venv call venv\Scripts\activate.bat echo 安装依赖... pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple echo 校验模型文件... if not exist models\best.pt ( echo 模型文件缺失,请将模型文件放入models目录 pause exit /b 1 ) echo 部署完成,正在启动系统... python main.py模型文件需要跟代码分离存放。我通常用models/目录单独放权重,weights/目录放ONNX或TensorRT引擎文件。注意.gitignore中要排除这些大文件,避免仓库体积失控。
4.2 离线部署与免安装打包
有些药房的电脑是完全离线的,不能用pip在线下载依赖。这时候我建议直接用PyInstaller把整个应用打包成单个exe文件。打包命令:
pyinstaller -F -w -D \ --name DrugBoxRecognizer \ --add-data "models/best.pt;models" \ --add-data "ui/;ui" \ main.py打包过程中最大的坑是PyQt5和ultralytics的动态导入问题。PyInstaller默认不会自动收集隐式导入的模块,导致打包出来的exe一运行就报ModuleNotFoundError。解决方法是加--hidden-import参数,或者在脚本里显式导入所有可能用到的模块。我踩过的一个具体问题是ultralytics.nn.tasks在打包后缺失,必须在代码顶部主动import ultralytics.nn.tasks一遍才能规避。
4.3 性能压测与硬件选型建议
部署前我习惯先在目标机器上做一轮性能压测,核心指标是推理耗时和显存占用。以下是我实测的一组数据,可以作为硬件选型的参考:
| 硬件平台 | 推理引擎 | 分辨率 | 单帧耗时 | 显存占用 |
|---|---|---|---|---|
| RTX 3090 | TensorRT FP16 | 640x640 | 约4ms | 1.2GB |
| GTX 1660 Ti | ONNX Runtime | 640x640 | 约18ms | 0.8GB |
| M1 MacBook Air | PyTorch MPS | 640x640 | 约40ms | 1.1GB |
| CPU i5-10400 | ONNX Runtime INT8 | 640x640 | 约150ms | 0.5GB |
结论是,如果部署在药店收银台,需要毫秒级响应,至少配一块GTX 1660 Ti以上的显卡。如果只是家庭药箱管理,CPU部署150毫秒完全够用,不用为了速度增加硬件成本。
5. 常见问题与排查技巧实录
我整理了整个项目周期里最常遇到的几个问题,做成速查表,方便你的项目遇到类似问题时快速定位:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 训练时loss为NaN | 学习率过大或数据集中有空标签 | 降低lr0到0.0001,检查labels目录是否有空txt文件 |
| mAP50很低但训练loss正常 | 标签类别定义重叠或标注框偏移 | 用X-AnyLabeling打开数据集逐类检查,合并模糊类别 |
| 摄像头画面卡顿 | 推理阻塞了UI主线程 | 把推理放到QThread子线程,用信号槽传递结果 |
| 打包后exe无法启动 | PyInstaller缺少隐式导入模块 | 显式import ultralytics.nn.tasks,增加hidden-import |
| 模型对暗光图片识别差 | 训练数据缺少低光照样本 | 在数据增强中增加亮度扰动范围,补充暗光实拍图 |
| 增量训练后旧类别识别崩溃 | 类别顺序被打乱 | 保持原有类别ID顺序,新类别追加到末尾 |
最后一个问题是很多人忽略的:药品类别数量不是越多越好。我最初尝试塞进60类药品,mAP50直接掉到75%以下。后来精简到25类,把外观极其相似、容易混淆的药品合并为同一个类别,识别率提升到94%以上。做实际项目时,一定要跟业务方确认清楚哪些药必须区分,哪些可以合并,这会直接影响模型的可用性。
另外还有一个关于标注的小细节,虽然我在数据准备那节提过,但这里值得再强调——对反光药盒的标注要格外小心。许多药盒表面是光面覆膜,在灯光下会产生大面积的高光反射,这些区域的纹理跟药盒原图案完全不同。如果标注框把这些高光区域全部框进来,模型很容易学到错误特征。我的做法是,在标注时对高光严重的样本做亮度归一化预处理,并在训练时多加入不同角度光源下的实拍样本,这个细节对精度的影响比很多超参数调整都大。
6. 部署到终端后的系统维护心得
系统真正上线后,维护工作才刚刚开始。前面讲过增量训练的流程,这里补充一个实操经验:不要等到模型精度明显下降时再更新,而是要建立数据回流和主动学习的机制。
我部署的药盒识别系统会记录每一次推理的结果和置信度。每天下班前,我会把置信度低于0.6的预测图片导出,快速浏览一遍,把确实识别错误的图片挑出来,补充到标注池里。每周做一次增量训练,每次投入的时间不超过半小时,但模型的持续进化能力完全靠这个机制维持。
另外还有一个容易忽略的维护点:摄像头角度变化。药店的摄像头如果被调整过位置,或者货架换了角度,原来训练的视角分布就会偏离,识别率会明显下降。我建议部署时在系统设置里增加一个"标定模式",让操作人员对着标准标定板拍一张照片,用来对照当前视角跟训练数据的差异,如果偏差太大,系统会提示重新采集数据。
这套系统的价值在于把目标检测、可视化交互和部署维护三条链路打通了。如果你正在做类似的项目,建议在最开始就考虑好数据的持续回流机制,不要只做一个一次性的模型。最后再分享一个小建议:药盒识别场景里,精度比速度重要,但稳定性比精度更重要。用户不会因为偶尔一次漏检而愤怒,但会因为你每次识别结果都在抖动而完全失去信任。与其追求极限的mAP,不如保证在正常使用场景下每次都能给出一致、可解释的识别结果。
本文还有配套的精品资源,点击获取