资讯动态

细胞活性检测数据集1298张2类标签VOC+YOLO格式目标检测实战解析

发布时间:2026/10/1 11:04:30 来源:尧图企业网站定制
简介细胞活性检测是生物医学图像分析中的典型任务本数据集围绕活细胞与死细胞的识别标注而构建共含1298张jpg图像以矩形框形式标注Dead与Live两个类别总框数31332个适合用于目标检测与细胞状态分类等视觉模型的训练。数据集同时提供Pascal VOC格式xml标注和YOLO格式txt标注便于在不同深度学习框架中直接使用无需自行转换。压缩包共2000个文件其中1298个xml标注文件、702个txt标注文件整体大小32.45MB体积紧凑下载与解压都很便捷。每张图片均有精确对应的标注文件标注由labelImg工具完成边界框布局合理可帮助研究者节省数据清洗与标注时间快速进入模型训练环节。目前该资源已有197人学习下载适合生物医学图像方向的学生、科研人员以及工业质检场景的算法工程师使用。1. 细胞活性检测数据集1298张2类标签先把“数细胞”这件事拆清楚做药物筛选或者细胞实验的人应该都有这种体验真正耗时间的不是加药、培养而是趴在显微镜前数细胞。一张图里几十上百个细胞活的和死的混在一起人工数一遍至少几分钟数到后面还会眼花。这个【目标检测数据集】细胞活性检测数据集1298张2类标签VOCYOLO格式.zip解决的正是这个问题能不能训练一个目标检测模型自动把视野里的活细胞和死细胞分别框出来、数出来。1298张、2类标签、同时给了VOC和YOLO两种格式这个体量在目标检测数据集里算小的但用在细胞活性检测这个细分场景里恰好处于“不够大到直接训练、又够做微调”的尴尬区间。能不能用好取决于你对标注格式的理解、训练策略的取舍以及对数据质量的判断。这篇就按我平时拿到一个检测数据集后的处理顺序来讲先拆格式、再谈训练、最后说坑。2. 解构数据集压缩包VOC 与 YOLO 两套标注格式的目录结构与换算关系解压这类数据集压缩包后常见的目录结构是分两套并存的VOC 一侧放AnnotationsXML 注释文件和JPEGImages原图YOLO 一侧放images和labels。两套描述的是同一批图片、同样的框只是存储方式不同。先搞清楚这两套格式的对齐关系后面训练才不会莫名其妙地出现“框全偏了”。2.1 VOC 格式XML 注释文件与 bndbox 的读取方式VOC 格式的核心是每个 XML 文件对应一张图。解压后打开任意一个 XML你会看到类似下面的结构annotation folderJPEGImages/folder filenamecell_001.jpg/filename size width960/width height640/height depth3/depth /size object namelive/name bndbox xmin142/xmin ymin88/ymin xmax198/xmax ymax132/ymax /bndbox /object object namedead/name bndbox xmin310/xmin ymin270/ymin xmax355/xmax ymax305/ymax /bndbox /object /annotation这里的name是类别名bndbox里存的是绝对像素坐标xmin/ymin是框的左上角xmax/ymax是右下角。注意 VGG 标注工具和 LabelImg 导出的 VOC 坐标通常是 0 基的也就是左上角从 0 开始计数转 YOLO 时不需要额外减 1但有些标注平台导出时从 1 开始不统一会导致中心点算偏 1 到 2 个像素。对细胞这种小目标来说1 到 2 像素的偏移可能就让框从“包住细胞”变成“切掉细胞边缘”。size里的宽高必须和实际图片一致。有的压缩包在预处理阶段被缩放过XML 里却还留着原始尺寸这种不一致会在转 YOLO 时让所有框错位。拿到数据集第一件事是抽样检查 XML 里的宽高和 PIL 读出来的图片尺寸是否对得上。2.2 YOLO 格式归一化坐标 txt 与类别文件对应关系YOLO 格式把同一张图的标注存在同名 txt 文件里放在labels目录下。图片是cell_001.jpg标签就是cell_001.txt。每一行代表一个目标格式是固定的五列0 0.177083 0.171875 0.058333 0.068750 1 0.346354 0.449219 0.046875 0.054688第一列是类别索引从 0 开始。第二、三列是目标中心点的 x、y 坐标第四、五列是框的宽和高。这四个值全部做了归一化也就是除以图片宽度和高度后得到的 0 到 1 之间的小数。所以 YOLO 格式里不存绝对像素它依赖“当前图片尺寸”才能还原出真实像素框。如果你换了图片尺寸训练标注不需要改模型输出的坐标也是归一化的但做可视化验证时要用原图尺寸乘回去。类别索引和类别名的对应关系由数据 yaml 文件里的names列表决定不是 txt 本身能看出来的。这一点在混合多个数据集时最容易踩坑两个数据集的类别列表顺序不一样直接合并会导致类别错乱。2.3 两种格式的相互转换一个脚本同时保住两类坐标精度不管压缩包里给的是哪种格式训练前我都建议先统一转成 YOLO 格式再抽几张图可视化确认。下面是一个把 VOC 转成 YOLO 的 Python 脚本我用它处理过好几套标注不统一的数据集。import xml.etree.ElementTree as ET from pathlib import Path voc_dir Path(Annotations) img_dir Path(JPEGImages) yolo_dir Path(labels) yolo_dir.mkdir(exist_okTrue) # 类别名到索引的映射顺序一定要和后续训练 yaml 的 names 一致 class_map {live: 0, dead: 1} for xml_path in voc_dir.glob(*.xml): tree ET.parse(xml_path) root tree.getroot() # 拿 XML 里记录的宽高做归一化分母 size root.find(size) img_w float(size.find(width).text) img_h float(size.find(height).text) lines [] for obj in root.findall(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) # 转成归一化中心点与宽高YOLO 要求值在 [0, 1] 区间 cx (xmin xmax) / 2.0 / img_w cy (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h # 越界保护细胞框偶尔会超出图像边缘 cx min(max(cx, 0.0), 1.0) cy min(max(cy, 0.0), 1.0) w min(max(w, 0.0), 1.0) h min(max(h, 0.0), 1.0) lines.append(f{class_map[name]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) if lines: yolo_dir.joinpath(xml_path.stem .txt).write_text(\n.join(lines) \n)脚本的逻辑不复杂遍历每个 XML把bndbox的绝对坐标转换成归一化的cx, cy, w, h按class_map映射类别索引写入 txt。有两个容易被忽略的细节一是归一化时除以的是img_w和img_h不是同一尺寸宽高不能混用二是只有完全无效的标注才跳过生成空 txt空 txt 在 YOLO 训练中会被忽略不会报错但也不贡献损失。转完之后不要急着训练抽 10 张图做叠加验证。用 OpenCV 读原图再把 txt 里的归一化坐标乘回图片尺寸画矩形框肉眼确认框是否紧贴细胞边缘。这一步十分钟能省下后面几个小时的排查时间。压缩包里如果自带标注工具导出的classes.txt建议先打开看类别顺序常用于目标检测的标注工具LabelImg、CVAT、X-AnyLabeling 这类导出的类别顺序未必一致这是坐标之外最容易出问题的地方。3. 用这个数据集训练检测模型划分、anchors 与超参的落地配置数据集拆清楚之后下一步是把训练跑起来。1298 张图、2 类目标常见做法是选 YOLO 系列的小模型n 或 s 级做迁移学习而不是从零训练。小模型对这个规模的数据量更友好训练速度快显存占用低在细胞检测这种目标尺寸小、类别简单的场景下效果往往不比大模型差。3.1 训练集/验证集划分1298 张如何分配才不虚高 mAP很多人在这一步直接随机切 90%/10%然后发现验证集 mAP 0.9一到实际拍摄的新图就掉到 0.6。问题多半出在随机划分上细胞活性检测图像的同一批次实验往往连拍多张相邻帧里细胞的位置和状态高度相似随机划分会把同一组序列的图分到训练集和验证集造成数据串集。模型记住的是这批实验的背景而不是细胞本身的特征。我一般按文件名前缀或拍摄批次分组同一组的图要么全进训练集要么全进验证集。一个简单的实现是用文件名中的分组标识做 group shuffleimport random from pathlib import Path import shutil train_dir Path(train) val_dir Path(val) train_dir.mkdir(exist_okTrue) val_dir.mkdir(exist_okTrue) # 假设文件名格式是 exp01_001.jpg取前缀 exp01 作为分组 id images list(Path(images).glob(*.jpg)) groups {} for img in images: group_id img.stem.split(_)[0] groups.setdefault(group_id, []).append(img) items list(groups.items()) random.shuffle(items) split_idx int(len(items) * 0.85) train_groups dict(items[:split_idx]) val_groups dict(items[split_idx:]) for group_id, imgs in train_groups.items(): for img in imgs: shutil.copy(img, train_dir / img.name) label Path(labels) / (img.stem .txt) if label.exists(): shutil.copy(label, train_dir / label.name) for group_id, imgs in val_groups.items(): for img in imgs: shutil.copy(img, val_dir / img.name) label Path(labels) / (img.stem .txt) if label.exists(): shutil.copy(label, val_dir / label.name)分组划分牺牲了一部分验证集和训练集的相似性换来的是验证指标更接近真实使用场景。1298 张按 8:2 或者 8.5:1.5 划分都行验证集不低于 150 张比较稳妥。如果压缩包里某些组的图片数量差异很大先看一眼每组张数的直方图别让某个大组独占验证集。3.2 锚框与图像尺寸细胞是小目标别拿默认参数硬上细胞在 640×640 的输入尺度下通常只有 20 到 50 像素属于典型的小目标。如果用 COCO 预训练权重里默认的 anchors 直接开训初始锚框偏大梯度更新前期会有大量浪费的迭代。常见做法是先用 k-means 在训练集的标注框上重新聚类 anchorsYOLO 系工具里大多内置了自动锚框计算训练时会根据数据重新聚类不需要手工指定。如果你用的版本默认关闭了自动锚框建议在训练前跑一次聚类把锚框输出配置到模型 yaml 里。输入尺寸方面如果显存允许12G 以上把imgsz从 640 提到 960小目标召回率会有肉眼可见的改善显存紧张就保持 640但要注意测试时也用同一尺寸不要训练 640、推理 1280输出坐标的尺度习惯完全不同。细胞密集的图像里细胞互相粘连标签框之间重叠严重这会直接影响 NMS 的效果后面避坑章会专门讲。3.3 训练启动命令与关键回调一个可复现的 YOLO 训练流程数据准备好后先写数据 yaml。以下面的内容创建cell.yamlpath: /path/to/cell_dataset train: train val: val nc: 2 names: 0: live 1: deadpath指向数据集根目录train和val是相对路径names的类别顺序必须和标签 txt 里第一列的索引完全一致。这里最容易犯的错是看到压缩包里有classes.txt就直接抄顺序但标签文件里的索引可能早就按另一个顺序生成过了两个对不上时训练不会报错损失照常下降但预测结果里 live 和 dead 是反的。训练命令以 YOLOv5/v8 系列的写法为例大同小异python train.py --data cell.yaml --weights yolov8n.pt --epochs 100 --batch 16 --imgsz 640 --patience 15 --workers 4几个关键参数--weights用预训练权重做迁移学习而不是随机初始化--epochs在 1298 张的小数据集上 80 到 120 就够多了必过拟合--batch建议不要小于 8后面避坑章详解--patience设为 10 到 20验证集指标连续不涨就提前停。训练过程中看两个曲线train/cls_loss是否平稳下降val里的mAP50是否在 30 到 50 个 epoch 后开始爬升。如果mAP50从第 10 个 epoch 就不动先别调模型回看数据划分和标签质量十次里有八次问题出在数据端。4. 小样本细胞检测的 5 个翻车现场现象、原因与处理1298 张属于小样本训练中遇到的问题和大数据集完全不是一个风格。这里整理我反复踩过的 5 个坑每一条都是“现象先说、原因定位、给解决路径”的三段式。4.1 活细胞与死细胞边界模糊mAP 停在 0.6 上不去现象训练 loss 正常下降但验证集 mAP50 卡在 0.6 左右死活上不去。 原因细胞活性检测本身的标注口径问题。很多细胞在图像里处于“将死未死”的状态台盼蓝染色后颜色深浅介于活细胞和死细胞之间不同标注员对边界的判断不一致。同一个细胞在相邻两帧里一个标注员标成 live另一个标成 dead模型学到的类别边界是模糊的。 解决先把训练集中置信度最低的 200 个验证集样本导出人工复查标签。发现争议样本后不是简单删掉而是统一标注规则只标形态明确可辨的边界模糊的细胞要么不标、要么单独建一个 ignore 类别。更实际的做法是在标注阶段的作业规范里写明“核染色明显深于背景才算 dead”把主观判断收敛为可执行的标准。4.2 类别不平衡死细胞占比低导致 recall 明显偏低现象混淆矩阵里 dead 的 recall 只有 0.4live 却是 0.9。 原因培养皿里本来活细胞就远多于死细胞1298 张图里 dead 类别的框可能只有 live 的五分之一模型把大部分容量用在了学 live 上。 解决先不要动模型结构加类别权重是最直接的手段。YOLO 的 loss 配置里通常可以给每个类别单独设cls系数把 dead 的权重提到 live 的 2 倍。如果提升不明显再考虑对 dead 样本做过采样或者简单复制 dead 占比高的图进训练集。需要注意过采样倍数别超过 3否则模型会开始记忆重复样本的噪声。4.3 转换坐标后框偏移问题出在归一化时用错了分母现象训练前可视化叠加图时一切正常训练后推理框却整体偏移 30 到 50 像素。 原因这种翻车在格式转换阶段就已经埋下了。很多人转完只抽查了训练集中图片尺寸和标注尺寸一致的样本没注意到压缩包里混入了横幅竖幅不同的图。VOC 转 YOLO 时如果某张图的 XML 里记录的是原始尺寸但 JPEGImages 里的图被预处理脚本重压缩过归一化坐标算出来就是错的。模型在错误标注上训练推理时对边界框的预测自然会漂移。 解决转换脚本里加一道断言用 OpenCV 读取真实图片宽高和 XML 里的size对比不一致就打印文件名并跳过。血的教训是不要信任压缩包里的任何中间文件以实际读入的像素为准。4.4 验证集指标虚高随机划分把同一视野的细胞分进了两个集合现象验证集 mAP 0.92部署到新拍摄的视频上 mAP 掉到 0.6。 原因这就是 3.1 里说的数据串集。细胞视频帧之间高度相似随机划分后验证集里混入了训练集相近的帧模型在验证集上表现好是“记住了”不是“学到了”。 解决严格按文件前缀分组划分推荐的做法是直接读文件名中的实验批次字段。实在没有批次信息就按拍摄时间戳做时间顺序划分前 85% 训练、后 15% 验证。这样验证集模拟的是“未来一批实验”指标才有参考价值。4.5 BN 崩溃与训练发散batch size 太小导致的梯度问题现象训练前 5 个 epoch loss 正常第 6 个 epoch 突然变成 nan或者 mAP 掉到 0。 原因batch size 设成了 2 或 4BN 层统计量在那么少的样本上极不稳定方差被拉到异常大梯度直接溢出。 解决细胞检测图像里目标密集小 batch 也确实能跑但不要把 BN 层的命运交给单卡小 batch。显存有限就降imgsz到 480 或 512保证 batch 至少 8最好 16。另外可以冻结前几层的 BN 参数让它们保持预训练统计量。遇到 loss 已经变成 nan 的就别想着接着训了改参数重启。5. 用数据可视化反推标注质量训练前先检查这三张图很多人拿到数据集第一件事就是开训结果翻车后回头检查数据才发现标注早就出了问题。我现在的习惯是训练前花半小时做三张图把标注质量定性看清楚省下的调试时间远超半小时。5.1 按类别统计框数量与尺寸分布第一张图是每个类别的标注框数量柱状图和框宽高的散点分布。先统计再确认这一步不需要模型参与。import glob import matplotlib.pyplot as plt datasets glob.glob(train/labels/*.txt) stats {0: [], 1: []} for txt_path in datasets: for line in open(txt_path): parts line.strip().split() if len(parts) 5: continue cls int(parts[0]) w float(parts[3]) h float(parts[4]) stats[cls].append((w, h)) fig, axes plt.subplots(1, 2, figsize(10, 4)) for cls, points in stats.items(): ws [p[0] * 640 for p in points] # 按 640 换算成像素尺寸 hs [p[1] * 640 for p in points] axes[0].scatter(ws, hs, s2, alpha0.5) axes[0].set_xlabel(box width (px)) axes[0].set_ylabel(box height (px)) axes[1].bar([live, dead], [len(stats[0]), len(stats[1])]) plt.tight_layout() plt.savefig(dataset_inspect.png, dpi150)这段代码读训练集所有 txt统计每个类别的框宽高和数量。散点图上如果发现大量框集中在 15 像素以下说明目标非常小需要调高imgsz或者考虑切图训练柱状图如果两类数量差距超过 5 倍后面就要做类别权重。5.2 用标注叠加图核对边界样本第二张图是原图和标注框的叠加直接目视检查。选图时别只挑前几张用随机数抽 30 张覆盖不同批次、不同光照条件的。OpenCV 画框时注意归一化坐标乘回原图尺寸import cv2 img_path train/images/cell_042.jpg label_path train/labels/cell_042.txt img cv2.imread(img_path) h, w img.shape[:2] colors {0: (0, 255, 0), 1: (0, 0, 255)} for line in open(label_path): cls, cx, cy, bw, bh map(float, line.strip().split()) x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), colors[int(cls)], 2) cv2.imwrite(overlay_cell_042.jpg, img)叠加图里常见的三种问题框比细胞大太多、两个类别的框互相重叠、本该标出的细胞漏标。框大太多多数是标注工具里拉框时没贴边重叠框在密集细胞场景下可以容忍但重叠比例超过 30% 会影响 NMS 训练时的正负样本分配漏标只能肉眼查没有捷径。这里查出来的问题记录成文档反馈给标注方比自己在代码里修补透明得多。5.3 混淆矩阵与置信度分布判断模型是否只学到了“好认的细胞”训练结束后看混淆矩阵有人发现每行的值加起来不是 1以为脚本计算错了。其实这是混淆矩阵的常见设计行归一化和列归一化是两个模式行归一化时每行和为 1列归一化时每列和为 1背景列还会占用一部分比例所以“总合不唯一”是正常的不是 bug。更值得关注的是置信度分布。把验证集预测结果按置信度从 0.5 到 0.95 切几个区间统计每个区间的命中率和误检数。如果高置信度区间0.9 以上命中率很高、但低置信度区间误检一大堆说明模型只学会了容易区分的细胞对那些处于活死边界的细胞没有泛化能力。这时可以把置信度阈值从默认的 0.25 调高到 0.5 甚至 0.6用召回率换精度或者回到 4.1 的标注口径问题上重新处理训练集。6. 让模型反哺标注用第一轮预测结果做二次校验迭代两轮比一次标满更划算这个数据集体量小一次训练不会直接达到可用水平。我惯用的收尾技巧是用第一轮模型对原始图片做预测把高置信度结果转成伪标签再让标注员修正而不是从头画框。一轮迭代下来比硬标几百张新图省一半时间而且标注口径会因为“看到模型预测结果”而变得更统一。流程分三步。第一步对新增的同一批次未标注图片做推理导出 YOLO 格式的预测结果python predict.py --weights best.pt --source new_images/ --save-txt --save-conf第二步写一个简单脚本把置信度拆档大于 0.9 的直接并入训练集0.6 到 0.9 的生成带框图片让标注员只做修改低于 0.6 的丢弃。第三步把修正后的标签合并回训练集重新训练。合并时注意类别索引仍按原来的names顺序不要因为新增样本重建索引。这个做法还有一层隐藏收益第一轮模型暴露出来的低置信度样本往往就是标注标准最模糊的边界样本。你不需要自己去几千张图里翻找模型会帮你把这些样本挑出来标注员只需要针对这些“刁钻样本”讨论并统一规则。我最早做这类项目时一口气标完上千张才开始训练后来改成先标 300 张训练出第一版、再预测反哺标注整体效率高了不少。这个小技巧也适用于其他小样本领域的数据集。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑