YOLOv8药盒药品识别系统:从数据集构建到Docker部署全流程

发布时间:2026/10/13 2:03:16
YOLOv8药盒药品识别系统:从数据集构建到Docker部署全流程 简介这是一套面向计算机、人工智能、自动化等专业学生及初学者的YOLOv8药品识别实战资源可用于毕业设计、课程设计、大作业或教学演示。系统基于YOLOv8目标检测框架支持图片与视频输入自动定位并识别药盒内常见药品内置yolov8n.pt与训练好的best.pt权重配套训练脚本与实时视频流检测脚本可视化界面可查看检测结果、置信度框选、标签分布图以及F1分数曲线、精确率-召回率曲线、混淆矩阵等评估图表。压缩包共11个文件约15.92MB以3个pt权重文件、3个py脚本、3个txt说明文档为主另含gitignore与inscode配置数据集已标注整理覆盖多角度、不同光照下的药盒图像。部署说明覆盖环境配置、依赖安装、权重加载与界面启动全流程Windows与Linux均可运行README提供清晰操作指引。目前已有171人学习适合快速上手目标检测项目并完成完整实践闭环。1. 药盒识别为什么总在真实货架上翻车做过零售视觉的人多半有过这种体验在自建数据集上 mAP 跑到 0.95信心满满搬到门店货架前模型立刻变成“睁眼瞎”。YOLOv8 药盒药品识别系统这个方向真正难的不是把 YOLOv8 跑起来而是让它在真实药盒场景里稳定输出。药盒本身是极难的检测目标长宽比极端有的细长如牙膏盒有的接近正方形、表面大面积白底反光、文字密集且字号极小、同类药品不同规格包装高度相似、货架摆放密集遮挡严重。这些特性叠加在一起直接导致通用检测模型在药盒场景下召回率断崖式下跌。这套系统要解决的核心问题很明确给定一张药盒货架或单盒照片输出药品类别、位置框和置信度并提供一个可视化界面供非技术人员使用。它适合三类人一是做智慧药房、零售盘点、药品分拣的工程团队二是想拿一个完整闭环项目练手 YOLOv8 全流程的算法同学三是需要快速验证药盒识别可行性的产品负责人。整条链路包含数据集构建、模型训练、界面封装和一键部署四个环节缺任何一环都只是 demo不是系统。2. 数据集构建与标注药盒识别的地基怎么打2.1 药盒数据集的采集策略与类别划分药盒识别的数据集不能随便拍。我一般按“场景分层 类别分层”两条线采集。场景分层指单盒正面平铺、单盒多角度、货架密集排列、手持遮挡、不同光照冷白灯、暖黄灯、自然光。类别分层指按药品通用名划分而不是按包装颜色或厂商划分因为同一种药可能换包装但通用名不变。类别数量建议控制在 30 到 80 之间太少没有泛化价值太多标注成本爆炸且长尾类别样本不足。采集时有个血泪经验每个类别至少保证 200 张有效样本其中货架密集场景占比不低于 40%。很多团队前期只拍单盒平铺图训练出来的模型在货架上直接崩掉因为密集遮挡下的特征分布和单盒完全不同。另外药盒表面的反光区域要刻意覆盖否则模型会把反光当成类别特征换一个光源就翻车。2.2 用 LabelImg 标注药盒并转成 YOLO 格式标注工具用 LabelImg 或 AnyLabeling 都行格式选 YOLO txt。标注时框要贴紧药盒外边缘不要框到货架背景也不要漏掉被遮挡但可辨认的盒子。下面是把 LabelImg 的 XML 转成 YOLO txt 的脚本import os import xml.etree.ElementTree as ET # 类别映射必须与训练时的 data.yaml 顺序一致 CLASSES [box_a, box_b, box_c] # 替换为你的药品类别名 def convert_annotation(xml_path, img_w, img_h, out_txt): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in CLASSES: continue cls_id CLASSES.index(cls_name) bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # YOLO 格式中心点 x,y 和宽高全部归一化到 0-1 cx (xmin xmax) / 2.0 / img_w cy (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(out_txt, w) as f: f.write(\n.join(lines)) # 批量转换示例 for xml_file in os.listdir(annotations): if xml_file.endswith(.xml): # 这里需要读取对应图片尺寸实际使用时用 PIL 或 cv2 获取 img_w, img_h 1920, 1080 # 替换为真实尺寸 convert_annotation( os.path.join(annotations, xml_file), img_w, img_h, os.path.join(labels, xml_file.replace(.xml, .txt)) )这段脚本的关键点有三个类别顺序必须和后续 data.yaml 里的 names 完全一致否则训练出来的类别全是错的归一化坐标要保留六位小数避免小目标精度损失被遮挡但可辨认的药盒要标完全不可辨认的不要标否则模型学到模糊特征。转换完成后按 8:1:1 划分训练集、验证集、测试集测试集里必须包含至少一个完整货架场景用来验证真实部署效果。2.3 data.yaml 配置与数据增强参数data.yaml 是 YOLOv8 训练的入口配置路径和类别名写错是最常见的低级翻车点path: /data/medicine_box # 数据集根目录 train: images/train val: images/val test: images/test names: 0: box_a 1: box_b 2: box_c数据增强方面药盒场景我一般开 mosaic1.0、mixup0.1、degrees10、translate0.1、scale0.3。mosaic 对密集小目标提升明显但 mixup 不要开太大药盒文字密集mixup 过度会让文字特征糊掉。另外 hsv_h、hsv_s、hsv_v 分别设 0.015、0.7、0.4用来对抗不同药房的灯光色温差异。如果货架遮挡特别严重可以额外开 copy_paste0.1把药盒实例粘贴到不同背景上提升遮挡鲁棒性。3. YOLOv8 训练调参与模型导出3.1 从预训练权重开始训练的最小命令不要从零训练药盒数据集规模通常不足以支撑随机初始化。用 COCO 预训练权重做迁移学习收敛快且小目标召回更好yolo detect train \ data/data/medicine_box/data.yaml \ modelyolov8s.pt \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ patience30 \ device0 \ projectruns/medicine \ nameexp01参数说明model 选 yolov8s 而不是 n 或 m是因为药盒文字和小目标需要一定容量n 容易欠拟合m 在单卡上训练太慢imgsz640 是精度和速度的平衡点如果药盒在图中占比很小可以提到 960 或 1280但显存要够lr00.01 是 SGD 的初始学习率用 AdamW 的话降到 0.001patience30 表示 30 轮无提升就早停避免过拟合。训练过程中重点看 metrics/mAP50-95 和 val/box_loss如果 box_loss 震荡不降多半是标注框质量有问题。3.2 药盒小目标检测的三个必调参数药盒在货架图中往往只占几十个像素属于典型小目标。除了提高 imgsz还有三个参数直接影响小目标召回参数默认值药盒场景建议作用imgsz640960 或 1280提升小目标分辨率box7.59.0 到 10.0加大框回归损失权重cls0.50.8 到 1.0加大分类损失权重box 和 cls 在训练命令里通过box9.0 cls0.9传入。加大 box 权重能让模型更关注定位精度加大 cls 权重能缓解同类药盒包装相似导致的误分类。但不要同时拉太高否则训练不稳定建议先调 box再微调 cls。3.3 导出 ONNX 与 TensorRT 的取舍训练完的 best.pt 要部署通常导出 ONNX 或 TensorRT# 导出 ONNX通用性最好 yolo export modelruns/medicine/exp01/weights/best.pt formatonnx opset12 simplifyTrue # 导出 TensorRTNVIDIA 平台推理最快 yolo export modelruns/medicine/exp01/weights/best.pt formatengine halfTrue device0ONNX 适合跨平台CPU 也能跑但速度一般TensorRT 在 NVIDIA 显卡上能快 2 到 3 倍但绑定硬件和驱动版本。如果部署环境不确定先导 ONNX 保底确定是 NVIDIA 边缘设备再导 engine。注意导出 engine 时 halfTrue 用 FP16精度损失通常可接受但如果药盒文字识别对置信度敏感先用 FP32 验证再切 FP16。4. 可视化界面与一键部署4.1 用 Gradio 搭一个药盒识别界面可视化界面不需要多复杂能上传图片、显示检测框和类别就够了。Gradio 是最快的方式import gradio as gr from ultralytics import YOLO model YOLO(runs/medicine/exp01/weights/best.pt) def detect(image): results model.predict(image, imgsz960, conf0.35, iou0.5) # results[0].plot() 返回带框的 numpy 图像 return results[0].plot() demo gr.Interface( fndetect, inputsgr.Image(typenumpy), outputsgr.Image(typenumpy), title药盒药品识别, description上传药盒图片自动识别类别与位置 ) demo.launch(server_name0.0.0.0, server_port7860)conf0.35 是药盒场景的经验阈值太低会误检货架纹理太高会漏检遮挡盒。iou0.5 控制 NMS 合并密集货架可以降到 0.4 减少漏检。界面里不要只显示框最好把类别名和置信度一起画上去方便人工复核。4.2 Docker 一键部署与依赖锁定一键部署的核心是把 Python 环境、模型权重、界面代码全部封进镜像FROM python:3.10-slim WORKDIR /app RUN pip install --no-cache-dir ultralytics gradio opencv-python-headless COPY runs/medicine/exp01/weights/best.pt /app/model.pt COPY app.py /app/app.py EXPOSE 7860 CMD [python, app.py]构建命令docker build -t medicine-detect:v1 .运行命令docker run --gpus all -p 7860:7860 medicine-detect:v1。注意 opencv-python-headless 而不是完整版避免容器里缺 GUI 库报错。模型权重直接 COPY 进镜像不要挂载否则换机器容易路径错。如果要用 GPU基础镜像换成 nvidia/cuda 对应版本并确保宿主机驱动匹配。5. 避坑与常见问题排查5.1 训练 loss 正常但验证 mAP 极低现象训练集 box_loss 持续下降但验证集 mAP50 一直在 0.1 以下。原因通常是 data.yaml 里 train 和 val 路径写反或者验证集图片和标签不对应。解决手动打开 val 目录确认每张图都有同名 txt且 txt 里类别 id 在 names 范围内。另一个常见原因是标注时类别名大小写不一致转换脚本里被过滤掉了。5.2 模型在货架图上漏检严重现象单盒图检测正常货架密集图大量漏检。原因是训练集里货架场景占比太低模型没见过密集分布。解决补充货架场景样本到总数据的 40% 以上同时把 imgsz 提到 960conf 降到 0.3iou 降到 0.4。如果还不行开 copy_paste 增强把单盒实例粘贴到货架背景上合成训练数据。5.3 导出 ONNX 后推理结果和 PyTorch 不一致现象pt 模型检测正常ONNX 推理框偏移或类别错乱。原因多半是导出时 opset 版本和推理引擎不匹配或者预处理归一化方式不同。解决导出时固定 opset12推理时确保输入是 RGB、归一化到 0-1、尺寸和训练一致。用 onnxruntime 跑一遍和 pt 对比逐张图核对输出。5.4 界面部署后上传图片无响应现象Gradio 界面能打开上传图片后一直转圈。原因是容器内模型加载失败或显存不足。解决先看容器日志确认模型路径存在如果显存不够把 imgsz 从 960 降到 640或者换 yolov8n 权重。另外 server_name 必须设 0.0.0.0否则容器外访问不到。5.5 同类药盒误分类严重现象不同药品但包装相似的盒子被识别成同一类。原因是类别划分太粗或者 cls 损失权重太低。解决把相似包装的药品拆成独立类别增加类间样本差异训练时把 cls 从 0.5 提到 0.9推理时如果两类置信度接近输出 top-2 供人工确认不要强行取 top-1。6. 把药盒识别推到可用的最后一公里模型训练完、界面跑通不代表系统能用。最后一公里是推理后处理与业务规则结合。我一般会在检测结果上加三层过滤第一层是尺寸过滤药盒在图中宽高比通常在 0.3 到 3 之间超出范围的框直接丢弃能滤掉货架边缘的误检第二层是位置过滤如果检测框中心落在图片最上方 10% 区域多半是货架顶层标签不是药盒第三层是类别一致性过滤同一张图里如果同一类别出现超过 20 个框大概率是误检触发人工复核。验证方法上不要只看 mAP。准备一个 50 张图的真实测试集人工统计三个指标单盒召回率、货架场景召回率、误检率。单盒召回率低于 95% 说明模型容量不够或 imgsz 太低货架召回率低于 80% 说明密集场景训练不足误检率高于 5% 说明 conf 阈值太低或后处理太松。这三个指标比 mAP 更贴近业务。一个具体技巧把推理结果按置信度分三档处理。conf 大于 0.7 直接输出0.4 到 0.7 之间标记为“待确认”界面用黄色框低于 0.4 不显示。这样既保证高置信度结果直接可用又不会因为阈值太高漏掉遮挡盒。这个分档策略在药房盘点场景里比单一阈值实用得多。我自己踩过最深的坑是早期只追求 mAP忽略了货架场景的召回率结果模型在演示时翻车。后来养成习惯每次训练完先跑真实货架测试集看召回率再看 mAP。模型指标是给别人看的召回率才是给自己用的。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询