尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

COCO格式BCCD血细胞数据集:从可视化校验到YOLO训练实战

COCO格式BCCD血细胞数据集:从可视化校验到YOLO训练实战 简介COCO格式的BCCD血细胞检测数据集面向计算机视觉、医学影像分析及深度学习目标检测方向的学习者与研究者特别适合用于训练和评估血细胞检测模型。数据集覆盖白细胞WBC、红细胞RBC和血小板Platelets三个类别共364张JPEG图像从原始VOC格式转换为COCO标注附两个JSON文件分别对应训练集205张、验证集87张、测试集72张划分清晰可直接接入YOLO、MMDetection等主流目标检测框架。每张图像均含多个血细胞实例标注包含类别、边界框位置及大小信息完整资源包共366个文件压缩后仅7.29MB轻量便携便于快速下载与实验迭代。目前已有551人学习下载。使用此数据集可省去格式转换和标注整理流程直接开展血细胞检测模型的训练、验证与算法对比研究适合医学影像AI入门、专业课程设计以及目标检测算法基准测试。1. 为什么要用COCO格式的BCCD一份能直接喂给检测框架的血细胞数据BCCD血细胞检测数据集的COCO格式版本是我在跑目标检测实验时最常拿出来复现的基准之一。它的本体是364张显微镜血涂片图像包含RBC红细胞、WBC白细胞、Platelets血小板三个类别原始标注是VOC的XML格式而这份资源已经帮你转换成了COCO格式的annotations.json——意味着你不用再写XML解析脚本也不用纠结类别映射拿到就能喂给支持COCO接口的检测框架。对刚入门目标检测的人来说它是少有的「小目标多类别数量不多」的练手数据对熟手来说这份数据可以用来快速验证数据增强策略、小目标检测技巧或者当作框架安装完之后的冒烟测试数据。这篇文章就围绕这份COCO格式资源把文件结构、训练前的校验、两种落地路线和实际踩过的坑一次说清楚。2. 认识这份COCO数据集文件构成、标注字段与分布特点2.1 annotations.json 的分层结构images、annotations、categories 怎么对应COCO格式的核心不是图片文件夹而是那个annotations.json。它能被Detectron2、MMDetection、PaddleDetection直接读取靠的就是一套固定的分层结构。拿到这份资源后我建议先别急着训练打开json把顶层字段扫一遍。import json with open(annotations.json, r, encodingutf-8) as f: coco json.load(f) print(顶层字段:, list(coco.keys())) print(categories:, coco[categories]) print(images 数量:, len(coco[images])) print(annotations 数量:, len(coco[annotations])) # 看一张图和它的标注 img coco[images][0] anns [a for a in coco[annotations] if a[image_id] img[id]] print(样例图片:, img) print(该图标注数:, len(anns)) print(第一条标注:, anns[0])这段代码做的事情是加载json打印顶层结构输出类别列表再统计图片数、标注总数最后抽出一张图和它对应的标注做检查。正常情况下categories里应该是三类细胞images数量为364而annotations的数量会明显多于图片数因为一张图里往往有几十个甚至上百个细胞。COCO的层级关系是images里的id是图片唯一标识annotations里的image_id指向它annotations里的category_id指向categories里的类别。三者通过ID串联任何一环对不上训练时就会出现「标注丢失」或者「类别对错」的怪问题。看这份资源的格式时重点确认一下bbox字段——COCO里它是[x, y, width, height]即左上角坐标加宽高不是[x1, y1, x2, y2]。这个字段在后续可视化失败时是头号嫌疑。2.2 BCCD 的三个类别RBC、WBC 和 Platelets 有什么特点BCCD这个数据集在血细胞检测里算「老熟人」。三个类别本身存在明显的难度差异RBC数量最多、尺寸相对大WBC数量少但目标明显Platelets则是数量少、尺寸小、经常聚成一团。从检测难度上排序Platelets WBC RBC这一点直接决定了后面训练参数的设置方向。类别典型尺寸数量级检测难点RBC红细胞较大最多密集、相互粘连WBC白细胞中等少类别区分度Platelets血小板很小较少小目标、易漏检原数据集中每张图的细胞数不固定有的图只有几个细胞有的图上百个。这种不均衡意味着如果直接拿COCO格式去训练而不做任何处理模型会在RBC上学得最快在Platelets上迟迟不收敛。这不是标注的问题是数据本身的长尾分布。理解这一点后再去看训练结果就不会因为mAP整体数值还行就忽略小类目的漏检。2.3 画框可视化训练前必须做的一步校验拿到COCO格式数据最怕的是json标注跟图片实际内容对不上。COCO格式本身不会帮你做交叉验证转格式的脚本如果坐标系弄错、图片名对不上生成出来的json结构是合法的但框的位置是错的。因此我拿到任何COCO数据集的第一件事不是训练而是可视化抽样。import cv2 import random from pycocotools.coco import COCO coco COCO(annotations.json) img_ids coco.getImgIds() random.shuffle(img_ids) for i in range(5): img_id img_ids[i] img_info coco.loadImgs(img_id)[0] img cv2.imread(img_info[file_name]) ann_ids coco.getAnnIds(imgIdsimg_id) anns coco.loadAnns(ann_ids) for ann in anns: x, y, w, h [int(v) for v in ann[bbox]] cat_id ann[category_id] cat coco.loadCats(cat_id)[0][name] color (0, 255, 0) if cat RBC else (0, 0, 255) if cat WBC else (255, 0, 0) cv2.rectangle(img, (x, y), (x w, y h), color, 2) cv2.putText(img, cat, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1) cv2.imwrite(fcheck_{i}.jpg, img) print(f已保存 check_{i}.jpg共 {len(anns)} 个标注)这段代码用pycocotools加载标注随机抽5张图把每个bbox按类别画出来。跑完一遍如果看到框的位置和细胞对得上、类别标签正确才能放心进入训练如果出现框整体偏移、宽高反了、或者画出来的框明显比细胞大一圈那就说明json里的坐标来源有问题继续训练只会浪费算力。提示pycocotools是COCO官方的Python接口库Windows上安装如果报错用pip install pycocotools-windows可以解决macOS/Linux直接pip install pycocotools。3. 数据落地直接训练还是转YOLO两条路线怎么选3.1 路线一COCO原生框架直接读以MMDetection为例这份资源最省事的用法就是直接喂给COCO原生框架。MMDetection这类库提供了完善的COCO数据接口只要配置好数据路径和类别信息不需要任何转换脚本。在MMDetection里数据集配置通常写在一个data字典中COCO格式的数据集需要指定三部分ann_filejson路径、data_prefix图片路径、metainfo类别名。对于这份BCCD资源配置片段大致是这个样子train_dataloader dict( datasetdict( typeCocoDataset, data_rootdata/bccd/, ann_fileannotations.json, data_prefixdict(imgimages/), metainfodict(classes(RBC, WBC, Platelets)), filter_cfgdict(filter_empty_gtTrue, min_size32), pipeline[...] ) )这段配置的关键是metainfo里的类别顺序必须和annotations.json中categories的顺序一致否则模型输出的类别索引和实际类别会错位。filter_empty_gtTrue表示过滤掉没有标注的图片min_size32过滤掉尺寸过小的gt框这两个参数在血细胞数据上有实际作用因为Platelets的小框如果不做过滤可能会在训练时计算loss时引入噪声。用MMDetection训练BCCD的好处是不用改数据坏处是环境的坑多编译算子、版本对齐、GPU驱动每一步都可能耗掉半天。我自己的习惯是如果只是想快速验证BCCD上某个检测头的效果直接走MMDetection如果目标是把模型用起来、做推理部署更推荐转到YOLO系列省心得多。3.2 路线二转成YOLO txt标签一份顺手就能跑的转换脚本YOLO系列框架默认不读COCO json它要的是一张图对应一个txt里面每行是class_id x_center y_center width height坐标都归一化到0~1。很多教程里这一步要靠标注工具自动生成但我们手上是json写个转换脚本反而更快。import os import json from glob import glob def coco_to_yolo(json_path, img_dir, out_dir): with open(json_path, r, encodingutf-8) as f: coco json.load(f) # 建立 image_id - 图片文件名的映射 id_to_name {img[id]: img[file_name] for img in coco[images]} # 建立 category_id - 类别索引的映射按json顺序 cat_id_to_idx {cat[id]: idx for idx, cat in enumerate(coco[categories])} # 按图片名聚合标注 anns_by_img {} for ann in coco[annotations]: img_name id_to_name[ann[image_id]] anns_by_img.setdefault(img_name, []).append(ann) os.makedirs(out_dir, exist_okTrue) for img_name, anns in anns_by_img.items(): h coco[images][anns[0][image_id]][height] w coco[images][anns[0][image_id]][width] txt_path os.path.join(out_dir, img_name.rsplit(., 1)[0] .txt) with open(txt_path, w) as f: for ann in anns: x, y, bw, bh ann[bbox] cx (x bw / 2) / w cy (y bh / 2) / h f.write(f{cat_id_to_idx[ann[category_id]]} {cx:.5f} {cy:.5f} {(bw / w):.5f} {(bh / h):.5f}\n) f.close() coco_to_yolo(annotations.json, images/, labels/)逻辑说明这个脚本遍历COCO json把每个bbox的[x, y, width, height]换算成YOLO格式的中心点坐标和归一化宽高然后按图片名生成对应的txt文件。换算公式是中心点x等于x width/2再除以图片宽归一化宽等于width除以图片宽。坐标全部用浮点数写到0~1区间。参数说明json_path指向原来的COCO标注img_dir是图片目录脚本里只用来确认路径习惯真正读取图片宽高是从json的images字段取的out_dir是txt输出目录。如果你的json里images字段缺少宽高这段脚本会报KeyError那就需要额外用cv2.imread读取图片来获取尺寸。3.3 类别顺序最容易忽略但后果最严重的一环不管是走MMDetection还是转YOLO「类别顺序」永远是优先级最高的问题。COCO json里categories的排列顺序决定了category_id是谁但很多转格式脚本会按自己的规则重新排序——比如按字母排序结果RBC变成索引0、Platelets变成索引2和你训练框架默认的顺序不一致模型训练出来所有预测框的标签全部错位。我一般拿到json后先执行一条命令看原始顺序python -c import json; djson.load(open(annotations.json)); print(d[categories])输出结果会显示categories里每个类的id和name。转YOLO时脚本里enumerate(coco[categories])使用的是这个顺序配置MMDetection时metainfo里的类别列表也要按这个顺序写。两头都对齐了训练出来的模型才不会出现「红细胞框标成血小板」的笑话。4. 把模型训练起来BCCD的配置参数与权衡4.1 YOLOv8 数据yaml与训练命令转好YOLO标签后下一步就是定义数据集yaml。YOLOv8用yaml描述数据集的路径和类别列表这份BCCD资源的yaml应该写成下面这样# bccd.yaml path: ./bccd train: images/train val: images/val test: images/test nc: 3 names: 0: RBC 1: WBC 2: Platelets以path为根目录train/val/test指向图片目录标签txt的路径会自动替换为相同目录结构下的labels文件夹。比如images/train/BloodImage_00001.jpg对应的标签路径是labels/train/BloodImage_00001.txt。nc: 3是类别数names的索引和转换时保持一致这里假设转换脚本是按json里的默认顺序生成的txt类别索引。训练命令通常长这样yolo detect train databccd.yaml modelyolov8s.pt epochs100 imgsz640 batch16epochs100对364张图的小数据量已经够用再往里加training时间并不会显著提升精度反而容易过拟合imgsz640是速度和精度的折中batch16取决于显存如果只有8G显存降到batch8或把模型换成yolov8n.pt更现实。血细胞目标小如果显存允许imgsz1024对Platelets的召回率会有明显帮助这点在第五节展开说。4.2 关键超参数怎么设imgsz、epochs、batch 的实验经验在BCCD这种小规模、小目标的数据集上几个关键参数值得单独讨论。先说imgsz它的影响不只是分辨率变大而是直接改变小目标在特征图中的像素占据。640尺寸下一个只有10×20像素的血小板在yolov8的检测头上可能只剩三四行特征输出提升到1024后同样目标能映射到更多输出单元。代价是训练时间和显存同步上升。如果主要关心Platelets的漏检率我的习惯是先跑一个短epoch的实验对比640和1024下的验证集召回率再决定。再说epochs。364张图、其中训练集只有205张属于典型的小数据量场景。100个epoch对YOLOv8来说通常到第60~70个epoch时mAP已经开始停滞甚至过拟合。如果看到训练loss持续下降但验证loss掉头向上几乎可以肯定是过拟合这时优先降低epochs或者加数据增强参数而不是调优化器。batch的选择影响的是bn统计量的稳定性小数据集上batch8~16之间差异不大但显存不够的时候不要用梯度累积硬凑大batchBCCD的图片尺寸本来就小batch8已经足够稳定。4.3 评估指标解读这张数据上mAP够用吗训练结束后的验证输出里YOLOv8会打印all这一类汇总指标也可能按类别列出每个类的AP。对于BCCD只盯mAP50会掩盖真实问题。指标含义在BCCD上的参考价值mAP50IoU0.5时的平均精度看整体是否收敛mAP50-95IoU从0.5到0.95的平均精度对框定位质量敏感recall (Platelets)血小板召回率小目标漏检的直接体现一个有代表性的翻车现象是整体mAP50很好看比如0.85但Platelets一类的recall不到0.5。原因就是RBC数量多、模型学得充分把整体指标拉起来了小目标类仍然是漏检状态。评估时务必把每个类别的AP单独打出来看一眼yolo val加上plotsTrue后生成的曲线图里各类的PR曲线一眼就能看出谁在拖后腿。注意BCCD的标注存在一定的类别粒度局限同一张图里血小板经常紧贴红细胞标注框之间会有重叠。评估时如果发现某个类别的AP出现异常波动先检查是不是标注重叠导致loss不稳定。5. BCCD COCO 常见坑与排查五个我实际踩过的问题5.1 现象可视化时所有框的位置偏右偏下原因json里的bbox是[x, y, width, height]但可视化脚本里cv2.rectangle的坐标参数写的是右下角坐标(x2, y2)直接把xw和yh当成右下角用看起来所有框都会偏一个固定offset。另一个可能是转换时把归一化坐标和像素坐标弄混了导致框整体放大。解决确认bbox四个值的语义cv2.rectangle(img, (x, y), (x w, y h), ...)的第二个点一定是左上角加宽高不能直接填bbox[2:]。如果是从其他格式转过来的json先拿一张细胞画面简单、标注数量少的图单步调试打印原始bbox和画框坐标对比。5.2 现象训练时报错“AssertionError: image not found”原因json里images字段的file_name写的是绝对路径但训练时换了机器或目录路径失效。或者file_name只写了文件名而数据yaml里指定的train路径拼不出来。解决先用脚本把所有file_name检查一遍确认是纯文件名还是带路径。如果是绝对路径用统一规则改写为相对路径并确保path指向正确位置。我一般会跑一遍python -c import json; djson.load(open(annotations.json)); print([i[file_name] for i in d[images][:5]])看输出是BloodImage_00001.jpg还是E:/data/BloodImage_00001.jpg后者在任何协作场景下都是定时炸弹。5.3 现象训练损失下降正常但验证时Platelets一类的recall一直为零原因大概率是类别不平衡加剧到小目标类别完全学不出来。364张图里标注数量极少batch里经常整个batch没有Platelets的gt框模型更新梯度时完全没有该类别的正样本参与收敛自然无从谈起。如果训练的batch设为16而platelets标注框平均每两三张图才出现一两个会出现大量“空跑”的迭代。解决先把训练yaml和验证yaml分开看确认验证集里确实存在Platelets的标注然后把imgsz调大让血小板在特征图中不再只是一两个像素再不行就换带fPN结构的模型或者用加权采样让含Platelets的图片在batch中被抽中的概率变大。直接在数据层面做copy-paste增强也是常见做法下一章会说。5.4 现象用MMDetection训练loss跑飞没有任何收敛迹象原因多数出在metainfo的类别顺序和json里categories顺序不一致。MMDetection在构建数据时会按metainfo分配category_id如果两边顺序一样但少写了某个类或者多写了某个不在json里的类别模型的输出通道和数据的标注索引就错位了。解决严格按我在3.1节里的顺序写法metainfodict(classes(RBC, WBC, Platelets))然后先跑一个小数据集比如只拿10张图验证确认loss在下降再跑全量。5.5 现象转成YOLO标签后发现某一行txt里坐标值出现大于1的数字原因annotations里的bbox本身越界了比如x w大于图片宽度。BCCD原始标注是由VOC格式转换过来的个别标注框的坐标就是超出图片边界的这在人工标注数据里不罕见。YOLO训练时遇到超过1的坐标会报warning导致该标签被跳过跳过多了就出现「某张图没有标签」的隐性丢数据。解决转换时做一次裁剪或过滤。常见做法是把越界的坐标clip到[0, w]和[0, h]范围内或者直接丢弃越界超过图片面积一半的标注框避免把错误样本喂给模型。写个简单过滤条件即可不要手工一张张改。6. 进阶用法用BCCD验证小目标策略和数据增强的实际收益BCCD最适合做的实验其实是「数据增强对小目标检测的影响」。因为RBC、WBC、Platelets三个类别的尺寸差异天然存在同一张图上就能对比不同策略对不同尺度目标的增益。我建议在yolov8的配置里尝试mosaic1.0和copy_paste0.1这两个参数。Mosaic在训练中将四张图拼成一张含Platelets的图被拼进去后模型能在batch里更稳定地看到小目标copy_paste则直接把小目标对象复制粘贴到其他图上等于把小类别的样本从物理层面「增多了」。另外一个值得试的技巧是两阶段验证先跑一次基础配置比如imgsz640、不使用增强的v8s作为baseline再跑一组imgsz1024 增强的配置对比两组结果里Platelets的AP变化。这个对比通常能直观地告诉你你的模型精度瓶颈到底是「目标太小看不清」还是「同类样本太少学不透」。我在做这类对比的时候有个固定习惯每次训练都在命令行里带上nameexp_tag参数给实验一个可读的名字这样results目录里不会出现一堆exp1、exp2最终对比起来也不需要去翻YAML才知道当时跑的是什么。血细胞检测这类小数据集一次从数据处理到训练完成不过一两个小时多跑几组实验的成本远低于在真实数据集上做一次完整训练。从那以后我每次拿到COCO格式的数据集都强制先过一遍可视化校验、类别顺序检查、小目标统计三步曲再决定训练策略这个流程省掉了我自己很多次「训练完了发现类别跑错」的后悔时间。希望帮到你。本文还有配套的精品资源点击获取
返回列表