☰
血细胞检测数据集VOC/COCO/YOLO标签与YOLOv8训练实践
2026/9/28 16:33:07 网站建设 项目流程

简介:面向医学影像与目标检测学习者的YOLO红白细胞血小板检测数据集,包含一千张真实场景下的高质量血液细胞图片,数据场景丰富,并配有VOC、COCO、YOLO三种格式的标注文件,标注框质量高,可直接用于YOLO系列目标检测模型的训练、验证与算法研究。压缩包内共两千个文件,以一千个XML和九百九十个TXT标注文件为主体,另配环境搭建教程、训练教程、三个数据集划分脚本及一个YAML配置文件,整体大小约二十九点三四兆,便于快速下载与本地部署。随包教程同时覆盖Windows与Linux环境,读者可参考案例修改后训练自己的数据集;划分脚本支持训练集、验证集、测试集的自由切分,并生成ImageSets记录文件,从环境配置到数据划分都有清晰指引,大幅减少手动整理标注的工作量。目前已有一百九十一人学习或浏览,适合课程设计、科研实验以及需要真实医学图像支撑的YOLO入门与进阶开发者。

1. 为什么血细胞检测数据集要同时给 VOC、COCO 和 YOLO 三种标签

做医学影像目标检测的同行应该都有过这种体验:好不容易在公开渠道找到一个血细胞相关数据集,下载下来发现只有一种标注格式,想用 YOLO 训练就得自己写脚本转换,转完还要担心坐标对不上、类别错位、训练集和验证集里有重复图。而标题里这个 YOLO 红白细胞血小板检测数据集,把 1000 张血液涂片图像和 VOC、COCO、YOLO 三种标签一并放入,外加划分脚本和训练教程,本质上解决的正是“拿到图之后还要折腾两三天才能开始跑模型”这个痛点。

这个数据集面向的是目标检测方向的血细胞形态学分析,典型检测对象是白细胞(WBC)、红细胞(RBC)和血小板(Platelets)三类。1000 张图对医学图像任务来说不算大,但配合三种标签格式和划分脚本,足够支撑你把一套 YOLO 血细胞检测流程从数据准备一直跑到验证集 mAP 输出。无论你用的是 YOLOv5、YOLOv8 还是以后推出的新版本,统一入口都是“先按格式拿到 labels,再套训练模板”。接下来我把三种格式的标签逻辑、划分脚本的用法、训练流程和踩坑点按顺序拆开讲。

2. 三种标注格式的底层逻辑:VOC、COCO、YOLO 各自该存什么

先说结论:VOC 格式是给“人读”的,COCO 格式是给“评价”的,YOLO 格式是给“训练”的。这套数据集把三种格式都配好,意味着你不管从哪个框架切入,都能直接进入训练环节,不用自己在格式之间反复横跳。

2.1 VOC 格式的 XML 结构:一张图一个文件

VOC 格式的标签是 XML 文件,一张图对应一个同名 XML。打开一个血细胞样本的 XML,核心内容长这样:

<annotation> <folder>JPEGImages</folder> <filename>blood_001.jpg</filename> <size> <width>640</width> <height>480</height> <depth>3</depth> </size> <object> <name>RBC</name> <bndbox> <xmin>180</xmin> <ymin>220</ymin> <xmax>280</xmax> <ymax>320</ymax> </bndbox> </object> <object> <name>WBC</name> <bndbox> <xmin>400</xmin> <ymin>100</ymin> <xmax>460</xmax> <ymax>160</ymax> </bndbox> </object> </annotation>

每一个<object>代表一个目标框,name是类别名,bndbox里四个值是左上角和右下角的像素坐标。注意这个坐标体系是 0 基索引,和 OpenCV 读取图像时的像素坐标一致,转换格式时不需要额外减 1。

如果你打算自己写转换脚本,最常犯的错是把xmin/ymin/xmax/ymax当成中心坐标去处理。VOC 的语义就是“绝对坐标的左上右下”,没有任何归一化成分,转换到 YOLO 时要做一次除法运算,直接套公式即可,后面会给出代码。

2.2 COCO 格式的 JSON:为了跑训练和评估

COCO 格式的标签集中在单个 JSON 文件里,三个关键字段是images、annotations和categories。images记录每张图的 id、文件名、宽高;annotations记录每个目标框属于哪张图、类别 id 是什么、bbox 的[x, y, width, height];categories做类别 id 与名称的映射。

在血细胞数据集里,categories 一般是:

[{"id": 1, "name": "WBC"}, {"id": 2, "name": "RBC"}, {"id": 3, "name": "Platelets"}]

注意 COCO 的 bbox 和 VOC 不同:[x, y, width, height]不是[xmin, ymin, xmax, ymax],坐标换过去时需要做一次width = xmax - xmin、height = ymax - ymin。如果你从 COCO 的 JSON 转 YOLO txt,还需要注意 COCO 的 bbox 坐标可能是 float 类型,而 VOC 的 XML 里通常是 int,直接强转会导致目标框偏移 1 到 2 个像素,影响小目标检测。

2.3 YOLO 格式的 txt:归一化的中心点与宽高

YOLO 的训练标签是一个 txt 文件对应一张图,每行格式是:

class_id cx cy w h

其中cx、cy是归一化后的目标中心坐标,w、h是归一化后的宽高,取值范围都在 0 到 1 之间。以 blood_001.jpg 的第一行假设为1 0.359375 0.562500 0.156250 0.208333,含义就是 RBC 类,中心在图的横向 35.94%、纵向 56.25% 的位置,宽度占全图的 15.63%,高度占 20.83%。

YOLO 格式之所以选择归一化,是因为训练时输入图片会被缩放到固定尺寸(比如 640x640),归一化坐标不随原始图像尺寸变化,模型读取标签时不需要关心原图是 640x480 还是 1920x1080。

2.4 三种格式互相转换:最小可用脚本

拿到三种格式的标签,多数场景下还是需要在它们之间互转。常见做法是写一个 Python 脚本统一处理。下面是一个从 VOC XML 转 YOLO txt 的最小实现,血细胞数据集里如果只给你 VOC 和 YOLO 两种,你也能靠它补出 COCO:

import xml.etree.ElementTree as ET class_map = {"WBC": 0, "RBC": 1, "Platelets": 2} def voc_xml_to_yolo_txt(xml_path, txt_path): tree = ET.parse(xml_path) root = tree.getroot() width = int(root.find("size/width").text) height = int(root.find("size/height").text) lines = [] for obj in root.iter("object"): name = obj.find("name").text if name not in class_map: continue box = obj.find("bndbox") xmin = float(box.find("xmin").text) ymin = float(box.find("ymin").text) xmax = float(box.find("xmax").text) ymax = float(box.find("ymax").text) cx = (xmin + xmax) / 2.0 / width cy = (ymin + ymax) / 2.0 / height w = (xmax - xmin) / width h = (ymax - ymin) / height lines.append(f"{class_map[name]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}") with open(txt_path, "w") as f: f.write("\n".join(lines)) # 用法示例:转换单张图的标注 voc_xml_to_yolo_txt("Annotations/blood_001.xml", "labels/blood_001.txt")

这段代码的逻辑很直白:先解析 XML 里的图像宽高,再把每个 object 的xmin/ymin/xmax/ymax做两次运算,一次求中心点,一次求宽高,最后统一除以图像宽高完成归一化。参数说明里有两点值得注意。class_map的 id 要和训练配置里的names顺序严格对齐,否则模型预测出的类别全是乱的。另外我特意用了float(box.find(...).text)而不是int,防止 XML 里出现浮点坐标时被截断,这在从标注工具导出时很常见,直接 int 会把小数部分丢掉,导致框偏移。

3. 用划分脚本拆出训练集、验证集和测试集:为什么要按 8:1:1 来分

数据集拿到手里,第一件事不是训练,而是划分。标题里的划分脚本承担的就是这个工作。一个合格的划分脚本要把 images 和对应的 labels 按比例拆成 train、val、test 三个子集,并且保证每张图和它的标签文件一一对应,不会出现训练集有图没标签、验证集有标签没图的情况。

3.1 划分比例的选择逻辑

1000 张图的规模下,我通常按 8:1:1 划分,也就是 800 张训练、100 张验证、100 张测试。这个比例的依据很直接:训练集太少,模型见不到足够的血细胞形态,红细胞和血小板这类小目标学不出稳定的特征;验证集太少,早停和超参数调整的置信度不够,100 张验证图足够算出波动可控的 mAP;测试集只用来做最终评估,100 张图已经能暴露类别层面的明显漏检。

如果你的目标并不是模型竞赛,而是要把模型用于实际检测场景,建议从 1000 张里多留一点做测试,比如 700 训练、150 验证、150 测试。因为血细胞检测的最终衡量标准是“没见过的血液涂片上能不能找到三类细胞”,测试集越接近真实分布,最终效果判断越靠谱。划分脚本里通常能改比例参数,我就按常见做法来设计。

3.2 一个不依赖第三方库的划分脚本

划分脚本一般是 Python 文件,核心操作是三件事:读取所有图片文件名、随机打乱、按比例复制到不同目录。下面这段代码可以直接跑:

import os import random import shutil random.seed(42) image_dir = "images" # 原始图片目录 label_dir = "labels" # 原始标签目录,YOLO 格式的 txt train_dir = "train" val_dir = "val" test_dir = "test" train_ratio = 0.8 val_ratio = 0.1 images = [f for f in os.listdir(image_dir) if f.endswith((".jpg", ".png", ".jpeg"))] random.shuffle(images) train_count = int(len(images) * train_ratio) val_count = int(len(images) * val_ratio) train_set = images[:train_count] val_set = images[train_count:train_count + val_count] test_set = images[train_count + val_count:] for subset, subset_name in [(train_set, train_dir), (val_set, val_dir), (test_set, test_dir)]: os.makedirs(f"{subset_name}/images", exist_ok=True) os.makedirs(f"{subset_name}/labels", exist_ok=True) for img_name in subset: src_img = os.path.join(image_dir, img_name) dst_img = os.path.join(f"{subset_name}/images", img_name) shutil.copy(src_img, dst_img) label_name = os.path.splitext(img_name)[0] + ".txt" src_lbl = os.path.join(label_dir, label_name) dst_lbl = os.path.join(f"{subset_name}/labels", label_name) if os.path.exists(src_lbl): shutil.copy(src_lbl, dst_lbl) else: print(f"警告: {label_name} 不存在,跳过")

关键点有三个。一是random.seed(42),固定随机种子保证每次运行划分结果完全一致,这很重要——跑训练发现效果不对时,你需要能复现同一个划分来做对照实验。二是用shutil.copy而不是move,保留原始目录不动,划分出错了随时能重来,这个习惯能给你留一条后悔药。三是检查标签文件存在性,有些图像可能没有对应的 txt 文件,直接跳过而不是报错中断,后面单独排查。

提示:如果你拿到的是 VOC 或 COCO 格式标签,划分前先全部转换成 YOLO txt,再跑这个脚本。因为 YOLO 训练框架读取标签时默认每个 txt 和图片在同一目录树结构下,转完再划分最省事。

3.3 划分后立刻验证两件事

划分脚本跑完后,不要急着开始训练,先检查两个文件。第一个是 train.txt 或你的数据配置文件中引用的路径是否真实存在。第二个是统计一下三类目标在训练集、验证集、测试集里的数量分布。血细胞数据里最常见的问题是:原始数据按文件夹整理时已经隐含了某种顺序,比如前面 300 张全是红细胞密集的图像,后面 300 张才有白细胞和血小板,随机打乱时如果随机种子设置不当,可能导致某个类别在验证集里数量为零,训练过程不报错,但 mAP 曲线会跳得让人怀疑人生。

简单统计类别分布的方法是把所有训练集 txt 读一遍,统计每行第一个数字出现的次数。这个动作很轻量,但能挡掉一大半后续排查时间。

3.4 对病人级数据要额外注意的划分方式

血细胞检测有一个容易被忽略的坑:如果同一个病人的血液涂片图像同时出现在训练集和测试集,模型实际上见过这个病人的细胞形态,测试结果会虚高。正规做法是按病人或涂片来源做组级划分,而不是单纯按图片随机划分。标题里提到的 1000 张血细胞图如果来自多个不同病人,随机划分会让验证 mAP 虚高至少 5 到 10 个点。具体做法是给每张图片的文件名加上病人 id 前缀,划分时按前缀分组,确保同一个病人的所有图都进同一个子集。

这份数据集的划分脚本如果没做病人级隔离,你可以在自己复现时加一层分组逻辑。做法是把images列表先按文件名前缀分组再随机分到 train、val、test,这样更贴近医学影像任务的真实评估需求。

4. 用分割后的数据集训一个 YOLO 血细胞检测模型:从 data.yaml 到训练命令

划分完成后,数据集结构长这样:

blood_dataset/ ├── train/ │ ├── images/ │ │ ├── blood_001.jpg │ │ └── ... │ └── labels/ │ ├── blood_001.txt │ └── ... ├── val/ ├── test/ └── data.yaml

接下来要做的,是把这段结构写进 YOLO 的配置文件,然后选一个合适的预训练权重开始训练。

4.1 血细胞场景下选择哪个 YOLO 分支

标题写的是 YOLO,没有限定版本,我一般会建议按你现在手头环境选。YOLOv5 的生态成熟,部署资料多,数据增强策略稳定;YOLOv8 在检测头细节上做了不少调整,训练出的模型在小目标召回上通常更好一点,而且命令行工具统一,一条命令就能训练。血细胞检测这个任务,三类目标的尺度差异很明显,红细胞较大且密集,血小板偏小且稀疏,属于典型的小目标夹杂常规目标场景。

如果你从零开始,我建议直接上 YOLOv8,因为它的默认配置里对小目标更友好的训练策略,减少了你手动调 anchor 的负担。当然,如果你要部署到 Jetson 之类的嵌入式设备,那 YOLOv5 的 C++ 部署链更顺手,选型就看落地环境。

4.2 写 data.yaml:路径、类别数和类别名

YOLO 训练的第一步是写 data.yaml。一个血细胞检测的 data.yaml 配置如下:

path: blood_dataset train: train/images val: val/images test: test/images nc: 3 names: 0: WBC 1: RBC 2: Platelets

path是数据集根目录的绝对路径或相对路径,注意 YOLOv8 默认以当前工作目录解析相对路径,如果你的终端不是在 blood_dataset 的上一级目录启动,路径会直接解析失败,最常见的报错是Train error: dataset not found。train和val填的都是 images 目录的相对路径,框架会自动在同一级找 labels 目录,所以不要在这里写 labels 路径。

names的类别顺序和之前提到的class_map必须完全一致。转换标签时如果把 WBC 放到了 id 0,这里 names 的 0 就必须是 WBC,顺序错一个全盘皆错。

4.3 训练命令与关键超参数:epochs、batch、imgsz

用 YOLOv8 训练血细胞检测模型的完整命令:

yolo detect train \ data=data.yaml \ model=yolov8n.pt \ epochs=150 \ batch=16 \ imgsz=640 \ patience=20 \ project=runs \ name=blood_cell_exp

命令里的model=yolov8n.pt是让框架自动下载 YOLOv8 的 nano 预训练模型参数并加载到模型里。nano 模型只有 3.2M 左右参数量,在血细胞这种目标尺度不算极端的场景下够用。如果你的 GPU 显存有 12G 以上,可以换成yolov8s.pt,精度会有提升但训练时间差不多翻倍。1000 张图的规模很小,不建议直接上 yolov8l 或 yolov8x,训练集不足以支撑大模型收敛,反而容易过拟合。预训练模型下载需要联网,如果网络受限,可以手动下载权重文件放到 YOLO 的权重目录再引用本地路径。

epochs=150是基于 1000 张图的经验值。医学图像检测通常收敛得比自然图像慢,150 轮能让 loss 曲线充分走平。batch=16和imgsz=640的组合决定了显存占用,我实测在 8G 显存的卡上正好能跑,如果训练中报 CUDA out of memory,优先把 batch 降到 8,然后才是降低 imgsz 到 512。

patience=20是早停策略,如果验证集 loss 连续 20 轮没有降低,训练会自动终止。对小数据集来说这个参数很关键,因为模型跑到第 80 轮可能就过拟合了,没有早停会白白多跑 70 轮浪费时间。

4.4 训练过程中观察什么:loss 曲线和验证指标

训练日志里需要盯三个指标:box_loss、cls_loss、val_mAP50。box_loss 是边界框回归损失,血细胞检测里它的下降速度一般比较快,前 30 轮能降一半;cls_loss 是分类损失,三类细胞的形态差异大,分类问题本身不困难,它降得慢的话说明类别顺序配置有问题。val_mAP50 是验证集上 IoU 阈值为 0.5 时的平均精度,这个值在 0.7 以上基本就能用了。

训练完成后,权重文件在runs/blood_cell_exp/weights/目录下,一个是best.pt,一个是last.pt。best.pt 是验证集上 mAP 最高的权重,last.pt 是最后一轮权重。经验上如果两者差距超过 2 个 mAP 点,说明早停起作用了,用 best.pt 做后续测试准没错。

5. 训练血细胞检测数据集避坑:5 个最容易翻车的地方

这部分写全流程里最容易出问题的环节。每条都是“现象 → 原因 → 解决”的结构,给你一套可以直接对号入座的排查思路。

5.1 血小板目标频繁漏检,验证集 mAP50 高但 mAP50-95 惨淡

现象:训练完成后,红细胞的检测框很干净,白细胞也能框出来,但血小板在每张图上都漏掉三分之一以上,尤其是在血小板密度高的区域,模型宁可少框也不碰。

原因:血小板在 640x640 的输入尺寸下平均只有 20 到 30 个像素见方,属于典型小目标。YOLOv8 的默认 anchor 在 640 尺度下对 32 像素以下的目标响应很弱,模型学不出血小板的有效特征。mAP50-95 要求 IoU 从 0.5 到 0.95 连续计算,小目标的 IoU 本身就难达到 0.5 以上,所以整体拉低。

解决:第一尝试把imgsz从 640 提到 960,目标在特征图上的像素面积能扩大约 2.25 倍,小目标召回率会有明显提升,代价是显存占用增加。你可以把训练命令里的imgsz=640改成imgsz=960。第二是只对血小板类别使用更强的数据增强,比如在训练过程中对血小板目标做随机复制粘贴。第三是换用 P2 检测头或增加一层小目标检测分支,这个改动较大,适合在调参无效后再做。

5.2 类别不平衡:红细胞占了大半标注框

现象:训练日志里的 cls_loss 降得很低,但混淆矩阵里白细胞被误检成红细胞的案例特别多。查看 labels 分布后,训练集里红细胞框的数量是白细胞的 10 倍以上。

原因:血液涂片里红细胞天然数量远多于白细胞和血小板,这是数据分布本身决定的。模型在类别预测时被红细胞的大量样本带偏,倾向于把不确定的区域判成红细胞。

解决:不要试图用删红细胞框的方式来平衡这种数据,删完信息量损失太大。常见做法是保持原始分布,训练后只看每个类别的 per-class AP,不要总 mAP 一锤定音。另外,对 WBC 类使用 mOSAIC 增强时注意别把同一个白细胞切碎,增强噪声过多会让本来就稀疏的类别学得更差。如果确实需要类别平衡,用复制少数类样本的方式比删减多数类更稳妥。

5.3 标签坐标越界或宽高为 0,训练直接崩

现象:训练跑到第 3 轮,loss 突然变成nan,或者训练进程直接报错退出。翻看标签文件时发现,某一行 txt 里的w或h是负数或大于 1。

原因:VOC 转 YOLO 时,如果原始 XML 里 xmax 和 xmin 相等,或标注框超出了图像边界,归一化后就会得到 0 或负数宽高。这类坏标签在血细胞数据里不少见,因为红细胞紧挨在一起,标注员复制框时经常出现边界重合,有些标注工具还会导出负坐标。

解决:训练前做一次标签清洗,逐行检查每个 txt,把宽高小于 1e-6、坐标超出 [0, 1] 范围的样本过滤掉或直接丢弃。快速清洗代码:

import os label_dir = "labels" bad_count = 0 for label_file in os.listdir(label_dir): if not label_file.endswith(".txt"): continue path = os.path.join(label_dir, label_file) valid_lines = [] with open(path, "r") as f: for line in f: parts = line.strip().split() if len(parts) != 5: continue _, cx, cy, w, h = parts cx, cy, w, h = float(cx), float(cy), float(w), float(h) if w <= 0 or h <= 0 or not (0 <= cx <= 1 and 0 <= cy <= 1): bad_count += 1 continue valid_lines.append(line.strip()) with open(path, "w") as f: f.write("\n".join(valid_lines)) print(f"清理了 {bad_count} 行异常标签")

这段代码遍历 labels 目录下每个 txt,过滤掉宽高非正数、中心点超出归一化范围的标签行。如果一张图的所有标签都被过滤掉,对应的 txt 会变成空文件,这也是个隐患,最好顺手把空文件对应的图片从数据集里移除。

5.4 训练过程中 BN 崩溃:loss 跑到一半变 NaN

现象:训练到 30 轮左右时,loss 突然跳到nan,并且后续所有 batch 的 loss 都是nan。模型输出变成一片黑或一片花框。这个现象在血细胞数据上出现频率不低。

原因:批量归一化层的统计量在训练中期被某个异常 batch 污染。血细胞图像目标和背景对比度差异巨大,个别 batch 里全是纯背景切片时,BN 计算出的均值方差会出现极端值,后续再回不来。

解决:最直接的办法是降低初始学习率,YOLOv8 默认 lr 在 0.01 左右,对 1000 张小数据集偏高,我通常改成lr0=0.005,同时开启 warmup 让前几轮学习率缓慢上升。其次是把 batch 从 16 提到 32,BN 的统计量在更大 batch 下更稳定。如果这两个方法都试过仍然崩,检查数据集中是否有损坏的图片文件,读取失败产生的全零输入也会引起 BN 崩溃。你要是跑过大规模目标检测可能发现 BN 崩溃多发生在中后期,本质上是优化轨迹出了问题,只管缩小学习率往往就够了。

5.5 验证集 mAP 很高,但拿到真实血液涂片上效果差

现象:测试集 mAP50 达到了 0.85,看起来很好。但把模型接到显微镜摄像头或扫描仪上,真实血液涂片的检测效果下降明显,误检率翻倍。

原因:数据划分时没有按病人或病例隔离。同一个病人不同视野的涂片图如果同时进了训练集和验证集,模型相当于提前见过验证分布的答案,mAP 虚高。另外,如果原始数据都来自同一种染色方法,真实场景染色的颜色分布变化会让模型特征失效。血细胞检测的颜色特征非常敏感,H&E 染色和瑞氏染色的色差足以让模型误判。

解决:划分数据集时按病人分组;训练时加入颜色抖动增强,比如 HSV 通道的随机扰动,让模型对染色差异不那么敏感。开增强参数时注意力度别太大,把白细胞核染成红细胞色反而是副作用。

6. 用混淆矩阵和 mAP 曲线验证血细胞检测模型:三个必看指标

训练结束不等于工作完成。验证模型到底检测得准不准,我会按下面三步走,这也是你复用这套数据集时最值得投入的环节。

6.1 先看混淆矩阵,再看总 mAP

训练结束后,在runs/blood_cell_exp/目录下会生成confusion_matrix.png。血细胞检测的混淆矩阵通常呈现对角线高亮、非对角线零星分布。重点关注 Platelets 这一行:如果它对应的行里有不少目标落入 background,说明小目标漏检仍然是主要矛盾;如果 WBC 对应行有大量误检到 RBC 的样本,说明类别不平衡问题没有通过调参解决。

混淆矩阵不要只看一眼就略过。我会记录三类各自的行列数值,做一个简单的误检原因归类:漏检多的瓶颈在目标尺度,误检多的瓶颈在特征区分。这两者的改善路径完全不同,前者回到数据增强和输入分辨率,后者回到类别权重和模型容量。

6.2 读 mAP50 和 mAP50-95 时要有不同预期

血细胞检测的验证结果里,mAP50 和 mAP50-95 可以差出 0.2 到 0.3。原因前面说过,mAP50-95 计算了 IoU 从 0.5 到 0.95 所有阈值下的平均精度,小目标天然吃亏。如果你看到 mAP50 有 0.85、mAP50-95 只有 0.55,不用慌,这在小目标密集场景是正常水平。

真正要关注的是 mAP50-95 的变化趋势。如果训练轮次增加时它在持续上升,说明模型还有余量,可以考虑加训练轮数或提升分辨率。如果它已经走平甚至下降,说明模型开始过拟合,best.pt 就是你应该停留的位置。

6.3 测试时调整置信度阈值和 IoU 阈值,找到适合你业务的参数

训练好的模型在实际使用时,conf阈值直接决定漏检率和误检率的取舍。血细胞检测场景里,如果你要用于筛检,宁可多框一些让医生复核,conf 阈值设为 0.2 到 0.25 比较合适;如果要直接输出结果而不经过复核,conf 阈值最好提到 0.4 以上,误检会少很多。测试命令如下:

yolo detect predict \ model=runs/blood_cell_exp/weights/best.pt \ source=test/images \ conf=0.25 \ iou=0.45 \ imgsz=960 \ save_txt=True

iou是 NMS 的 IoU 阈值,0.45 是默认值。血细胞这类小目标重叠较少,可以适当降到 0.3,让 NMS 更手下留情,减少误合并。imgsz=960在推理阶段提高分辨率同样可以提升小目标检出率。

我的习惯是拿到 best.pt 后,先在 test 上跑一组 conf=0.25 的预测,把检测结果的可视化图片翻一遍,重点看血小板区域。这个习惯帮我挡掉过至少两次数据处理上的低级失误,所谓玄学问题,多数最后都落在数据和配置上。希望这篇文章里给出的脚本和排查顺序,能让你在自己的血细胞检测项目上少走一截弯路,也希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询