
简介淋巴细胞目标检测数据集是一套面向医学病理AI与目标检测开发者的专业资源聚焦病理切片中淋巴细胞Lymphocyte的精准定位任务适用于YOLOv5/v7/v8及YOLOv12等主流算法训练、医疗影像辅助诊断及免疫微环境研究。压缩包内含2000个文件其中1152个txt标注文件对应每张图片的YOLO格式边界框与类别标签846张jpg医学病理图像覆盖训练、验证、测试三部分另有yaml配置文件可直接用于模型工程配置docx说明文档辅助理解数据规范整体大小67.68MB。目前已有60人浏览学习可作为淋巴细胞检测、细胞计数与密度分析的实用数据集。数据集由医学专家校验标注兼顾细胞簇密集等复杂场景训练/验证/测试集划分明确下载后即可按YOLO流程开展训练与评估也为病理诊断辅助、癌症分析和医学教学提供直接支撑。1. 淋巴细胞目标检测数据集1152 张 HE 病理图先看懂再动手做病理目标检测的人应该都有体会找数据集比调模型还难。手头这份淋巴细胞目标检测数据集是直接从 HE 染色病理切片上切出来的瓦片图总计 1152 张训练集 580 张、验证集 290 张、测试集 282 张标注是 YOLO 格式类别只有一类——Lymphocyte淋巴细胞。它能直接喂给 YOLOv8/v12 这类检测器用于病理辅助诊断、免疫微环境评估和淋巴瘤相关研究的细胞定位。和常规目标检测数据集不同这里的难点不在类别多而在细胞密集、边界粘连、染色差异大。拿到手不要急着开训花半天把数据拆开看清楚后面能省下好几轮无效实验。2. 拆开数据集从文件名和标注文件里读出关键信息2.1 目录结构与文件命名的信息量先用标准姿势解压。注意一点路径里不要带中文和空格我一般统一放到/mnt/data/lymphocyte/这种纯英文路径下避免某些训练框架在读取时出现编码问题。解压后能看到三类文件jpg 原图、对应的 txt 标注文件以及一份数据集说明文档。图片文件名长这样CD3CD20_Lymphocyte_193_069632_081920_HE_png.rf.205a1a2f38d4bd428e126c506ca4a867.jpg这四个字段都藏着信息逐个拆开看CD3CD20免疫组化双标记。CD3 标记 T 细胞CD20 标记 B 细胞两者都属于淋巴细胞谱系所以数据集把标注类别统一归为 Lymphocyte没有细分 T/B。Lymphocyte类别名对应标注文件里的 class 0。193切片编号。把整个压缩包里的文件名过一遍能看到 167、193、205、222、275 等编号说明这批数据来自多张不同的全切片扫描不是一个病例的重复切块。069632、081920这个瓦片在原切片上的像素坐标分别是 X、Y。这个坐标信息后续做跨切片分析或者拼接回原图时非常有用建议先保留在文件名里不要训练时顺手改掉。HE_pngHE 染色原始格式是 pngRoboflow 导出时转成了 jpg。rfRoboflow 平台导出标记后面的长十六进制串是该图在平台上的唯一 ID。再看目录结构。解压后大概率是这样lymphocyte/ ├── train/ │ ├── images/ # 580 张 jpg │ └── labels/ # 与 images 同名的 txt ├── val/ │ ├── images/ # 290 张 jpg │ └── labels/ ├── test/ │ ├── images/ # 282 张 jpg │ └── labels/ └── 数据集说明.docximages 和 labels 平级文件名一一对应这是 YOLO 系列最标准的目录组织方式。原图尺寸我没记错的话在 2000 像素量级单张瓦片覆盖的是一小块组织区域。这种从全切片扫描上切瓦片的做法是医学图像检测的主流方案——整张切片可能上万像素直接送进网络不现实切成瓦片既能保住分辨率又让每个样本有独立标注空间。2.2 YOLO 标注里到底存了什么随便打开一个 txt 文件能看到每行五个数0 0.582031 0.447396 0.026042 0.032292第一个数是类别 ID这个数据集里只有 0对应 Lymphocyte。后面四个数依次是归一化后的中心点 x、中心点 y、宽度、高度。归一化是相对图片宽高的比例也就是说如果图片是 640x640这个框的像素中心就在(0.582031 * 640, 0.447396 * 640)框宽高为(0.026042 * 640, 0.032292 * 640)算下来约 16x20 像素。淋巴细胞在 HE 切片上直径大约 7-15 微米在 20 倍物镜下通常就 20-40 像素。这个量级放在目标检测里属于小目标范畴。后面选 imgsz 时要把这个数字记在脑子里640 的输入尺寸下一个 30 像素的细胞被压缩到原来的三分之一特征几乎看不出来。这是病理小目标检测和自然场景最大的差别也是后面踩坑的根源。提示如果你打算用这份数据集做跨切片的细胞密度分析文件名里的069632、081920坐标千万不要清洗掉。它们是瓦片在全切片上的定位锚点后续拼接热图或者按区域统计时缺了它们会非常被动。3. 训练前的体检用脚本校验标注、剔脏数据、看分布3.1 标注文件体检脚本先写一个 Python 脚本检查标注是否完整。常见做法是逐行解析 txt确认格式是否为五个浮点数、归一化坐标是否在 0~1 之间、宽高是否为正。import os from pathlib import Path img_dir Path(lymphocyte/train/images) lab_dir Path(lymphocyte/train/labels) bad [] # 格式异常的标注 empty [] # 空标注文件 counts [] # 每张图的目标数 for lab in lab_dir.glob(*.txt): lines [l.strip() for l in lab.read_text().splitlines() if l.strip()] if not lines: empty.append(lab.name) continue for ln in lines: parts ln.split() if len(parts) ! 5: bad.append((lab.name, field count)) break try: vals [float(p) for p in parts] except ValueError: bad.append((lab.name, nan)) break cid, cx, cy, w, h vals if cid ! 0: bad.append((lab.name, fclass {cid})) break if not (0 cx 1 and 0 cy 1 and w 0 and h 0): bad.append((lab.name, bbox out of range)) break counts.append(len(lines)) print(bad:, len(bad), empty:, len(empty)) print(avg objects per image:, sum(counts) / len(counts)) print(max objects:, max(counts)) print(bad samples:, bad[:10])逻辑说明脚本遍历 labels 目录下所有 txt把空文件单独记下来再逐行检查字段数和数值合法性最后统计每张图的框数。跑完重点看两个指标单张图目标数均值如果一张图里有几十上百个框说明这是密集细胞簇场景训练时要注意增强参数最大值尤其重要决定 mosaic 增强是否会造成目标重叠爆炸。参数说明这个脚本只输出报告不做任何清洗。异常情况先备份再决定剔还是留。空标注文件如果数量不多最省事的做法是从数据集中删掉对应图片如果想让模型学没有淋巴细胞的负样本需要单独放一个目录不要用 YOLO 标注格式硬塞。3.2 类别与框分布可视化单类别数据集没有类别不平衡的问题重点要看框的尺寸分布它直接决定你该用什么 imgsz。写一个统计脚本import numpy as np ws, hs [], [] for lab in lab_dir.glob(*.txt): for ln in lab.read_text().splitlines(): _, cx, cy, w, h map(float, ln.split()) ws.append(w) hs.append(h) ws, hs np.array(ws), np.array(hs) print(box width in px 640:, ws.mean() * 640, -, ws.std() * 640) print(box height in px 640:, hs.mean() * 640, -, hs.std() * 640)逻辑说明把所有归一化宽高换算到 640 尺度下的像素值。如果平均框尺寸在 20-40 像素附近就属于小目标主导建议 imgsz 直接上 1280或者至少用 960不能为了省显存降到 416。另外可以再算一下宽高比分布淋巴细胞接近圆形宽高比应该趋近 1。如果看到一堆极端长条框要么是标注质量问题要么是组织切片边缘的细胞被截断这两种情况处理方式完全不同。4. 拉起第一次训练数据集 yaml、参数设置和划分验证4.1 准备 YOLOv8/v12 能直接读的 dataset.yamlYOLO 系列训练入口是数据集的 yaml 文件。这份配置对 YOLOv8 v8 和 YOLOv12 都通用YOLOv12 只是换了网络骨架数据接口没变path: /mnt/data/lymphocyte train: train/images val: val/images test: test/images names: 0: Lymphocyte逻辑说明path指向数据集根目录train/val/test写的是相对于根目录的图片文件夹路径YOLO 会按同名机制自动找 labels 目录——把路径里的images替换成labels不需要单独配置标注路径。如果目录结构是 images 和 labels 平级这样写不会有问题。参数说明test字段加不加都能正常训练训练时会忽略它模型验完后单独用 test 目录做最终评测。names里类别名必须和标注文件里的 class 0 对应。如果原数据集的标注里写的是 0但 yaml 里只声明了 0没问题反过来把类别 ID 写成了 1训练会直接丢失全部正样本而且不会报错这类坑在第 5 章详细说。4.2 训练参数怎么定给一份我在类似病理数据集上常用的启动命令以 YOLOv8 为例YOLOv12 加载方式相同yolo detect train \ datalymphocyte.yaml \ modelyolov8s.pt \ imgsz1280 \ batch8 \ epochs150 \ lr00.01 \ mosaic0.5 \ hsv_h0.01 \ hsv_s0.3 \ hsv_v0.3 \ fliplr0.5 \ flipud0.5逻辑说明针对这个数据集imgsz1280是为了保住小目标。前面体检时算过框均值在 20-40 像素640 输入下压缩太狠。mosaic降到 0.5因为病理瓦片本身细胞密度高4 张图拼在一起后目标数量可能上百标注重叠严重模型容易学乱。hsv_h大幅降到 0.01 是重点——HE 染色的红紫配色有诊断语义过大变换色相会把染色特征彻底打乱模型学到错误的颜色关联。参数说明如果显存只有 12Gimgsz1280配batch8可能撑不住可以降到imgsz960或batch4。lr0对单类别任务可以再低一些0.005 起步更稳毕竟单类别收敛比多类别快学习率太大容易在后期震荡。flipud在病理小图上可以开切片方向不携带语义信息不像自然图像里上下翻转可能改变物体朝向。4.3 验证集合理性再确认上面 yaml 里的 train/val/test 是数据集作者分好的580/290/282。直接用没问题但建议先做一件事把文件名里的切片编号提取出来检查三个子集是否来自相同的切片。from collections import Counter from pathlib import Path def get_slide_id(name): # 文件名格式: CD3CD20_Lymphocyte_193_069632_081920_HE_png.rf.xxx.jpg return name.split(_)[2] for split in [train, val, test]: names [p.name for p in (Path(lymphocyte) / split / images).glob(*.jpg)] ids Counter(get_slide_id(n) for n in names) print(split, dict(ids))逻辑说明如果某个切片编号只在验证集里出现训练集完全没有说明验证集相当于一个未见过的染色背景域测试。这时 val 分数偏低不代表模型差只是数据分布存在偏移。反之如果某个切片 ID 同时大量出现在训练集和测试集测试分数会被虚高真正的部署场景会翻车。这一步虽然不改变任何训练参数但能帮你正确解读后面每一轮实验的指标。这个坑展开讲就是第 5 章的内容。提示看到 val 分数虚高别高兴太早。医疗数据集做划分时同一个病例的切片瓦片同时进训练和验证是常态严格按切片分组是唯一可靠的划分原则。5. 避坑记录病理小目标检测的六个真实翻车现场5.1 训练集图片数对不上空标注文件被静默过滤现象数据集说明写训练集 580 张YOLO 训练日志里实际加载的图片数只有 560 多凭空少了几十张。原因部分 txt 标注文件是空的一个目标都没有。Roboflow 导出时对无目标图片的处理策略不稳定这些图片在 YOLO 数据集扫描阶段被静默跳过日志里不会出现任何警告。解决用前面 3.1 的体检脚本把空文件打出来。逐个确认后最简单做法是从数据集中删掉对应图片保证每张图都有标注。如果你想让模型学没有淋巴细胞的负样本把空标注图单独放进一个不带 labels 的目录用额外的背景图集做验证不要混在标准 YOLO 格式里。5.2 验证集和测试集串片按病例分组而不是全局随机现象第一次训练结束val mAP 到了 0.85以为模型已经很能打换到真实切片推理却掉到 0.6 以下像换了个模型。原因这 1152 张图来自多张全切片如果划分时是全局随机同一个切片的多个瓦片可能同时进了训练集和验证集。模型在验证集上存在严重的半记忆效应相当于开卷考试真实部署遇到的是完全没见过的切片染色风格成绩自然崩。解决严格按切片编号分组所有来自切片 193 的瓦片只能落在同一个子集。如果原始划分不满足建议重划把 1152 张按切片 ID 分桶再按 7:2:1 切。训练集至少包含 3-4 个完整切片验证集 1 个测试集留 1 个完全没见过的切片。从那以后我拿到任何病理数据集第一件事就是按切片 ID 检查划分不会再被虚高指标骗。5.3 小目标漏检图像缩放吃掉了细胞现象imgsz640 训出的模型在验证集上 recall 偏低特别是那些和背景颜色接近的弱染色淋巴细胞框直接消失怎么调 conf 阈值都拉不回来。原因病理瓦片原图可能接近 2000x2000缩到 640 时一个 30 像素的淋巴细胞变成约 10 像素特征基本丢失。模型没有足够信息区分淋巴细胞核和背景里的其他细胞核。解决imgsz 直接上 1280。如果显存不够用 SAHI 这类切片推理工具把大图切成 640 有重叠的块分别推理最后合并框。两种方式可以组合使用训练用 960推理用 SAHI 切块。注意 SAHI 的切块重叠率建议设 0.2-0.3太低会导致边缘细胞被截断。5.4 染色差异让模型认色不认形颜色归一化现象模型在同一中心医院的数据上 mAP 不错换到另一家医院的切片上淋巴细胞一个都检不出来全部漏检。原因HE 染色受切片厚度、染色时间、扫描仪参数影响不同批次的色彩分布差异巨大。YOLO 训练默认的 HSV 增强幅度按自然图像设置如果只用原始颜色训练模型会把染色深浅当作判别特征一旦颜色分布漂移就失效。解决训练前对全部图片做染色归一化用 Macenko 方法把每张图的染色向量映射到参考图的统计分布。另一种思路是训练时把hsv_h改到很小、hsv_s适当增大模拟染色深浅变化但不动色相。两种都试过的情况下第一种在真实场景里的泛化收益更明显因为它是确定性的预处理不依赖随机增强碰运气。5.5 密集细胞重复框NMS 的 IoU 阈值要降现象推理时同一个细胞出两三个框尤其是成簇的淋巴细胞区域几个框置信度还都不低NMS 没有合并掉。原因细胞密集且边界模糊模型输出的候选框 IoU 本就偏高YOLO 默认 NMS 阈值 0.7 在密集小目标场景下不足以充分合并重复框。自然图像里两个目标 IoU 超过 0.7 基本是同一目标但细胞簇里不同细胞之间 IoU 超 0.5 很常见。解决推理时把iou阈值降到 0.4-0.5。如果还压不住重复框用加权框融合WBF替代 NMS把重叠框按置信度加权平均得到更贴近真实细胞边界的框。代价是推理时间变长但病理分析要的是准确计数不是实时性。5.6 类别编号写错单类别也要从 0 开始查现象训练日志一切正常loss 在下滑但验证阶段显示 class 0 的 AP 是 0标注矩阵里多出一行空类。原因YOLO 要求的类别编号从 0 开始。如果之前处理标注时把 Lymphocyte 写成了 1比如 CSV 转 YOLO 格式时多写了一位而 yaml 里只声明了 0训练会静默丢失全部正样本。模型收敛但学不到任何目标指标全是 0诡异的是训练过程完全不报错。解决训练前跑 3.1 的体检脚本时把cid ! 0的样本全部拦下来。训练日志出现所有类别 mAP 全为 0 时第一件事先查标注文件的 class ID而不是调学习率、改增强参数。这是单类别数据集上最容易栽的坑因为看起来训练一切正常实际上模型什么都没学到。6. 进阶用法把检测结果变成细胞计数与密度热图6.1 推理输出转计数检测完只是第一步医学场景真正要的往往是这片区域里有多少个淋巴细胞。用 YOLO 推理结果直接统计相当简单from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) results model.predict(test/images, conf0.25, iou0.5, imgsz1280, verboseFalse) for r in results: n len(r.boxes) print(r.path, lymphocyte count:, n)逻辑说明一行推理加一个len统计就得到了每个瓦片里的淋巴细胞绝对数量。关键在于 conf 和 iou 阈值的配合病理切片背景复杂conf 设太高会漏掉弱染色的细胞0.2-0.3 是常见区间iou 按第 5 章的坑调整到 0.5配合降过阈值的 NMS 才能拿回稳定计数。6.2 密度热图对每个瓦片输出一个密度值再拼接成整张切片的密度热图是免疫微环境分析里常用的一步能看到淋巴细胞在组织中的聚集区域。简单实现是给每个检测框中心画高斯点import numpy as np from PIL import Image img Image.open(some_tile.jpg).convert(RGB) heat np.zeros(img.size[::-1], dtypenp.float32) for box in results[0].boxes.xyxy.cpu().numpy(): x1, y1, x2, y2 box cx, cy int((x1 x2) / 2), int((y1 y2) / 2) heat[cy - 8:cy 9, cx - 8:cx 9] 1.0 heat (heat - heat.min()) / (heat.max() - heat.min() 1e-9) * 255 Image.fromarray(heat.astype(np.uint8)).save(density.png)逻辑说明为每个细胞检测框的中心生成一个局部计数累计成密度图可以直接看到淋巴细胞在组织切片上的聚集区域。更规范的做法是用 scipy 的gaussian_filter做平滑或者每个框按其宽度生成对应标准差的高斯核能得到分布更连续的热图。如果要把多张瓦片拼回整张切片记得用文件名里的069632、081920坐标做拼接锚点按原坐标位置贴回去再统一做热图不然瓦片间会出现错位。从第一次在这个数据集上翻车到现在我养成了一个习惯拿到任何病理数据集先做三件事——体检标注文件、按切片 ID 检查数据划分、跑一遍颜色分布统计全部确认后再谈训练参数。这三步看起来不如调参那么高级但省掉的无效实验时间最实在希望帮到你。本文还有配套的精品资源点击获取