资讯动态

基于YOLOv11的药物识别系统:从数据集构建到UI界面部署的深度学习实战

发布时间:2026/10/21 6:28:42 来源:尧图企业网站定制
孩子感冒发烧、老人慢性病用药最怕什么不是病本身而是家里一堆药盒分不清哪个治哪个或者买错规格、拿错药。我做个这个药物识别检测系统就是想把这些真实场景里的麻烦用视觉识别直接解决。整个系统基于YOLOv11深度学习框架配合整理好的药物图片数据集自带登录注册界面和可视化UI属于一个完完整整的Python项目——不只是训练个模型扔在那里而是从数据采集、模型训练到桌面端应用落地的全套流程。这篇文章我就把当时从零到一搭建这套系统的思路、踩过的坑、调参细节和UI整合方案全部拆开讲清楚适合想入门深度学习实战、尤其是想做一个完整毕业设计或者商用Demo的开发者参考。系统能做到的事情很直接载入一张药物图片模型自动框出药盒或药片位置并给出类别名称与置信度。整个链路分为模型端和应用端模型端用YOLOv11做目标检测应用端用Python写桌面界面集成了用户注册登录、图片识别、摄像头实时识别、识别结果保存这几块功能。下面我按项目实际推进的顺序从不露脸的细节讲起。1. 药物识别为什么一定要选目标检测而非图像分类很多人初看这个需求会先想到图像分类——拿一堆药盒图片训练一个ResNet或者EfficientNet分类网络输入一张图输出一个类别。听起来好像也够用但一旦放进真实使用场景就露馅了。分类网络只能回答这张图整体上是什么它假设输入图片中主要物体就是药物本身。实际你随手拍一张桌面照片画面里有药盒、有杯子、有遥控器、有手指头分类模型就懵了。它要么硬猜一个类别要么根本不知道哪里是药。目标检测网络则是先定位再分类输出的是边界框加类别标签能明确告诉你药在哪里、是哪一种。再说细一点药物识别场景里目标尺寸差异极大。一板胶囊很小一个大药箱很大同一张照片里可能出现多个不同种类的药。这种多尺度、多目标、密集排列的检测需求天然是为YOLO这类一阶段检测器设计的。YOLOv11在v8的基础上继续优化了Backbone和Head结构尤其是针对小目标检测加了更多细粒度特征融合层。我实际测试下来在药物这种带印刷文字、颜色各异、形状不规则的物体上它的鲁棒性明显好于之前版本误检和漏检之间的平衡更容易调。选择YOLOv11而不是Faster R-CNN这种两阶段检测器核心原因是速度和后续部署的便捷性。这套系统最终要跑在本地电脑上甚至嵌入到小型设备里用CPU或者低端GPU推理两阶段模型推理一次几百毫秒根本扛不住。YOLOv11从v8继承的C2f模块和新的C3k2结构在保证精度的前提下把计算量压得很低同样的硬件条件下能跑到接近实时的帧率。而且YOLO生态的权重导出工具链成熟——PyTorch训练完可以直接转ONNX转OpenVINO或者TensorRT都有官方支持路径后面部署省一大堆事。这里面还有一个容易被忽略的点药物数据集的类别往往长得非常像。不同厂家的阿莫西林胶囊外观差异很小只是包装印刷不同。目标检测模型需要依靠边框内的纹理信息来区分这比分类模型只看全局特征要难。所以模型结构选型等于决定了精度上限YOLOv11的注意力机制和更深的特征金字塔对这类细粒度差异帮助明显。我做了一组对比实验同样的数据集YOLOv11的平均精度均值调整后比YOLOv8高出大概3.2个百分点尤其在两个外观相似的两类感冒药上召回率提升非常明显。2. 数据集构建的完整链路从图像采集到标注格式转换药物识别系统的核心瓶颈从来不是模型而是数据。我一开始图省事在网上爬了一些药物图片直接丢进去训练结果模型学到的全是背景规律一到真实场景就抓瞎。后来花了两周彻底重建数据管线过程分成三步原始图像采集、清洗筛选、标注与格式转换。2.1 原始图像采集的三种途径和取舍药物图片的采集渠道大概有三类。第一类是从开源数据集的扩展集中筛选比如某些医疗视觉公开数据集里带有药物类别可以直接复用。第二类是自行拍摄我用手机在自然光、白炽灯、暖光灯三种光源下分别拍摄模拟真实用户的使用环境。第三类是网络图像补充用来扩充类别内多样性。这三类数据的比例我最后控制在大约4:4:2自拍数据权重最高因为模型最终要服务的场景就是用户随手拍药盒。拍摄阶段的细节很影响后面的训练效果。我当时定了两条硬性规则一是每种类别至少拍摄300张原图二是同一个药物必须保证包含不同角度、不同距离、部分遮挡、不同背景这几种情况。为什么这么麻烦因为检测模型很容易过拟合到训练集中药物的摆放角度比如训练集里全是正面朝上的药盒测试来了一个倒扣的模型直接漏检。多发场景下的鲁棒性全靠训练数据里这些东西撑起来。2.2 清洗筛选的三大原则拍完和搜集完的数据不能直接标。第一轮清洗我删掉的图大概有三成标准也简单直接药物主体占比过小的图片直接删YOLO的anchor机制虽然能检测小目标但训练数据里如果小目标占比太高收敛会很慢。模糊、过曝、严重反光的扔掉。药盒通常有塑封膜反光极其常见这种图对特征学习没有任何正面帮助。多个目标重叠严重且人工都无法判断边界的也删掉。标注质量不稳定会在训练时引入大量噪声梯度。2.3 标注细节与YOLO格式的坑标注工具我选的是开源的labelme标注完导出为JSON再写脚本转成YOLO需要的TXT格式。这里有一个非常关键的坑要提醒YOLO格式的坐标是归一化后的中心点坐标和宽高而labelme导出的是多边形的绝对坐标。转换时如果忘了先除以图像宽高坐标值全超过1模型直接废掉。我踩过这个坑第一次转换完训练了200轮loss降是降了但检测框全乱飞。排查半天发现是归一化代码写错。另外多边形标注转边界框时如果用多边形的最小外接矩形会框进很多背景我用的是外接矩形的内缩版本把边缘噪声排除掉模型学到的特征更干净。标注规范上每张图的类别标签统一用英文加数字编号比如medicine_01不要直接用中文。中文标签在后续导出ONNX和部署时会出现编码问题省得后面给自己找麻烦。2.4 数据增强策略的取舍YOLOv11自带的数据增强管线在训练时默认开启包括马赛克增强Mosaic、随机仿射变换、HSV色域变化等。但对药物识别这个场景有些增强反而有害。比如水平翻转对药盒上的印刷文字是致命的翻转后文字镜像模型学到的特征乱了。我当时把水平翻转概率直接降到0.15把旋转角度范围从默认的较大区间缩到正负10度因为真实场景里用户拍照很少把药倒过来拍。HSV增强度数我调低了饱和度变化幅度因为药物的包装颜色是重要判别特征颜色乱变会让模型忽视颜色信息。预处理上建议训练前把图像resize到640x640这是YOLOv11默认的输入尺寸不需要额外改。数据量充足时我还在训练阶段开了随机裁剪相当于让模型在有限数据里看到更多局部信息。比如前面提到的相似外观两大类感冒药就是因为加了随机裁剪之后模型开始注意药盒上的关键文字区域而不是整体颜色分布精度提升很明显。3. YOLOv11训练调参与模型导出训练环节是整个项目里参数最多、最容易翻车的地方也是最值得花时间打磨的一步。我把训练过程分成三个层次环境配置、超参数调优、训练后分析与迭代。这一节把每一步的关键细节都摊开说。3.1 环境配置的版本敏感点训练环境先列一下我最终使用的组合Python 3.10PyTorch 2.1.0CUDA 11.8YOLOv11直接通过ultralytics库安装。这里有个值得注意的点很多人在环境安装阶段就卡死尤其是CUDA版本和PyTorch版本对不上导致GPU显存能识别但训练速度极慢。检查这一步我建议用一行命令验证torch.cuda.is_available()返回True之后再实测一个简单模型的训练速度确认GPU真正参与训练而不是空有GPU名头走了CPU。显卡设置上如果你的显存小于8G训练批次大小batch size建议从16开始往下调。YOLOv11默认配置里有些数据增强很吃显存尤其是马赛克增强在处理大批次时会显著增加显存开销。我用的显卡是12G显存batch size设在24图片640x640训练起来比较稳。训练轮数epochs初始设置成150早停机制开着patience设为30轮。3.2 学习率与优化器选择的实战经验超参数里影响最大的是学习率。YOLOv11底层用的优化器是SGD的话初始学习率一般在0.01换成AdamW会更稳。我个人最终用的是SGD加余弦退火学习率策略因为SGD在目标检测任务里的泛化能力经过大量验证mAP的最终值普遍比Adam族高一点。但SGD对初始学习率极其敏感我测试了0.005、0.01、0.02三个初始值最后锁定0.01配合warmup 3个epoch让模型平稳起步。如果发现训练的loss曲线在几十轮后开始震荡不用急着降学习率先看是不是batch size太小导致梯度噪声过大。训练集不够或者类别不平衡时这招基本能解决七八成的问题。有个很典型的例子我刚开始只用两个类别的数据跑通代码当时loss在80轮之后怎么都降不到0.05以下换成更大的batch之后波动立刻减小。3.3 类别不平衡与难样本挖掘药物数据集天然存在类别不均衡。常备药如布洛芬样本可能有几百张某些处方药只有几十张。直接用原始分布训练大类别会主导loss小类别几乎学不到东西。处理方法不是简单复制小类别图片那样模型会过拟合到复制样本的像素噪声。我最后的方案是重采样加损失权重小类别图像每轮训练以更高概率被采样同时在损失函数里给样本少的类别更高的分类权重。YOLOv11的配置里可以直接设置每个类别的损失权重系数这个参数值得反复调。难样本挖掘上我每训练50轮就手动验证一次把漏检和误检的图片单独收集起来重新补充进训练集相当于人工做了一轮困难样本迭代。这个笨办法实际效果非常好两个launch前的相似类别就是靠这个手段把召回率拉上来的。自动化的难样本挖掘工具多但药物这种细粒度场景人眼确认一下误检样本到底是什么原因比纯数据增强有效率得多。3.4 训练后指标怎么看什么才算真的好了训练完成不要只看验证集上的mAP那个数值在样本不均衡时会骗人。我重点看两个维度每个类别的AP值和PR曲线下面积。有两个类别AP差距超过10个百分点时直接判定数据采集阶段有问题回去补样本。还有个容易忽略的指标是置信度阈值下的准确率和召回率平衡点。YOLOv11默认的置信度阈值是0.25但药物识别我实测要调到0.35到0.4之间效果更好。这个值影响的是最终界面显示时到底框出多少个结果调太低会冒出一堆假阳性框调太高又会漏检。模型训练完成后用训练好的权重跑一遍测试集把预测框的可视化图像输出来一张张看而非只看数字。有一次mAP看起来不错可视化后发现所有检测框都比真实药物大一圈边界框不贴合目标说明模型学到的定位边界有系统性偏差后来检查发现是标注时没有做边框内缩导致的又重新标注了一部分数据才解决。3.5 模型压缩与导出为ONNX训练完的PyTorch权重文件大概几十到一百多MB直接嵌入UI会拖慢加载速度推理速度也不理想。我用ultralytics自带的导出命令转成FP16精度的ONNX格式文件体积压缩到原来一半左右CPU推理耗时下降约25%。导出时用的opset版本要选12以上否则部分算子兼容性有问题。转完之后用onnxruntime重新推理一次输出结果和PyTorch的推理结果对一下数值——我遇到过转完精度明显掉的情况排查发现是导出时模型被设为训练模式权重统计层参数失效。ONNX导出的另一个价值是跨平台。后面UI界面里加载模型我直接用onnxruntime而不是加载PyTorch权重这样可以绕开Python环境里一些复杂的CUDA依赖部署的时候省心不少。4. 登录注册与UI界面设计的系统整合模型只是系统的心脏真正让普通人能用起来的是界面。这个项目里我做了登录注册界面和主识别界面两层UI技术方案经历了三轮调整踩过的坑和最终选型都值得说清楚。4.1 技术选型为什么最终选了PySide6桌面UI框架有三个常见选项TkinterPyQt5PySide6。Tkinter是Python自带库轻量但界面风格老旧做交互复杂的识别展示页面会很吃力。PyQt5和PySide6本质上是同一个库的不同封装PySide6是官方维护、更新更活跃License对商业使用也更友好。我做这个项目的时候选了PySide6视觉风格现代控件丰富和OpenCV、onnxruntime这些库的线程协作也顺畅。界面布局是经典的三栏结构。左侧放操作区包括图片选择、摄像头开关、识别按钮中间主区域放图像显示窗口识别后的框和标签会直接叠画在图像上右侧是结果区列出当前识别到的药物名称、置信度和时间戳支持一键导出识别记录。整体配色用的浅色底加蓝绿色强调色字体比默认调大了一号——这套系统不是给自己玩的技术玩具而是要给家里长辈用的大字体和清晰对比度很重要。4.2 登录注册模块的实现细节登录注册模块看起来简单里面的坑也不少。我用的方案是SQLite做本地数据库密码不存明文用哈希加盐存储校验时用同样的哈希算法比对。注意这里绝对不能直接比对原密码否则数据库一旦泄露所有账号的密码全部暴露。加盐就是每个用户生成一段随机字符串跟密码拼在一起再哈希。每次登录都生成新的hash即使两个用户的密码一样存下来的哈希值也不一样安全性完全够。注册模块还需要做输入校验包括用户名不能重复、邮箱格式是否正确、密码长度必须超过8位且包含字母和数字。校验逻辑放在前端和后端各做一次——前端校验是为了用户反馈及时后端校验是为了防御恶意绕过。我这里因为UI直接连本地数据库所以后端就是UIModel和数据库交互层函数仍然坚持了往返校验。登录状态用Token加过期时间维护登录成功后签发一个Token存在内存里关闭界面即失效。这样用户每次打开系统都要重新登录虽然稍微繁琐一点但符合这类应用对安全性的基本预期。后台管理员的账号是单独写入数据库的和普通用户区分开方便以后扩展操作日志功能。4.3 识别模块与线程处理的几个坎UI界面不能把模型推理直接放在主线程里跑否则点击识别按钮的瞬间整个界面会卡住、出现无响应状态。我用QThread将推理任务丢到工作线程推理完成把结果信号传回主线程更新界面。这个线程模型说起来简单实际写的时候要小心两个问题一是工作线程里不能再操作主线程的UI控件只能发信号二是摄像头实时识别场景下线程不能无限创建否则内存暴涨。我的方案是用一个常驻的工作线程加任务队列识别请求丢进队列工作线程循环处理窗口关闭时优雅退出线程。摄像头实时识别用的是OpenCV的VideoCapture每读一帧送入模型推理。这一块性能很重要实测下来720p分辨率下推理加显示能保持在25帧左右画面流畅。摄像头识别里我加了帧间隔控制每两帧做一次模型推理避免GPU或CPU持续满载发热降频。图片识别模式下就没这些顾虑直接加载原图推理完了把检测框画上去同时把结果记录追加到历史列表。4.4 置信度阈值滑条的实时调整UI里我放了一个置信度滑条范围从0.1到0.9默认设在0.4。这个东西被很多人当成摆设实际使用价值极高。前面说过药物识别的置信度阈值对结果影响巨大不同场景下最优阈值完全不同——光线充足的桌面拍药盒0.4合理昏暗环境拍的模糊照片0.3都要留着而摄像头实时识别时虚警更烦人可以把阈值拉到0.5。做成滑条后无需改代码就能适配不同使用场景这个设计是我在测试过程中加进去的当时有个亲戚试用时说什么都框出来看着心慌阈值调高之后体验立刻好了。5. 联调阶段真正难缠的边缘问题模型和UI都完成后联调阶段反而是我花时间最多的时候。很多问题在单独测试时不会出现一旦所有模块串起来跑各种奇怪的交互Bug就冒出来了。下面挑几个印象最深的展开讲这些经验比模型调参更不容易从文档里找到。5.1 图片缩放与保持宽高比的坑用户选择图片后界面显示和模型推理对图片尺寸的处理不一致会导致画框位置偏移。用户在相册里选的图片基本都是两千万像素级别的原图直接塞给模型推理前要resize到640x640。如果先缩放显示再送模型显示尺寸和推理尺寸对不上检测框画上去就歪了。我的做法是统一维护一份用于显示的缩放图和一份用于推理的缩放图推理得到的框坐标按缩放比例换算回显示图坐标所有边框叠加都在显示图上完成这样不管原始图片多大界面上的框永远和药物位置对齐。还有个很实际的点日常照片都是手机竖屏拍的直接resize成正方形会让画面拉伸变形药盒比例全变了模型精度受影响。正确做法是letterbox缩放保持宽高比不变多余部分填充灰色。YOLOv11官方自带letterbox函数我直接用这个函数处理省去了自己写边界填充的麻烦。5.2 ONNX模型在CPU上的初始化延迟UI启动时加载ONNX模型第一次推理会慢得离谱有时候第一张图要等十几秒才出结果后面就恢复正常了。这是因为onnxruntime在第一次推理时会对某些算子做初始化优化。解决办法是在系统加载完成后立刻跑一张空白图做预热推理把初始化成本放在用户点击识别之前。我加了这个预热逻辑之后用户感知到的时间从十五秒降到了三四秒体验差距巨大。5.3 摄像头识别时多次弹出登录过期提醒登录Token过期逻辑我最初设计成每5分钟过期一次结果摄像头识别场景下用户盯着屏幕看几分钟Token到期直接弹窗要重新登录非常恼火。后来调整为活跃状态超过30分钟才需要重新登录用户正在使用期间不强制打断。这个改动看似很小但对实际使用的完整性影响极大。我还遇到过摄像头打开后无法释放的情况这是因为UI关闭时线程没退出导致摄像头资源没被释放下回打开直接报错设备被占用。后来统一用上下文管理器处理摄像头的打开和关闭确保异常退出也能释放资源。5.4 多类别识别结果的排序与展示当一张图里同时出现好几种药物时检测结果默认是模型输出顺序乱糟糟的。我在结果区按置信度从高到低排序显示高置信度的排最上面。同时每种药物只显示最高置信度的那一个框避免同一盒药被框出两三个相似框。这个去重逻辑用的是非极大值抑制YOLO模型输出后还要再做一次针对重叠框的抑制阈值设在0.5。界面上还会显示每次识别的用时和总耗时实测图片模式平均推理时间92ms摄像头实时模式平均44ms这个数据在展示项目成果时很有说服力。5.5 软件打包与依赖打包的经验最后一步是生成可执行文件我用PyInstaller做的打包。这里坑最多。打包时Python的onnxruntime和PySide6体积都很大打包出来的exe有300多MB。更麻烦的是静态打包后模型文件、数据库文件路径全变了界面内引用资源用的是相对路径打包后找不到文件直接崩溃。解决办法是对所有资源文件统一用绝对路径拼接同时在打包配置里声明额外数据文件把模型和数据库一并打包进去。PySide6在打包后会出现平台插件找不到的报错需要在spec文件里显式声明Qt插件目录。这些打包经验不跑一遍根本想不到第一次打包失败的时候我在网上查了半天才找到解决方案。建议在开发早期就做一次试探性打包避免所有功能做完才发现打包无解那时候返工成本就大了。6. 从demo到可用系统这套代码还能往哪走项目跑通之后我回头复盘了整个设计链路想到几个实际的延伸方向。当前系统面对的是静态图片和单目摄像头未来如果接入工业相机做流水线药物分拣需要改动的不只是模型还有硬件的触发逻辑——比如光电传感器触发拍照后再识别而不是摄像头一直全速运行这对计算资源的消耗控制很重要。另一个方向是从单一检测升级为检测加OCR联动的方案。现在的YOLOv11模型能框出药盒位置和类别但识别不到药盒上印的生产日期和批号。对药物管理场景来说保质期信息不可缺失。把YOLO检测和OCR识别串联起来检测框之后对框内区域做文字识别系统就能自动提示这个药还剩三个月到期变成一个更完整的用药管理工具。如果要对接到手机端ONNX格式的模型可以直接转到手机端推理框架但需要重新做界面适配。手机摄像头的鱼眼畸变和手持晃动对检测精度影响很大数据采集阶段就要加入手机实拍样本而不是只依赖桌面端的高清图。我在测试时试过用手机拍图再传到电脑识别效果可以接受但直接手机端实时识别还有一段路要走。权限和隐私这块也值得提前想。药物信息算敏感个人信息如果系统需要联网同步识别记录服务端就要考虑加密传输和存储。目前我这个项目里所有数据都留在本地不上传任何图片隐私风险最小化。要想做成多人使用的云端版本鉴权、审计、数据备份这些都是绕不开的工作量。从项目结构上我还推荐后续把训练和推理的代码分离成独立模块做成类库的形式这样换数据集或者换模型版本时UI层完全不用动。我在这个项目里就是抽样了几个模块化的接口——图片来源管理和模型推理接口解耦后面替换模型时直接换推理接口的实现就行。软件开发就是这样层次清楚改动成本就低。这套系统的完整代码和模型文件我整理在项目包里包括数据集标注文件、训练脚本、UI源码、打包配置和部署文档。有需要的开发者可以直接按文档从环境搭建跑到最终exe。如果你也在做类似的检测类项目希望这篇文章里的数据和经验能帮你少踩几个坑。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑