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

资讯详情

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

红细胞检测数据集:VOC/COCO/YOLO标签转换与YOLO训练实战

红细胞检测数据集:VOC/COCO/YOLO标签转换与YOLO训练实战 简介这份YOLO红细胞目标检测数据集面向医学图像分析、目标检测算法实践与课程设计等场景来自真实场景的高质量图片样本覆盖丰富标注框质量高可帮助学习者摆脱自建数据集的繁琐流程直接聚焦模型训练与调优。包内共2000个文件以1000个xml、990个txt标签文件为主体并包含html教程、py脚本和yaml配置文件整体压缩包仅19.82MB标签格式覆盖VOC、COCO、YOLO三种分类存放、即下即用便于接入主流YOLO系列项目。配套内容包含Windows与Linux环境搭建教程、YOLO训练案例教程以及训练集/验证集/测试集划分脚本读者可按需拆分数据并快速跑通完整训练流程。目前已有344人学习下载既适合目标检测入门者学习完整流程也适合研究人员直接复用数据集开展红细胞检测实验。1. 一千张红细胞图片为什么要带三套标签做血涂片红细胞检测时模型效果除了取决于图片质量更大程度取决于训练数据怎么组织。我拆开这套 1000 张的数据集压缩包时最先看到的是按文件夹分好的 voc(xml)、coco(json)、yolo(txt) 三份标签外加三个划分脚本和 Linux/Windows 两版训练教程。也就是说从数据读取到训练流程被文档化得比较完整适合刚开始接触目标检测、又不想把时间耗在标签转换上的工程师。也正是因为三类格式齐全同一份图片可以直接喂给 YOLOv5、YOLOv8也可以转到 mmdetection 这条技术栈。这篇文章就按实际操作的顺序把格式对应关系、划分脚本的数据流、训练命令和排错要点拆开讲。2. VOC、COCO、YOLO 标签格式的数据组织与解析把压缩包解开后第一件事不是看模型代码而是把图片、xml、json、txt 四个文件的位置对应起来。这套红细胞数据集用 LabelImg 标注LabelImg 的默认保存格式是 PASCAL VOC 的 xmlcoco json 和 yolo txt 则是围绕同一批边界框生成的另外两种描述。三类标签内容等价只是坐标定义不同VOC 和 COCO 都走像素坐标YOLO 走归一化坐标因此训练前的格式检查直接决定后面能不能少踩坑。2.1 目录布局与文件命名先看压缩包里常见的目录结构。由于资源里说明“三种格式标签分别存放在不同文件夹下”实际组织通常是这样的RBC_dataset/ ├── JPEGImages/ # 1000 张红细胞图片 ├── Annotations/ # VOC 格式的 xml 标注 ├── coco/ │ └── annotations.json # COCO 格式标签 ├── labels/ # YOLO 格式 txt 标签 ├── ImageSets/ │ └── Main/ # 由划分脚本生成的 train/val/test 列表 └── train_list.txt # 图片路径列表方便脚本遍历这个目录并不需要严格照抄train_list.txt才是关键入口。它每行写一张图片的相对路径或绝对路径划分脚本读它时只用文件名主干比如001然后在不同目录下找001.jpg与001.txt。所以正常解压后先检查三个位置图片文件扩展名是否统一、标签文件和图片是否同名、train_list.txt末尾是否有多余空行。如果这里不一致后面所有脚本都会出现“文件找不到”的假阳性错误。文件格式边界框定义常见消费方Annotations/xx.xmlVOCxmin, ymin, xmax, ymax自定义读取、Faster R-CNNcoco/annotations.jsonCOCObbox: [x, y, width, height]mmdetection、Detectron2labels/xx.txtYOLOclass, x_center, y_center, w, hYOLOv5、YOLOv82.2 从 xml 到 json两种格式的边界框字段对照VOC xml 的解析是所有转换的基础。下面这段脚本可以直接用来读取任意一张红细胞图片的标注import xml.etree.ElementTree as ET def parse_voc(xml_path): # 读取 LabelImg 生成的 VOC xml root ET.parse(xml_path).getroot() img_w int(root.findtext(size/width)) img_h int(root.findtext(size/height)) objects [] for obj in root.iter(object): name obj.findtext(name) # 类别名例如 rbc box obj.find(bndbox) x1 int(box.findtext(xmin)) # 左上角 x y1 int(box.findtext(ymin)) # 左上角 y x2 int(box.findtext(xmax)) # 右下角 x y2 int(box.findtext(ymax)) # 右下角 y objects.append({name: name, x1: x1, y1: y1, x2: x2, y2: y2, w: x2 - x1, h: y2 - y1}) return img_w, img_h, objectsroot.iter(object)会遍历 xml 下所有 object 节点比 findall 更能容忍中间层变化。红细胞图片里一张视野可能有几十个细胞所以 xml 中会出现多个 object 片段这段脚本会把它们全部解析出来并放入列表。w x2 - x1、h y2 - y1是 COCO 格式需要的宽高正好转换时能直接复用。COCO json 的结构和 xml 不一样它是“三个顶层数组”的 JSONimport json with open(coco/annotations.json, encodingutf-8) as f: coco json.load(f) # annotations 里每一条是一次标注 for ann in coco[annotations]: bbox ann[bbox] # [x, y, width, height] cat_id ann[category_id] # 指向 categories 里的 id image_id ann[image_id] # 指向 images 里的 id # categories 里保存类别 id 与类别名 for cat in coco[categories]: print(cat[id], cat[name])bbox的四个数字依次是左上角 x、左上角 y、框宽、框高注意它不是xmin, ymin, xmax, ymax。很多人转格式时在这一点上写错导致 mAP 一路掉到 0。COCO 的image_id不一定等于文件名数字映射时要先读images字段里的file_name再和 xml 文件名对齐。2.3 YOLO txt 的归一化坐标与类别索引YOLO 系列直接消费的 txt 标签更简单每行一个目标格式为类别索引 中心x 中心y 宽 高。解析如下with open(labels/001.txt) as f: lines f.readlines() for line in lines: parts line.strip().split() cls int(parts[0]) # 类别索引例如 0 代表红细胞 cx, cy, w, h map(float, parts[1:]) # 四个数值都是相对于图片宽高的比例范围通常在 0~1 之间一个文本文件里有多少行就代表这张图有多少个目标。坐标是归一化的真实像素中心点除以图片宽度得到cx除以高度得到cy。从 VOC 转 YOLO 的公式# 已知图片宽高 img_w, img_h x_center (x1 x2) / 2.0 / img_w y_center (y1 y2) / 2.0 / img_h box_w (x2 - x1) / img_w box_h (y2 - y1) / img_h yolo_line f{0} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}\n这里0是类别索引与训练配置里的names列表严格对应。如果类别名顺序改成[red_blood_cell]索引仍是 0流程没影响但如果后续往里加白细胞就必须先处理旧 txt否则会出现类别错位。数据集中单类红细胞时不太容易暴露这个问题换成多类任务就要格外小心。3. train_list.txt 与三个划分脚本的数据流压缩包里带了三个 Python 文件split_train_val生成ImageSets下txt文件划分脚本.py负责生成 ImageSets/Main 下的列表训练集、验证集、测试集划分脚本图片标签划分写入新文件夹.py把图片和标签一起拷进 train/val/test 目录训练集、验证集划分脚本图片标签划分写入新文件夹.py是去掉 test 的简化版本。三者配合起来就是两条典型路径先出 txt 列表再按列表同步拷贝图片和标签。3.1 split_train_val 生成 ImageSets 下的 txt这个脚本的作用是把train_list.txt里的所有样本随机打乱然后按比例生成仅含样本名的 txt。扩充后的代码大致如下import os import random random.seed(2024) # 固定种子保证每次划分一致 images [line.strip() for line in open(train_list.txt)] random.shuffle(images) train_ratio, val_ratio 0.8, 0.1 n len(images) train_end int(n * train_ratio) val_end train_end int(n * val_ratio) split_files { train: images[:train_end], val: images[train_end:val_end], test: images[val_end:], # 没有 test 的行会变成空文件 } os.makedirs(ImageSets/Main, exist_okTrue) for split_name, split_list in split_files.items(): with open(fImageSets/Main/{split_name}.txt, w) as f: for path in split_list: stem os.path.splitext(os.path.basename(path))[0] f.write(stem \n)random.seed是最容易忽略的参数不固定随机种子同一份数据集每次划分出来的训练集都不同模型对比就没有意义。脚本默认写的是文件名主干不含扩展名这样后续函数可以自己去.jpg或.png目录里匹配。train_ratio0.8, val_ratio0.1表示剩余 10% 作为测试集如果不需要测试集把val_ratio调成0.2再删掉 test 对应分支即可。脚本类型输出使用场景split_train_val 生成 txtImageSets/Main/train.txt 等先出列表再配合其他工具读取图片标签划分写入新文件夹train/、test/ 下的 imageslabels直接给 YOLO 的 data.yaml 使用只分 train/val 的简化版train/、val/ 下 imageslabels不需要测试集的快速实验3.2 图片与标签同步写入新文件夹的划分实现“标签划分写入新文件夹”脚本会把上一步生成的 txt 作为输入复制图片和对应的 yolo 标签到新目录。注意它不会自己去重新划分而是依赖ImageSets/Main下的列表文件。同步复制的核心代码如下import shutil from pathlib import Path def split_by_list(txt_path, src_images, src_labels, dst_root): # 从列表读取样本名并同步拷贝图片和标签 for stem in Path(txt_path).read_text().splitlines(): img_src Path(src_images) / f{stem}.jpg lab_src Path(src_labels) / f{stem}.txt # 训练/验证目录按 txt 文件名区分 split_name Path(txt_path).stem img_dst Path(dst_root) / split_name / images / img_src.name lab_dst Path(dst_root) / split_name / labels / lab_src.name img_dst.parent.mkdir(parentsTrue, exist_okTrue) lab_dst.parent.mkdir(parentsTrue, exist_okTrue) if img_src.exists(): shutil.copy(img_src, img_dst) if lab_src.exists(): shutil.copy(lab_src, lab_dst) else: print(fwarning: {stem} 缺少标签)这段代码的关键在于split_name Path(txt_path).stem它直接从 train.txt / val.txt 文件名推断输出目录避免硬编码 train、val。若只复制图片不复制标签训练时 YOLO 会在加载阶段报image without label警告严重时直接跳过样本。所以日志里出现“缺少标签”时要回退到train_list.txt检查样本名是否在 labels 目录中存在。标签文件的扩展名在这一步默认用.txt如果数据集中是.png需要把两处.jpg改成.png。注意扩展名不统一时split_by_list里的.jpg要和数据实际格式保持一致否则会出现大量缺少标签提示。3.3 划分后检查样本数、标签缺失与类别分布训练前我建议用三个命令快速验收wc -l ImageSets/Main/train.txt wc -l ImageSets/Main/val.txt find labels/train -name *.txt | wc -l第一行统计训练样本数第三行统计真实标签文件数。如果两者不一致说明部分样本没有被标注对 1000 张红细胞图片来说允许少量无目标的负样本但不能出现大量图片有标签而列表里没有的错位。更稳妥的办法是写一个 Python 脚本统计每类目标的边界框数量from collections import Counter counts Counter() for txt in Path(labels/train).glob(*.txt): for line in txt.read_text().splitlines(): cls int(line.split()[0]) counts[cls] 1 print(counts)最终输出形如Counter({0: 8123})单类数据集主要看总数和每张图平均框数。红细胞是高度密集的小目标单张 640x640 图片里出现几十个框很正常如果平均框数超过 100可以考虑把输入分辨率从 640 提到 960否则小细胞会挤在一起anchor 匹配不到足够的正样本。判断阈值时还要看图片原始尺寸不能只看标注框数量。4. 从环境搭建到训练命令Linux 和 Windows 两个版本的要点资源里的两份教程按系统拆开是合理的YOLO环境搭建Linux版本.html和YOLO训练教程Linux版本根据案例修改训练自己的数据集.html覆盖 Ubuntu 侧YOLO环境搭建Windows版本.html覆盖本地训练。两者的核心差别集中在驱动安装、conda 环境激活和路径写法上训练命令本身几乎一致。下面按一整套流程复述我通常会走的路。4.1 版本选择与依赖安装conda 和 CUDA 的坑Linux 侧常见步骤是# 在 Ubuntu 环境安装时先用 nvidia-smi 看驱动支持的 CUDA 版本 nvidia-smi # 创建独立的 Python 环境避免污染系统 Python conda create -n yolo python3.9 -y conda activate yolo # 安装 PyTorchcu118 表示 CUDA 11.8 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 再装 YOLO 相关依赖 pip install -r yolov5/requirements.txt配合资源里那份Linux之Ubuntu环境安装教程.html主要看的其实是前两步驱动是否已装、conda 是否在 PATH 中。Windows 侧用 conda 会更稳因为系统 Python 经常和 Visual Studio 工具链冲突conda create -n yolo python3.9 -y conda activate yolo pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118参数说明cu118与驱动有关新版 YOLO 教程一般推荐 cu118 或 cu121如果机器只有 CPU可以把--index-url删掉直接用 CPU 版 torch训练会慢很多但能先跑通流程。判断安装是否成功只用一条命令python -c import torch; print(torch.cuda.is_available())输出True才说明 GPU 可用。Windows 上常见坑是 conda 环境激活后命令行路径出现C:\Windows\System32与 conda 路径混排导致 pip 装到系统 Python 里解决办法是每次训练前先where python确认当前解释器位于环境目录。还要注意YOLO训练教程Windows版本.html里数据集路径最好写成D:/RBC_dataset而不是D:\RBC_dataset这样在 yaml 和 Python 字符串里都能少踩转义坑。4.2 data.yaml 与确认类别索引下面是一份可直接改用的 data.yaml# RBC_dataset/data.yaml path: D:/RBC_dataset # 数据集根目录Linux 下写 /home/user/RBC_dataset train: images/train # 训练图片相对路径 val: images/val # 验证图片相对路径 test: images/test # 测试图片相对路径可为空 nc: 1 # 类别数量 names: - rbc # 必须与 yolo 标签里的类别索引一致这段配置的重点不是nc而是names顺序。YOLO 对 txt 标签里的0会直接对应names[0]所以如果第 3 章脚本复制标签时把类别索引写成了 1这一行 names 里就必须把rbc放在第二个位置。红细胞数据只有一个类别仍建议保留names列表而不是只填nc因为训练日志、混淆矩阵和最终导出都要读 names。train、val使用相对路径时路径是相对于path根目录计算的如果训练时报Dataset not found先看输出里拼接后的绝对路径对不对八成是 path 那一行写错了。4.3 训练命令与断点续训数据集不走测试集时可以直接用 train/val 开启训练python train.py --data dataset.yaml --weights yolov5s.pt --img 640 --batch-size 16 --epochs 200 --patience 30如果用的是 YOLOv8等价命令是yolo detect train datadataset.yaml modelyolov8s.pt imgsz640 batch16 epochs200 patience30参数解释--img 640指输入边长为 640 像素红细胞目标小建议保留 640 或尝试 960但 batch-size 要相应减半以控制显存。--patience 30表示验证集指标连续 30 个 epoch 不上升就早停对 1000 张图像的数据集足够。训练中断时YOLOv5 用python train.py --resume runs/exp/weights/last.ptYOLOv8 用yolo detect train resumeTrue。恢复后 batch 和 img 参数都会从上次的权重文件里读出不需要重新设置。教程里的“根据案例修改训练自己的数据集”实际上就是改 data.yaml 的路径、nc 和 names再替换 train.py 的--data指向其余结构不用动。参数Linux 常见写法Windows 常见写法说明data--data dataset.yaml--data D:/dataset.yaml路径用正斜杠weights--weights yolov5s.pt同左预训练模型batch-size--batch-size 16同左8G 显存用 8img--img 640同左小目标可调 960提示先跑一个 50 epoch 的短实验确认 loss 曲线下降后再跑全量 200 epoch能省很多试错时间。5. 红细胞小目标检测的验证与结果复盘用同一个数据集训练后正式跑测试集之前要先在 val 上出一份评估结果。红细胞检测本质上是个小目标检测问题边框重叠频繁只看一个 mAP 数字会掩盖漏检和重复框两类问题。5.1 用混淆矩阵和 PR 曲线定位漏检YOLOv5 的评估命令是python val.py --data dataset.yaml --weights runs/train/exp/weights/best.pt --img 640YOLOv8 也可以单独执行yolo detect val datadataset.yaml modelruns/train/exp/weights/best.pt imgsz640输出会包含results.png混淆矩阵和PR_curve.png。在单类红细胞任务里混淆矩阵只有rbc与 background 两类。如果 background 被预测为 rbc说明有太多背景纹理被当成细胞这时优先提高置信度阈值或者在训练集中加入纯背景负样本而不是加数据增强。如果 rbc 被预测为 background常见原因是输入分辨率不够红细胞只有十几个像素640 尺度下特征图里被压缩到一两个格子召回率自然上不去。5.2 重叠细胞场景下的置信度与 NMS 阈值调整红细胞数据集里细胞之间经常大面积重叠NMS 设置不当会直接吞掉正确的框。默认conf-thres0.25, iou-thres0.45对稀疏场景没问题对红细胞建议先跑一遍python detect.py --source test_images/ --weights best.pt --img 640 --conf-thres 0.35 --iou-thres 0.4 --save-txtiou-thres调低会让重叠度高的两个框更难被合并但太低也会出现一个细胞被框两次的情况。我一般先在 val 上分别试 0.4 和 0.45比较mAP0.5如果两个值差距小于 0.01就选置信度更高的组合因为密集场景下精度的价值高于多框几个不明目标。另一个技巧是用--save-txt输出文本检测结果每行格式为class x_center y_center w h conf然后写脚本统计所有框的面积分布如果大量框面积集中在图像面积的 0.5% 以下说明模型在学小目标后续训练应保持--img 960如果面积分布集中在 5% 以上则当前场景不需要过高分辨率继续调低 NMS 阈值反而更快。本文还有配套的精品资源点击获取
返回列表