ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

YOLO11血液细胞检测实战:从数据集构建到模型部署全流程

YOLO11血液细胞检测实战:从数据集构建到模型部署全流程 简介面向医学影像分析与计算机视觉开发者这份资源以 Ultralytics YOLOv11 为检测框架提供一套完整的血细胞图像检测与辅助血液疾病诊断方案。数据集部分包含 364 张已标注血液细胞图像覆盖血小板、红细胞、白细胞等关键类别同时提供 YOLO 格式txt与 VOC 格式xml两套标签已完成训练、验证、测试集划分并附带 data.yaml可直接接入 YOLOv5/v8/v9/v10/v11/v12 等主流算法训练。包内还有训练好的模型权重、Python 推理脚本和详细使用教程便于快速复现检测效果整体 1854 个文件以文档、图像、标签、配置及脚本为主压缩包约 64.42MB。已有 93 人学习下载适合想要快速上手血细胞目标检测、构建辅助诊断原型的科研人员与算法工程师。1. 一张血涂片与一套权重为什么血液细胞检测总在等一个开箱即用的模型血液细胞形态学检查是血液疾病诊断的第一道关卡但绝大多数检验科和实验室至今仍在靠人工在显微镜下一个视野一个视野地数细胞。这个活儿不仅枯燥而且极度依赖操作者的经验不同染色批次、不同焦平面、细胞重叠严重的区域计数结果可能相差百分之二十以上。当检验量上来之后漏检和误判几乎不可避免。这就是 ultralytics-yolo11 这类目标检测模型介入的价值所在——用一套已经训练好的权重文件把红细胞、白细胞、血小板从复杂的血涂片背景中实时框出来辅助医生做初步筛查和计数统计。这个方向对于两类人特别有用一类是做医学影像 AI 的算法工程师手头有标注好的血细胞数据但不想从零开始训练一个检测器希望直接用 YOLO11 迁移学习快速出一个 baseline另一类是检验科或病理科的从业者想在工作流里引入自动化计数工具但缺乏深度学习工程经验需要一个开箱即用的数据集和模型来跑通闭环。本文不讲空泛的理论直接拆解如何把模型跑起来、数据集如何组织、训练参数怎么调以及实际落地时那些让人抓狂的边界问题。2. 把 YOLO11 拉起来跑通最小推理命令行与 python 两种姿势2.1 环境配置不玄学ultralytics 安装与权重文件放对位置ultralytics 这个库已经把 YOLO11 的训练、验证、导出、推理整个链路封装得很干净环境配置的门槛比早期 Darknet 版本低了一个数量级。前提是你的 Python 版本在 3.8 到 3.12 之间PyTorch 版本在 1.8 以上。这里强烈建议用 conda 新建一个独立环境不要和系统 Python 混在一起否则后面装 opencv 或者 cudatoolkit 时很容易把系统搞崩。conda create -n yolo11 python3.10 -y conda activate yolo11 # CPU 版本直接 pip 即可GPU 版本建议先装匹配的 torch 再装 ultralytics pip install ultralytics这段命令的逻辑是先用 conda 隔离环境再通过 pip 安装 ultralytics 主库。它会自动拉取 torch、opencv-python、pandas 等依赖但不会自动安装匹配你显卡型号的 CUDA 版 torch。如果你有 N 卡建议先去 PyTorch 官网用pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118这类命令装上 GPU 版再执行上面的pip install ultralytics否则默认装的是 CPU 版推理速度会很感人。权重文件放哪个目录有讲究。常见做法是在项目根目录下建一个weights文件夹把拿到的best.pt放进去然后通过相对路径引用。很多人第一次跑通失败不是代码问题而是权重文件路径写错或者没有解压到正确的层级。如果你拿到的是.zip压缩包解压后一定要确认best.pt是否直接可见有时候压缩包内层还套了一层文件夹导致路径多了一层。2.2 跑起第一个推理用 python 脚本预测并导出标注图当你拿到的是别人训练好的模型最关心的是这个模型能检测哪些类别以及在一张新图上效果如何。直接用 ultralytics 封装的 API 写一个推理脚本是验证模型可用性最快的方式。from ultralytics import YOLO # 加载预训练权重文件 # best.pt 是训练过程中在验证集上表现最好的模型权重 model YOLO(weights/best.pt) # 对单张血涂片图像进行推理 results model.predict( sourcesamples/test_001.jpg, conf0.25, # 置信度阈值低于该值的预测框会被丢弃 iou0.45, # NMS 交并比阈值控制重叠框的抑制力度 imgsz640, # 推理时输入网络的图像尺寸 saveTrue, # 保存标注后的结果图 projectruns/detect, nameexp_test, devicecuda # 可选 cuda/cpu无 GPU 时改为 cpu ) # 解析检测结果的类别、置信度与坐标 for result in results: boxes result.boxes if boxes is not None: cls boxes.cls.cpu().numpy().astype(int) conf boxes.conf.cpu().numpy() xyxy boxes.xyxy.cpu().numpy() names result.names for i in range(len(cls)): print(f{names[cls[i]]}: {conf[i]:.2f} at {xyxy[i]})这段代码的逻辑很直接先加载权重文件然后对输入图片做前向推理。conf和iou是两个最常调的推理参数需要重点说明。conf默认 0.25如果你的场景希望尽量把可疑细胞都框出来可以降到 0.1但代价是会冒出大量假阳性框如果追求高精度、只输出明确信号就调到 0.5 以上。iou控制非极大值抑制的严格程度血液细胞因为存在大量重叠形态建议保持 0.4 到 0.45过高会导致重叠细胞被合并成一个框过低则出现同一细胞被框两次。推理通过之后你就走通了整个 YOLO11 的最小链路。接下来真正决定模型上限的是数据集和训练策略这比推理本身复杂得多。3. 血液细胞数据集揭秘目录结构、LabelMe 标注与 YOLO 格式转换3.1 数据集目录长什么样images 和 labels 缺一不可无论你拿到的是自带数据集还是自主标注的数据都必须先把它整理成 YOLO 格式YOLO11 的训练器才会认账。YOLO 格式的数据集强制要求训练集和验证集分开且每张图片对应的标签文件是.txt文件名必须与图片文件名完全一致例如blood_001.jpg对应blood_001.txt。标签文件里每一行代表一个目标格式为class_id x_center y_center width height注意这四个坐标值全都是归一化到 0-1 之间的浮点数。以下是一个典型血细胞数据集的文件结构直接对照检查你的目录是否符合规范blood_cell_dataset/ ├── data.yaml # 数据集配置文件训练器靠它定位数据 ├── images/ │ ├── train/ │ │ ├── blood_001.jpg │ │ ├── blood_002.jpg │ │ └── ... │ └── val/ │ ├── blood_100.jpg │ └── ... └── labels/ ├── train/ │ ├── blood_001.txt │ ├── blood_002.txt │ └── ... └── val/ ├── blood_100.txt └── ...data.yaml是连接数据和模型的桥梁内容通常是下面这样。path是数据集根目录的绝对或相对路径train和val分别指向训练集和验证集的图片文件夹nc是类别数量names是每个类别的名称。血液细胞检测任务中最常见的是三类RBC 红细胞、WBC 白细胞、Platelets 血小板。如果有更多类别如嗜酸性粒细胞、淋巴细胞等按实际顺序填在 names 列表里即可。path: D:/blood_cell_dataset train: images/train val: images/val nc: 3 names: [RBC, WBC, Platelets]这里有一个很容易踩的坑path的路径分隔符。Windows 上用反斜杠有时会被转义建议统一用正斜杠或双反斜杠Linux 和 Mac 上则没有这个问题。另外train和val的值是相对于path的路径不是绝对路径不要混淆。3.2 踩过标注坑后的经验从 VOC/COCO 转 YOLO 格式的脚本很多人的标注数据可能来自 LabelMe 或 LabelImg导出的是 VOC 格式的 XML 文件里面记录的是xmin, ymin, xmax, ymax这种像素坐标。YOLO 不认这种格式所以需要写一个转换脚本。这里给出一段 Python 代码能把 VOC 的 XML 标注批量转换成 YOLO 的 TXT 标注。import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, output_dir, class_names): 将单个 VOC XML 标注转换为 YOLO 格式的 txt 文件 :param xml_path: XML 文件路径 :param output_dir: 输出 txt 的目录 :param class_names: 类别名称列表索引即 class_id tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size).find(width).text) img_h int(root.find(size).find(height).text) txt_name os.path.splitext(os.path.basename(xml_path))[0] .txt txt_path os.path.join(output_dir, txt_name) lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in class_names: continue # 跳过未在类别列表中的目标 class_id class_names.index(cls_name) bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) # 归一化到 [0, 1] x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h box_w (xmax - xmin) / img_w box_h (ymax - ymin) / img_h lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) with open(txt_path, w) as f: f.write(\n.join(lines)) # 使用示例 class_names [RBC, WBC, Platelets] voc_to_yolo(annotations/blood_001.xml, labels/train, class_names)这段代码的逻辑是先读取 XML 中的图片宽高再遍历所有 object 节点取出类别和边界框坐标。归一化过程是必须的重点在于所有数值都必须除以图片的原始宽高否则训练时模型会误以为坐标超出图像范围。输出时统一保留六位小数精度足够且文件体积小。动手写脚本时见过不少翻车现场最常见的问题是类别名称对不上XML 里写的是 red blood cell而class_names列表里是 RBC。建议在循环里先打印cls_name和class_id的映射确认没有漏项再批量执行。转换完成之后需要将images和labels目录按 9:1 的比例划分成train和val两部分确保验证集里不出现训练集的同名文件。4. 真正影响精度的模型训练策略参数、数据增强与验证集玄学4.1 训练命令的 hidden 参数imgsz、batch、patience 怎么设数据集准备好之后就该进入训练环节了。YOLO11 的训练常用命令是yolo train但把命令敲对只是基本功真正拉开模型精度差距的是对参数的理解。下面的命令是一个经过调优的血细胞检测任务基线看完之后逐项说明哪些参数是决定成败的关键。yolo train \ modelyolo11s.pt \ datablood_cell_dataset/data.yaml \ epochs150 \ imgsz640 \ batch16 \ workers4 \ optimizerauto \ patience50 \ projectruns/train \ nameblood_cell_v1 \ cacheTrue \ device0参数说明如下modelyolo11s.pt是预训练权重相比yolo11n拥有更强的特征提取能力又比yolo11x占用显存更少在血细胞这种中小目标场景上是性价比最高的选择。imgsz640是输入分辨率血细胞相对较小用过 1280 训练mAP 提升有限但训练时间翻倍性价比差。batch是显卡显存直接决定的参数如果训练时报CUDA out of memory第一件事就是把 batch 从 16 降到 8 或 4。patience50是早停机制的容忍轮数意思是验证集指标连续 50 个 epoch 没有提升就自动终止训练。这个参数极其重要因为它能帮你避免过拟合也节省时间。最后一个容易被忽略的是cacheTrue它会在训练前把整个数据集缓存到内存中显著减少磁盘 IO 等待前提是你的内存大于数据集大小。以下是另一个值得优先尝试的数据增强参数组合放在训练命令里能直接改善模型对染色差异的鲁棒性yolo train ... \ mosaic1.0 \ hsv_h0.02 \ hsv_s0.7 \ hsv_v0.5 \ degrees0.0 \ fliplr0.5血细胞涂片不像车辆、行人那样有明确的方向性所以degrees设为 0不做旋转增强水平翻转fliplr保持 0.5以两倍扩充样本量。hsv三项是色彩抖动参数血液样本因染色批次不同会有明显色差适当调大hsv_s和hsv_v能模拟出不同染色强度下的样本从而提升模型的泛化能力。4.2 验证与评估用混淆矩阵看红细胞和白细胞到底差在哪训练结束后不要急着部署先用验证集做一次系统性评估。运行如下命令可以把模型在验证集上的所有指标导出来yolo val \ modelruns/train/blood_cell_v1/weights/best.pt \ datablood_cell_dataset/data.yaml \ imgsz640 \ batch16 \ save_jsonTrue \ conf0.001这里把conf设成 0.001是为了在评估时尽可能低地放开阈值从而生成完整的 PR 曲线和混淆矩阵。评估完成后重点看results.csv里的几项指标mAP50是 IoU 阈值为 0.5 时的平均精度血细胞检测任务一般要求达到 0.9 以上才算可用mAP50-95更严格反映了定位精度通常达到 0.6 以上说明模型定位能力不错。还要重点检查confusion_matrix.png。在血液细胞这种不平衡数据集中红细胞数量往往远超白细胞和血小板模型极易偏向红细胞导致其它类别被忽略。如果在混淆矩阵中发现很多白细胞被误检为红细胞说明类别不均衡问题没有被数据增强解决此时应该在data.yaml里为每个类别增加权重或者用过采样策略复制小类目标样本让模型看到更多的白细胞实例。5. 常见问题排查细胞重叠、染色差异与小目标漏检的止血方案5.1 现象重叠细胞导致误检 —— 原因与 NMS 阈值调整现象是推理结果中两个紧挨着的白细胞被模型重复标注成一个大框或者重叠区域被错误框选为单个细胞导致计数不准。这是血液细胞检测里最隐蔽的问题因为细胞在涂片中天然就是密集排布的。原因有两个一是测试时的iou阈值设得太高非极大值抑制无法把重叠的大框分开二是训练阶段标注框不够紧实标注人员的标准偏移导致模型对边界框的回归很模糊。解决方向是在推理时先把iou从 0.45 下调到 0.35观察重叠区域是否被正确拆分为两个独立目标。如果拆分后的边界框依旧混乱就要回到数据集检查标注质量特别关注重叠区域是否有漏标或不精确的框。建议用一张细胞高密度图做针对性验证把conf和iou各设几组不同数值跑一遍网格测试找到当前模型最合适的阈值组合而不是盲目跟随默认值。5.2 现象染色差异导致换台显微镜就翻车 —— 归一化与色彩增强现象是同一套权重文件在 A 实验室的染色图集上效果很好在 B 实验室采集的图像上框出来的目标明显减少。这是典型的域偏移问题血液染色的色度、亮度受试剂品牌、染色时长、显微镜光源温度影响极大。原因很简单训练时模型把颜色当成了重要特征之一当测试图像的整体色调发生偏移时模型就难以激活对应的特征。解决方向是在训练阶段加强色彩抖动参数前面提到的hsv_h、hsv_s、hsv_v就是有效的止血手段将其调大到0.03、0.8、0.6能模拟更大范围的染色差异。此外在预处理阶段对输入图像做一次简单的标准化比如统一调整至 RGB 均值 0 方差 1也能降低不同设备的色彩差异。如果跨实验室的数据差异实在太大最可靠的方案是收集不同染色批次的少量样本加入训练集做微调哪怕每个批次只有几十张图都能有效缓解。5.3 现象训练从第一步就断开 —— 显存溢出与数据加载器崩溃现象是运行训练命令后几秒钟终端直接报CUDA out of memory或DataLoader worker (pid) is killed训练无法开始。前者一般是显存不够后者通常是内存不够或workers数设置过大。显存溢出的解决方向很明确将 batch 减半到 8如果你已经用了 8 还报错就再减半到 4同时把cache从True改为False并确认imgsz没有意外设置成 1280。数据加载器崩溃则和操作系统有关Windows 上workers4有时会触发安全限制先改成0如果训练能跑起来再逐步加大。这是血泪经验在 Windows 上默认workers0是免踩坑的保守做法。6. 最后一公里把模型封装成辅助诊断脚本并输出检验报告检测模型跑通后真正的落地价值不在于框出来而在于把框的坐标和类别转化为临床可用的统计指标。血常规检验最基础的指标包括红细胞计数、白细胞计数和血小板计数而辅助诊断的关键则在于计算白细胞分类比例。例如中性粒细胞比例显著升高常提示细菌感染淋巴细胞比例升高则可能与病毒感染相关。在已完成的模型推理脚本基础上加入对各类别目标的计数统计并按比例计算出白细胞分类指标脚本输出的结果就能直接给检验科医生做参考。代码实现如下from ultralytics import YOLO model YOLO(weights/best.pt) results model.predict(sourcesamples/pbmc_slide.jpg, conf0.35, iou0.4) # 统计各类别数量 cls_counts {RBC: 0, WBC: 0, Platelets: 0} for result in results: cls result.boxes.cls.cpu().numpy().astype(int) names result.names for c in cls: cls_counts[names[c]] 1 total_wbc cls_counts[WBC] lymphocytes 0 # 模拟淋巴细胞亚类检测实际项目中通常独立建模输出 # 此处仅示意统计逻辑 lymphocyte_ratio lymphocytes / total_wbc if total_wbc else 0 report f 血液涂片自动分析报告 ---------------------------------- 红细胞计数: {cls_counts[RBC]} 白细胞计数: {total_wbc} 血小板计数: {cls_counts[Platelets]} 淋巴细胞比例: {lymphocyte_ratio:.2%} ---------------------------------- 提示: 本报告由 YOLO11 模型自动生成仅供临床初筛参考。 print(report)这段代码的逻辑分两步先调用模型完成推理再遍历所有预测框的类别进行计数。这里要强调一个细节淋巴细胞比例的精确计算需要单独训练一个亚类分类模型因为通用血液细胞检测模型通常只输出 RBC、WBC、Platelets 三大类不会细分淋巴细胞、中性粒细胞等亚型。如果你拿到的数据集包含子类标注只需调整前面的data.yaml中names列表即可检测逻辑完全不需要改动。这几年做医疗影像落地的过程中最深的习惯是每到一个新场景先花一小时把 baseline 跑通再花一周把数据清洗干净最后才花时间去调参。很多人翻车的根源是拿到模型立刻就跑训练结果数据集里有成百上千个空标签文件或者标注框严重越界训练出来的模型自然不堪用。希望帮到你。本文还有配套的精品资源点击获取
返回列表