简介:面向医学影像检测、目标检测课程设计与YOLO系列算法验证的学习者,该数据集以1000张真实场景高质量血细胞图片为基础,使用LabelImg标注,包括红白细胞与血小板检测,并提供VOC(XML)、COCO(JSON)、YOLO(TXT)三种格式标签,直接对接YOLO训练流程,省去自行转换格式的繁琐步骤。压缩包内共2000个文件,以1000个XML标注文件、990个TXT标签/列表文件为主,辅以HTML教程、Python脚本与YAML配置,整体约29.34MB,目录结构按不同标注格式分开放置,便于按需调用。已有190人浏览学习,适合课程设计、毕业设计或医学图像入门项目。配套资料包含Windows/Linux环境搭建教程、YOLO训练案例教程、训练集/验证集/测试集划分脚本以及ImageSets生成脚本,可帮助快速完成数据划分、环境配置与模型训练,还能在训练后根据案例修改路径与参数,有效降低从标注数据到目标检测模型落地的门槛。
1. YOLO红白细胞血小板检测数据集:一份能直接开工的血液细胞目标检测资源
做目标检测最烦的不是调模型,而是找数据、标数据、转格式这三件事轮着来。这份YOLO红白细胞血小板检测数据集算是把前期工作都做完了:1000张真实场景的血液镜检图片,三类目标——红细胞、白细胞、血小板,全部用LabelImg人工标注,同时给出VOC(xml)、COCO(json)、YOLO(txt)三种格式的标签,分别存在不同文件夹,拿过来直接就能喂给YOLO系列训练。对我这种经常临时要跑医疗图像检测验证的人来说,省掉的不只是标注时间,还有从xml转txt时最容易翻车的那几步。资源里还附带三个划分脚本和Windows/Linux双平台的环境搭建、训练教程HTML文档,适合刚入坑YOLO的新手,也适合需要快速验证检测效果的熟手。下面按我的拆包习惯,把数据组织、脚本用法、训练配置和坑位一次说清。
2. 数据集内部结构与三种标签格式:先搞清楚文件怎么组织
2.1 资源包文件清单与目录组织方式
解压之后第一件事不是急着训练,而是先看目录结构。这份资源解压后主要分两块:一块是图片和标签文件夹,另一块是教程和脚本。图片和标签按格式分开放置,VOC格式的xml、COCO格式的json、YOLO格式的txt各占一个目录,图片单独一个目录,互不混淆。
HTML教程文档有五个,覆盖了Ubuntu安装、YOLO环境搭建(Windows和Linux两个版本)、YOLO训练教程(Windows和Linux两个版本)。这三个脚本建议放到你的工程目录下,别扔在解压根目录里不管——后面我会细讲怎么用它们做数据集划分。
从训练角度看,这个组织方式的好处是:你不需要自己写格式转换脚本,也不用担心xml和txt对应关系错乱。用LabelImg标注时,一份标注数据可以同时导出VOC和YOLO两种格式(LabelImg支持设置自动保存为YOLO格式),COCO格式需要用脚本转一下或者用标注工具导出。收到数据集后,我一般习惯先抽查三张图和一个xml、一个txt,确认类别顺序一致再开工。
2.2 VOC、COCO、YOLO三种格式的字段差异与换算关系
这三种格式看起来是同一份标注的三种表达,实际字段命名和坐标体系完全不同,混用必翻车。VOC格式是xml文件,核心字段是bndbox(xmin、ymin、xmax、ymax),单位是像素,坐标是绝对的。YOLO格式是txt文件,每行表示一个目标,格式是class x_center y_center width height,全部归一化到0到1之间。COCO格式是json文件,annotations里每个目标用bbox表示,格式是[x, y, width, height],像素单位。
从VOC转YOLO时,核心换算关系是:
# VOC (xmin, ymin, xmax, ymax) -> YOLO (x_center, y_center, width, height) x_center = (xmin + xmax) / 2 / img_width y_center = (ymin + ymax) / 2 / img_height width = (xmax - xmin) / img_width height = (ymax - ymin) / img_height换算的坑在于除法顺序和整数溢出。图片的宽高必须用xml里<size>节点的值,不能自己重新读图算宽高,否则某些训练脚本在做数据增强或resize时会读出越界的框,轻则警告,重则loss直接变成nan。
COCO格式则要注意两个地方:一是bbox里的[x, y, w, h]指左上角坐标加宽高,不是中心点;二是area字段和iscrowd字段必须正确。area用w * h算就行,但iscrowd默认必须为0,如果从其他地方转换时漏了这个字段,用pycocotools做评估时会报错。
2.3 类别顺序约定与标签文件命名规则
训练YOLO时,类别顺序由data.yaml里的names列表决定,而names的顺序要和txt里的整数索引一一对应。这份数据集里三个类别的默认顺序通常和标注时的class列表一致,我拿到手第一件事就是读一个txt看类别索引,再和教程里的yaml配置对比。
文件命名规则方面,图片和标签文件同名,只是后缀不同——blood_001.jpg对blood_001.txt(YOLO格式)和blood_001.xml(VOC格式),COCO格式则是把所有标注汇总进一个json文件。这种命名规则的好处是划分脚本可以只对图片列表做随机打乱,然后按文件名前缀去匹配对应的标签文件。
| 格式 | 文件后缀 | 坐标体系 | 标注表达方式 | 适用框架 |
|---|---|---|---|---|
| VOC | .xml | 像素绝对坐标 | xmin, ymin, xmax, ymax | Detectron2, mmdetection |
| COCO | .json | 像素绝对坐标 | [x, y, w, h] + area + iscrowd | Detectron2, mmdetection, YOLOv5/v8转换版 |
| YOLO | .txt | 归一化坐标 | class + x_center + y_center + width + height | YOLO系列直接读 |
3. 三个划分脚本详解:训练集、验证集、测试集怎么切才靠谱
资源里附带三个Python脚本,名字分别是“训练集、验证集、测试集划分脚本(图片标签划分写入新文件夹).py”“训练集、验证集划分脚本(图片标签划分写入新文件夹).py”“split_train_val生成ImageSets下txt文件划分脚本.py”。这三个脚本做的事有交集也有区别,很多新手拿到手分不清该用哪个,我把我实际的用法拆开讲。
3.1 脚本一:训练集、验证集、测试集三段划分
这个脚本做的是完整的三段划分,把图片和标签按比例拆成train、val、test三个新文件夹。内部逻辑是:读取指定目录下所有图片文件名,用random.shuffle打乱顺序,然后按比例切片,最后把图片和对应用标签复制到新目录。
import os import random import shutil # 配置区域 img_dir = 'images' # 原始图片目录 label_dir = 'labels' # 原始标签目录(yolo格式txt) train_ratio = 0.7 # 训练集比例 val_ratio = 0.2 # 验证集比例 # test_ratio = 0.1 # 测试集比例,剩余部分即为测试集 out_dir = 'split_data' # 输出根目录 files = [f for f in os.listdir(img_dir) if f.endswith('.jpg')] random.shuffle(files) train_num = int(len(files) * train_ratio) val_num = int(len(files) * val_ratio) train_files = files[:train_num] val_files = files[train_num:train_num + val_num] test_files = files[train_num + val_num:] def copy_files(file_list, subset): os.makedirs(f'{out_dir}/{subset}/images', exist_ok=True) os.makedirs(f'{out_dir}/{subset}/labels', exist_ok=True) for f in file_list: shutil.copy(f'{img_dir}/{f}', f'{out_dir}/{subset}/images/{f}') label_name = f.replace('.jpg', '.txt') label_path = f'{label_dir}/{label_name}' if os.path.exists(label_path): shutil.copy(label_path, f'{out_dir}/{subset}/labels/{label_name}') copy_files(train_files, 'train') copy_files(val_files, 'val') copy_files(test_files, 'test') print(f'train: {len(train_files)}, val: {len(val_files)}, test: {len(test_files)}')这个脚本最关键的参数是三个比例,默认建议7:2:1或者8:1:1。我一般会用7:2:1,训练量1000张图按7成是700张,对YOLO这种数据饥饿模型来说,数量不算富裕,但配合数据增强也够用。脚本中有个隐含约定,就是标签文件和图片文件同名,只是后缀从.jpg换成.txt,如果使用同一批数据但标签是XML格式,需要把f.replace('.jpg', '.txt')改成f.replace('.jpg', '.xml')。
脚本里的随机打乱没有固定随机种子,这意味着每次运行划分结果都不同。我自己做实验时会加一行random.seed(42),确保两次实验结果可复现,不然对比模型效果时你分不清是模型改进了还是数据划分变了。
3.2 脚本二:只做训练集和验证集划分
有些场景不需要测试集,比如做交叉验证或者只是临时看一下训练曲线。第二个脚本就是只划分train和val两段,逻辑更简单,基本是上面的脚本减去test部分。这类脚本常用于模型训练阶段的快速验证,等模型选型完成后再跑一次三段划分做正式评估。
3.3 脚本三:生成ImageSets下的txt索引文件
第三个脚本做的事情和前面两个完全不同,它不复制文件,而是在数据集目录下生成ImageSets/Main文件夹,里面写入train.txt、val.txt、test.txt,每个txt里是图片的文件名列表(不带后缀或带完整路径,取决于脚本实现)。这种形式是VOC数据集的标准组织方式,后来被很多基于VOC格式的检测框架沿用。
如果你用的是YOLOv5或YOLOv8,你其实可以不用这个脚本,因为YOLO系列直接读data.yaml里train.txt和val.txt的路径列表;但如果你后续要切到mmdetection或者自己写数据加载器,ImageSets格式会更顺手。这个脚本的价值是兼容性,不急着用,但别删。
3.4 划分时最容易犯的错:图片和标签脱同步
划分数据时最常见的问题是只复制了图片没复制标签,或者训练集里有一张图没有对应标签。这种“半残”的样本训练时不会报错,因为YOLO训练逻辑会跳过没有目标的图片,但它会让训练集的有效样本量下降,同时模型会对“无目标”的图片产生错误的先验——后期推理时容易把背景误判成目标。
我拿任何数据集做划分后都会强制做一步校验:统计train目录里图片数量和txt数量是否一致。数量对不上就说明有图没标或者有标没图,直接找出来处理,别带着问题进训练。
4. 环境搭建与训练配置:从零训练YOLO血细胞检测模型
4.1 Windows和Linux双环境搭建:conda虚拟环境流程
资源里的四个HTML教程分得很清楚——Windows和Linux各一套环境搭建教程加一套训练教程。核心走的都是conda虚拟环境加pip安装pytorch和ultralytics的路线。
Windows环境我常用的流程是这样的:
conda create -n yolo python=3.8 -y conda activate yolo pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralyticsLinux环境基本一样,但如果你有NVIDIA显卡,记得先跑一下nvidia-smi确认CUDA版本,再安装对应版本的torch。CPU版torch也能训练,只是速度慢得感人,1000张图一次epoch可能要跑很久,我不建议这么做。如果只有CPU,优先用YOLOv5s或者YOLOv8n这种小型网络,参数量小,能在可接受的时间内出结果。
YOLO系列里v5和v8是目前社区最常用的版本,v5的工程化做得好,文档全;v8的代码结构更新,anchor-free机制对尺寸差异大的目标更友好。血细胞检测里白细胞和血小板大小差一个量级,用v8的anchor-free可能会比v5省心一些。
4.2 data.yaml配置:类别数与训练参数对照
数据准备好后,核心是写data.yaml。这个文件负责告诉YOLO训练脚本你的数据在哪、有几个类别、类别名字是什么。
# data.yaml path: ./datasets/blood_cell train: images/train val: images/val test: images/test nc: 3 names: ['RBC', 'WBC', 'PLT']这里的nc必须是3,对应红白细胞血小板三类。names列表的顺序和txt里类别索引的对应关系必须一一对应,不然类别标签会张冠李戴。用这份数据集前,先拿一个txt文件,看第一行第一个数字是0还是1还是2,再对应去看names顺序,基本就能确认。
开始训练前还应该检查labels目录里是否有类别不平衡问题。血细胞图像里红细胞数量远比白细胞和血小板多,三类目标数量可能差几十倍,这会直接导致模型对少样本类别学习不充分。后面我会讲怎么针对这种情况调整训练策略。
4.3 训练命令与关键参数解释
环境就绪、data.yaml写好后,训练命令本身不长,但几组参数值得抠一下:
yolo train data=blood_data.yaml model=yolov8n.pt epochs=100 batch=16 imgsz=640 device=0epochs=100对于1000张图的数据集来说,配合mosaic增强,可以在不多的训练时间内收敛;如果数据量更少,我一般会降到50到70轮,防止过拟合。batch=16取决于显存大小,如果你只有6GB显存,建议降到8或者4,同时把imgsz降到480或416。imgsz对检测效果影响很大,640是速度和精度的折中点——如果你想提高对小目标(血小板)的召回率,可以考虑用1280,但训练时间会翻倍甚至更多。
训练过程中值得关注的是损失曲线。YOLOv8会输出三部分损失:box_loss、cls_loss、dfl_loss。正常情况下三者应该平滑下降,如果box_loss快速降到接近0而cls_loss还在高位,说明模型定位学得好但分类判断不行;如果三个loss都在0.5以上震荡,大概率是学习率偏高了。
4.4 训练中断的恢复与断点续训
训练跑一半挂了是常事,原因是显存溢出、断电、手动Ctrl+C。YOLO系列的默认行为是每个epoch结束保存last.pt和best.pt,断点续训直接这样做:
yolo train data=blood_data.yaml model=runs/detect/train/weights/last.pt epochs=100 device=0注意model参数换成last.pt路径,而不是从头开始。这里有个坑:last.pt里保存的状态包含当前epoch数,续训时会从断点继续,而不是重新计数。如果你发现续训时epoch从1开始,说明用的不是last.pt而是best.pt或者预训练权重,训练轮数会超预期。我个人习惯每隔10个epoch手动复制一份last.pt另存,防止训练到90轮崩了只能回退到50轮的结果。
5. 避坑排查指南:格式转换、类别不均衡与小目标,五个必踩的坑
5.1 训练直接报“标签文件不匹配”或所有loss都是nan
现象:训练刚开始就提示某些标签文件找不到,或者loss输出为nan。
原因:txt标注文件里类别索引超出nc范围,比如txt里写了3但yaml里nc: 3的索引只允许0、1、2;或者标注文件里出现了负坐标、大于1的归一化坐标。另一个常见原因是你把VOC格式的xml直接扔进了labels目录,YOLO训练代码读xml读不出合法内容。
解决:写一个检查脚本,遍历labels下所有txt,解析每一行,看class索引是否在[0, nc-1]范围,看坐标是否都在[0, 1]内。发现有问题的文件直接删除对应图片和标签,或者手工修正。数据量只有1000张,花十分钟清洗一遍,比训练时Debug一晚上强得多。
5.2 三个类别之间数量差了几十倍,少样本类别完全不收敛
现象:训练30轮后,红细胞(RBC)的mAP到0.9,白细胞(WBC)到0.7,血小板(PLT)的mAP还不到0.3。
原因:这是血细胞检测里最典型的类别不平衡问题。红细胞几乎每个视野都有几十个,血小板往往只有少量,模型天然倾向于学习高频类别。此外血小板的尺寸在640分辨率下可能只有几个像素,属于小目标检测的老大难问题。
解决:三步走。第一步,给少样本类别做离线增强,将包含血小板或白细胞的图片做随机旋转、翻转、HSV扰动,复制几份扩充到训练集里。第二步,训练时调整增强参数,增大mosaic和copy_paste的概率,让不同样本在增强时互相混合,变相增加少样本类别的出现频率。第三步,降低batch大小并增加epoch数,给模型更多迭代去学少样本类别。如果还不够,可以尝试给少样本类别配置更高的分类权重系数,但这个操作不同YOLO版本的做法不同,要查对应版本的参数名。
5.3 VOC或COCO格式转换后mask和bbox错位
现象:从COCO json加载数据训练,发现预测框和真实目标位置有偏差,或者标注框整体位移。
原因:COCO的bbox格式是[x, y, width, height]且是像素单位,很多人转换时容易和VOC的[xmin, ymin, xmax, ymax]搞混,导致w和h被算成了右下角坐标。另一个问题是在resize时没有同步缩放bbox坐标,比如原图1080P缩放到640训练,bbox坐标没跟着缩,预测时自然错位。
解决:任何格式转换后做一次可视化检查,把标注框画回原图。用OpenCV画框看位置是否贴合目标,这一步虽笨但能一眼发现坐标体系问题。不要直接开训练,训练半天发现是数据问题,心态容易崩。
5.4 划分脚本运行后某些图片没有标签或标签没复制
现象:跑完划分脚本,train目录里图片数比txt多,或者val目录里某张图的txt是空文件。
原因:划分脚本里写的是固定后缀替换,比如f.replace('.jpg', '.txt'),但数据集中部分图片可能是.png或.jpeg后缀,替换失败后找到的标签不存在,脚本没有做异常处理就静默跳过了。空txt文件的情况是某些图片没有目标,人工标注时没有生成标注内容。
解决:自己加一轮校验,对比图片文件名集合和标签文件名集合的差集,找出哪些图缺失标签,要么补充标注要么删掉这张图。对于空txt文件,建议直接删除对应图片,否则模型会学到“这张图没有目标”的错误模式,推理时容易误检背景。
5.5 Windows路径分隔符报错和数据路径硬编码问题
现象:Windows上跑训练脚本报文件找不到,路径看起来没错但就是读不到;换一台机器重新训练又要改一堆路径。
原因:Windows默认路径分隔符是反斜杠\,而Python字符串里\t、\n会被转义,路径写死容易出这类问题。另一个问题是data.yaml里面用了绝对路径,比如path: C:/Users/xxx/datasets/blood_data,换机器或者换目录后路径失效。
解决:所有路径统一用正斜杠/或者pathlib的Path对象处理。data.yaml里的path配置建议用相对路径,配合当前工作目录定位。我自己习惯把这些数据集和脚本统一放在一个独立目录,每次训练前用cd切换到该目录再执行命令,避免交叉引用绝对路径造成混乱。
6. 进阶技巧:推理时的置信度阈值调优与血细胞小板检测优化
训练完模型只是第一步,部署到实际推理场景时还需要做阈值调优。YOLO推理输出有两组关键参数:conf_thres置信度阈值和iou_thresNMS交并比阈值。默认的conf=0.25在通用目标上表现尚可,但在血细胞检测这类场景下容易出问题——血小板的检测结果置信度普遍偏低(0.2到0.4之间),如果阈值设高了会漏检,设低了背景误检又控制不住。
推理时可以用如下命令先测一组基线结果:
yolo predict model=best.pt source=test_images/ conf=0.1 iou=0.5 save_txt=True把conf降到0.1会导致大量误检框出现,但这时候不是去调模型,而是用这组结果判断:血小板类别的置信度分布大概在哪个区间。如果发现血小板检测框的置信度集中在0.15到0.25之间,而背景误检的置信度在0.1以下,那0.15就是一个比较合适的阈值。这个确定阈值的过程我建议写个脚本批量跑验证集,统计不同阈值下的精确率和召回率。
针对血小板小目标漏检的问题,除了前面说的增强策略,还有一个更直接的办法——imgsz推高到1280。YOLOv8在推理时支持比训练更大的输入尺寸,血小板在1280下占据的像素面积是640下的4倍,检测难度会明显下降。代价是推理速度变慢,如果你是在CPU或者边缘设备上跑,这个方案可能不现实,那就要考虑对原图做切片推理(把大图切成若干小块分别检测再聚合结果),但这份资源附带的教程没有覆盖这个方案,需要你自己额外找资料。
从数据角度还有一个取舍要提:这份数据集的图片来自真实血液涂片场景,不同设备、不同染色条件下细胞外观差异较大。如果你拿它训练出的模型换到另一台显微镜下测试,泛化效果可能不如源域。我处理这类问题时,会额外收集一些目标场景下的无标注图片,用训练好的模型先跑一遍伪标注,人工筛选后加入训练集,整个过程花不了多少时间,但对新场景的适应性提升非常明显。
那份数据集划分脚本我从一开始就是固定种子再跑,从那以后我每次做数据切分都强制走一遍固定种子加数量校验的流程,省了很多对比实验翻车的后悔药。希望这份拆解能帮上忙,尤其是第一次拿YOLO做医学图像检测的你,少踩几个格式和划分的坑,快速跑出自己的模型。
本文还有配套的精品资源,点击获取