ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

血细胞检测数据集实战:从YOLOv8训练到密集小目标切片推理

血细胞检测数据集实战:从YOLOv8训练到密集小目标切片推理 简介这是一份专为计算机视觉与医学图像分析场景准备的血细胞检测数据集面向算法工程师、研究人员及医学生用于训练目标检测与分类模型。压缩包共1753个文件其中876个txt标签文件与874张jpg图像一一对应另含yaml配置、license许可说明及md文档整体大小约11.81MB结构清晰便于快速上手。数据集已按train、valid、test划分可直接用于构建卷积神经网络在TensorFlow或PyTorch等框架下训练识别红细胞、白细胞、血小板等血细胞类型并完成模型调参与泛化评估。已有150人学习下载适合在血细胞自动识别、异常检测及医疗影像辅助诊断等课题中作为基准数据借助配套的README等说明文档还可降低理解数据格式与标注规则的门槛对贫血、白血病等疾病的早期筛查研究具有参考价值。整体来看这份数据集的目录组织与配套文档也为入门者提供了低成本实践医学图像识别项目的良好起点。1. 血细胞检测数据集.zip医学影像目标检测里最典型的密集小目标考题你从同事手里接过来一个血细胞检测数据集.zip解压后不是现成的红色图片文件夹而是几十张血涂片显微图像和同样多的XML标注。这正是医学影像自动化检验最常见的起点用目标检测模型把白细胞、红细胞、血小板的位置和类别找出来替代人工镜检计数。它解决的是血常规检验中的识别与定位问题适合做医学影像算法、检验科自动化和医疗AI落地的人。反直觉的地方在于这类数据集里模型结构反而不是瓶颈密集的小目标和极度失衡的类别分布才是真正决定你能不能跑通的因素。2. 解压血细胞检测数据集之前先搞清楚格式、规模和标注可信度拿到血细胞检测数据集.zip之后我建议你先别急着 unzip 然后直接训练。这个任务和你平时接触的车辆检测、行人检测差别很大血涂片里单个目标很小类别分布极度不均衡标注是否可靠直接决定后面所有工作的价值。我见过不少团队在数据集上跑通了 YOLOv8却在换一个染色批次后全线翻车问题大多出在数据准备阶段。这一章先讲清楚怎么判断一个血细胞数据集能不能用、用什么姿势解压、解压之后应该先检查什么。2.1 血细胞检测为什么不能拿通用数据集直接练血细胞检测的典型输入是血涂片在显微镜高倍镜下的图像一个视野里几十到几百个细胞红细胞呈双凹圆盘状白细胞带核血小板尺寸更小。目标检测模型本身不挑领域COCO 预训练权重也能迁移过来但关键差异在目标和分布。COCO 里最常见的 person 占几百像素而血涂片单个红细胞在 4000×3000 原图里可能只有 30×30 像素血小板更小常常只有十几个像素。直接套用通用目标检测流程第一轮训练出来的模型几乎只会把大片红色区域当成红细胞对白细胞则完全无视。另一个问题是类别比例。血液中白细胞、红细胞、血小板的数量相差几个数量级反映到标注文件里可能就是 RBC 有几千个框WBC 只有二十几个框。如果你不干预采样模型在损失函数里就会被红细胞统治WBC 的召回率趋近于 0。这也是为什么拿到血细胞检测数据集.zip后最先做的是统计类别分布而不是马上训练。我把这类检查叫“数据体检”30 秒就能发现后面可能翻车的地方。在 BDD100K 这类驾驶数据集上成立的训练流程到了血细胞检测上往往要改的不只是路径还有整套采样策略。2.2 一个血细胞数据集 zip 解压后通常有什么常见做法是解压到独立目录我一般先把压缩包重命名成英文小写路径避免后面 Shell 和 Python 在处理中文路径时出问题。如果你接触过 COCO2017 数据集的结构会对 images 与 annotations 的分离模式很熟悉但血细胞检测数据集更常见的是 VOC 风格少量是 YOLO 风格或 COCO 风格。解压命令很简单# Linux 下解压血细胞检测数据集.zip-d 指定解压目录 unzip blood_cell_dataset.zip -d blood_cell_dataset # 如果解压出来的文件名是乱码说明压缩包在 Windows 下用 GBK 编码打包 unzip -O CP936 blood_cell_dataset.zip -d blood_cell_dataset解压之后目录结构通常是这几种之一。VOC 风格有 JPEGImages、Annotations、ImageSetsCOCO 风格只有 images 和一个 annotations.jsonYOLO 风格已经处理好 images 和 labels。血细胞数据集中用 LabelImg 标注的 VOC 风格最常见因为标注工具默认就是导出 XML。三种格式各有特点直接影响后续转换脚本怎么写。格式文件组织常见配套文件你需要注意的地方VOC XML一张图对应一个 XMLImageSets/Main/train.txt、val.txt检查是否有缺失 XML 或多余 XMLCOCO JSON一个 JSON 索引所有图instances_train.json、instances_val.json确认类别 id 是否连续YOLO txt一张图对应一个 txtimages/ 与 labels/ 同名检查是否存在没标注的图如果你看到 ImageSets/Main 里有 train.txt 和 val.txt说明作者已经帮你划分过数据集如果没有就得自己做划分。VOC 的每个 XML 独立描述一张图脚本处理起来方便但也更容易出现标注缺失和格式不一致所以解压后我第一件事是检查是不是每个 XML 都有对应的图片。这一步不需要训练写个小循环扫一遍就行。2.3 跑一个体检脚本30 秒知道数据集能不能用这里给一个我常用的体检脚本只读 XML不做任何修改。你要改的只有路径变量# inspect_blood_cell.py # 不要急着训练先统计类别数、框数和图像尺寸 import glob import xml.etree.ElementTree as ET from collections import Counter annotations glob.glob(annotations/*.xml) class_counter Counter() box_count 0 image_sizes [] for ann in annotations: tree ET.parse(ann) root tree.getroot() # 部分数据集的 XML 里没有 size 节点这里做一层保护 if root.find(size) is not None: w int(root.findtext(size/width)) h int(root.findtext(size/height)) image_sizes.append((w, h)) for obj in root.iter(object): name obj.findtext(name) if name is not None: class_counter[name] 1 box_count 1 print(样本图像数:, len(annotations)) print(标注框总数:, box_count) print(类别分布:, dict(class_counter)) if image_sizes: widths [s[0] for s in image_sizes] heights [s[1] for s in image_sizes] print(图像宽度范围:, min(widths), -, max(widths)) print(图像高度范围:, min(heights), -, max(heights))这段脚本输出三件事样本图像数、标注框总数、各类别数量。如果某类别占比低于 1%后面训练时必须做采样干预。如果图像宽度从 640 到 4000 都覆盖说明数据集来自不同采集设备训练时要考虑尺度变化。如果你发现统计出的类别名称不统一比如 WBC、Leukocyte、白细胞混着出现先合并再训练否则模型会把这些都当成不同类别导致同一类细胞被拆成多类训练和验证都会乱掉。2.4 类别命名不统一先合并再训练我遇到过标注里 WBC 写成 WbC、RBC 写成 Red Blood Cell 的情况直接在转换脚本里加一层归一化即可。常见做法是维护一个别名表把每个 object 的 name 先映射到标准类别再映射到类别 ID。这样即使数据集内部标注不一致训练时也不会凭空多出几个类别。和 CCPD 车牌数据集、HRSC2016 遥感舰船数据集一样领域数据集的标注字典经常带着作者的个人习惯不能拿到手就当标准。类别名合并这件事越早做越好晚了等你训练完看结果再回头改标签等于重来一遍。3. 把血细胞数据集转成 YOLO 格式并跑起来转换脚本、YAML 和训练参数的取舍血细胞检测数据集.zip 里的原始标注无论是什么格式最终喂给 YOLO 系列模型的都是归一化坐标的 txt 文件。用 YOLOv8 训练自己的数据集最常卡住的不是模型结构而是格式转换和路径配置。这一章给出从 VOC XML 到 YOLO txt 的转换脚本再讲训练配置文件怎么写最后给出血细胞场景下几个关键训练参数的取舍。3.1 VOC XML 转 YOLO txt转换脚本与越界处理YOLO 格式每行五个值类别 ID、归一化中心点 x、归一化中心点 y、归一化宽 w、归一化高 h。转换的核心是把像素坐标除以原图宽高。听起来简单但血细胞标注里经常出现框超出图像边界的情况细胞被涂片边缘截断时标注工具的矩形框甚至会延伸到图外。下面的脚本做了 clamp 处理# convert_voc_to_yolo.py # 把 VOC XML 转成 YOLO txt并在写文件前把越界框裁剪回图像范围 import glob import os import xml.etree.ElementTree as ET # 类别映射必须和之后 blood_cell.yaml 里的 names 保持一致 CLASS_MAP {WBC: 0, RBC: 1, Platelets: 2} def convert(xml_dirannotations, out_dirlabels): os.makedirs(out_dir, exist_okTrue) for xml_file in sorted(glob.glob(os.path.join(xml_dir, *.xml))): root ET.parse(xml_file).getroot() w int(root.findtext(size/width)) h int(root.findtext(size/height)) stem os.path.splitext(os.path.basename(xml_file))[0] lines [] for obj in root.iter(object): cls_name obj.findtext(name) if cls_name not in CLASS_MAP: print(f跳过未知类别: {cls_name} {stem}) continue box obj.find(bndbox) x1 float(box.findtext(xmin)) y1 float(box.findtext(ymin)) x2 float(box.findtext(xmax)) y2 float(box.findtext(ymax)) # 先把坐标限制到图片范围内防止 YOLO 训练时报标签越界 x1 max(0, min(x1, w)) y1 max(0, min(y1, h)) x2 max(0, min(x2, w)) y2 max(0, min(y2, h)) # 再计算归一化的中心点和宽高保留 6 位小数 cx (x1 x2) / 2.0 / w cy (y1 y2) / 2.0 / h bw (x2 - x1) / w bh (y2 - y1) / h lines.append( f{CLASS_MAP[cls_name]} {cx:.6f} {cy:.6f} f{bw:.6f} {bh:.6f}\n ) with open(os.path.join(out_dir, stem .txt), w) as f: f.writelines(lines) if __name__ __main__: convert()这里有一个参数需要根据你的数据集改CLASS_MAP。统计脚本输出的类别名称是什么就映射什么。如果统计里有 Three 大类但你想合并成 WBC、RBC、Platelets 三类就在这一层做收敛。脚本跳过未知类别是为了避免训练时类别 ID 对不上导致 loss 异常。还有一点要说明如果数据集是 COCO JSON 格式你需要先解析 JSON 而不是 XML常见做法是先把 JSON 转成 VOC 再跑这个脚本或者直接用 json 库解析后生成 txt逻辑一样只是数据源换了。越界 clamp 是容易忽略的坑。你以为加了 clamp 就安全了但 clamp 之后如果框宽高变成 0比如 x1 和 x2 都被 clamp 到同一个值这行标注就废了。我在后续巡检里会再加一层过滤把宽高小于 1 像素的框直接丢掉后面章节会讲。3.2 划分数据集并编写 blood_cell.yaml转换完标注文件后需要把图片和对应的 txt 按比例分成训练集和验证集。血细胞数据集规模不大用 shell 脚本就能完成。以下命令在 blood_cell_dataset 目录下执行# 先把所有图片路径打乱再按 8:2 划分训练集和验证集 find images -name *.jpg | shuf all_files.txt total$(wc -l all_files.txt) head -n $((total * 8 / 10)) all_files.txt | while read img; do stem$(basename $img .jpg) mv $img images/train/ mv labels/$stem.txt labels/train/ done # 剩余图片进入验证集 tail -n $((total * 8 / 10 1)) all_files.txt | while read img; do stem$(basename $img .jpg) mv $img images/val/ mv labels/$stem.txt labels/val/ done这种 shell 方式适合百张以内的数据集几分钟能搞定。如果数据集上千张建议用 Python 脚本做分层划分先把按类别分布排序确保验证集里每一种细胞都有一定样本否则验证集的 mAP 会失真。划分完成后在项目根目录写一个 blood_cell.yaml# blood_cell.yaml # train 和 val 指向图片目录YOLO 会在同目录下找同名 txt train: /data/blood_cell_dataset/images/train val: /data/blood_cell_dataset/images/val nc: 3 names: [WBC, RBC, Platelets]这个配置文件的关键是 names 的顺序和 CLASS_MAP 里类别 ID 必须一致。如果 WBC 在 CLASS_MAP 里是 0在 yaml 里也必须排第 0 位否则模型训练时会把白细胞学成红细胞。路径建议用绝对路径省得每次训练前 cd 半天。如果你用的数据集本来就有 ImageSets/Main/train.txt也可以直接读取那个列表去复制文件不用重新 find。3.3 血细胞训练的参数经验值准备好数据和配置文件后训练命令本身不复杂# 安装 ultralytics 运行环境 pip install ultralytics # 开始训练参数顺序不影响YOLO CLI 会解析 yolo detect train \ datablood_cell.yaml \ modelyolov8n.pt \ imgsz640 \ epochs100 \ batch16 \ patience20 \ ampFalse参数上我一般会针对血细胞场景做几个调整。imgsz640 是速度优先但如果原图是 2000 像素以上640 下单个白细胞可能只剩不到 20 像素模型很难学到细节。建议第一轮用 640 跑通流程看 mAP 值再决定要不要上 1280。batch 大小完全看显存16 在 12G 左右卡上比较安全显存不够就降到 8。ampFalse 是我在医学影像上的习惯部分血细胞数据集在混合精度下会出现 loss 变成 NaN 的情况关掉省心。epochs 和 patience 也要看数据规模。血细胞数据集的样本数少模型可能到第 40 个 epoch 还在涨patience20 意味着 20 个 epoch 不涨就早停可能提前切断训练。我会把 patience 放到 30 到 50让它多跑一会儿。如果你发现训练曲线一直在抖先把验证集确认一遍而不是急着调学习率。训练完成后权重在 runs/detect/train 目录下best.pt 是按验证集 mAP 保存的最佳权重后续推理都用它。4. 训练前的标注质量巡检框不靠谱mAP 就是自欺欺人血细胞检测数据集.zip 里的标注不一定是高质量的。很多开源数据集的标注来自半自动标注工具红细胞密密麻麻时标注员会漏点白细胞偶尔标错类别血小板经常画出一个过大的框把周围红细胞也包进去。这些问题如果不处理训练出来的模型 mAP 会虚高换一张真实涂片就露馅。这一章讲怎么在训练前把标注质量查一遍以及怎么处理类别不平衡和增强的边界。4.1 把标注画到图上最笨但最有效的检查方式判断标注质量最简单的方法是把标注框画回原图肉眼扫一遍。血细胞框数量大不需要一张张全看随机抽 30 到 50 张重点看白细胞和血小板的框。下面的脚本会把训练集里的每张图和它的 YOLO txt 标注重叠输出到 vis 目录# draw_boxes.py import os import glob import cv2 def draw_label(img_path, label_path, out_dirvis): os.makedirs(out_dir, exist_okTrue) img cv2.imread(img_path) if img is None: print(f图片读不到: {img_path}) return if not os.path.exists(label_path): print(f漏标文件: {img_path}) return h, w img.shape[:2] with open(label_path) as f: for line in f: parts line.strip().split() if len(parts) ! 5: print(f格式异常: {label_path}) continue cls, cx, cy, bw, bh map(float, parts) # YOLO txt 是归一化坐标还原时要乘回原图宽高 x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) color (0, 0, 255) if cls 0 else (0, 255, 0) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.imwrite(os.path.join(out_dir, os.path.basename(img_path)), img) for img_path in glob.glob(images/train/*.jpg): label_path labels/train/ os.path.basename(img_path).replace(.jpg, .txt) draw_label(img_path, label_path)这段脚本里有个细节容易出错还原框坐标时用的是原图宽高不是训练时的 imgsz。如果你把图 resize 到 640 再还原坐标画出来的框和细胞位置是对不上的。另外脚本会打印两类问题读不到的图片和缺失的标注文件。读不到的图片说明图片路径和标注文件名对不上常见原因是图片是 png 而脚本在找 jpg或者文件名里有多余空格。缺失标注文件说明这张图被划分进了训练集但作者没标训练时 YOLO 会跳过它但会影响训练集规模和类别分布。提示巡检的目的不是把每一张图都画出来看而是抽出最可能出现问题的类别重点看。血细胞数据集里红细胞框偏大、血小板框重叠是最常见的两类问题。4.2 类别不平衡当白细胞只有 20 个框统计脚本如果告诉你 WBC 占比不到 1%你有两个选择一是换 dataset二是做采样干预。真实项目中能换数据集的场景很少大多数人只能硬着头皮做。我一般会先做一次过采样把白细胞样本所在图片在训练列表里重复 3 到 5 遍让模型在每个 epoch 里有更多机会看到白细胞。训练列表就是 images/train 目录下的文件你可以人工把 WBC 样本多的图片复制到另一个临时目录再软链接回训练集也可以直接在数据增强配置里动手脚。更好的方式是做细胞级裁剪。既然白细胞框那么少干脆把每个标注框裁出来缩放到固定尺寸单独做分类或检测。这种方式适合那种“检测少、分类难”的场景比如白细胞五分类你先用检测网络把所有有核细胞找出来再做分类。缺点是脱离了检测任务的端到端流程但实际效果往往比硬训练一个大模型好。另一个思路是负采样。红细胞框太多模型训练时正负样本比例严重失衡可以随机丢弃一部分红细胞框。但 YOLO 的 txt 是按图组织的你没法只删一部分框而不影响同一张图里的其他类别。所以常见的做法是挑出“只有红细胞、没有白细胞/血小板”的图直接从训练集里挪出去一部分。这个操作要小心如果挪得太多模型对红细胞的泛化能力也会下降。我一般先把红细胞占比压到 70% 以下再看 WBC 和 Platelets 的 AP 有没有起来。4.3 数据增强的边界染色是医学图像的敏感信号血涂片里有大量临床信息藏在颜色里染料的浓度、染色时间、显微镜光源色温都会让同一类细胞呈现不同颜色。你想用数据增强提升泛化能力但用力过猛会让模型学到不真实颜色导致换一台显微镜就翻车。YOLOv8 的数据增强可以在 yaml 里覆盖默认参数血细胞场景我通常这样调# blood_cell_aug.yaml # 在训练时通过超参数覆盖默认增强 mosaic: 0.5 hsv_h: 0.02 hsv_s: 0.3 hsv_v: 0.3 degrees: 10 translate: 0.1 scale: 0.3mosaic 从默认的 1.0 降到 0.5是因为 mosaic 会把四张图拼在一起细胞会被拼接缝截断血细胞这种密集小目标对象容易学到半截特征。hsv_h 只给 0.02色调不要乱动饱和度和亮度可以稍大一点模拟不同染色深浅。degrees10 表示最多旋转 10 度血细胞本身是圆的旋转多一点问题不大但对方向敏感的细胞形态如血小板聚集会有影响。translate 和 scale 保持适中保证细胞不会被裁掉太多。如果你发现模型在验证集上 mAP 不错但换一个实验室的数据集就掉点优先检查颜色增强是否过硬。有个土办法把训练时的增强可视化出来看增强后的图是不是已经偏绿偏紫。如果肉眼都看出来颜色不对劲模型也不可能学到靠谱的颜色特征。医学图像的数据增强边界在于“不能改变诊断特征”你增强出来的图要能让一个检验科医生认可它仍然是正常的血涂片。5. 血细胞检测训练与推理的常见问题排查这一章把我在血细胞检测训练和推理里踩过的一些问题列出来每条都按现象到原因到解决办法来讲。这些问题不会同时出现但如果你照着前面的步骤做还翻车先来这里对对症状。5.1 解压后文件名乱码和中文路径导致训练中断现象解压血细胞检测数据集.zip 后文件列表里是一串乱码训练时提示 FileNotFoundError 或 NotADirectoryError图片读不到标注文件也对不上。原因zip 包在 Windows 下打包时使用 GBK 编码Linux 下 unzip 默认按 UTF-8 解压中文文件名和目录名就会变成乱码。另一个隐性问题是路径本身含中文Python 的 glob 和 OpenCV 的 imread 在部分系统上对中文路径兼容不好报错还特别隐晦。解决Linux 下用unzip -O CP936 blood_cell_dataset.zip -d blood_cell_dataset指定编码解压macOS 的 unzip 可能不带 -O 参数可以用 Python 的 zipfile 库在解压时手动用 errorsignore 重命名。解压后我习惯先把目录重命名为英文mv 血细胞检测数据集 blood_cell_dataset。所有后续脚本和训练命令都不要出现中文路径这是给自己省时间。5.2 白细胞类别 AP 一直是 0现象训练跑完验证集上 RBC 和 Platelets 的 mAP 都有 0.8 以上WBC 的 AP 始终是 0.000预测结果里一张白细胞都没框出来。原因不是模型坏了而是白细胞在训练数据里占比太低。一个典型血涂片视野里红细胞上万白细胞只有几个标注框数量相差几个数量级。模型从随机权重开始训练时几乎每个 batch 里都没有白细胞样本梯度完全被红细胞主导。解决先跑第 2 章的统计脚本确认 WBC 框数量。如果确实不到 1%做过采样把包含 WBC 的图片复制到训练列表 3 到 5 遍或者把这些图片单独放进一个目录在 yaml 里多加一个数据源。还有一种做法是降低红细胞样本比例把只有红细胞的图片从训练集里挑出一部分挪走让 WBC 的相对占比从 0.5% 提高到 5% 左右。训练完再看 WBC 的 AP如果还是 0检查类别 ID 是否映射错了。5.3 验证集 mAP 高但实际场景翻车现象在数据集划分的验证集上 mAP0.5 到 0.97拿一张其他实验室采的血涂片来测白细胞召回率直接掉一半边界框松松垮垮。原因这是典型的域偏移。同一个数据集里的训练图和验证图来自同一台显微镜、同一个染色批次模型学到的是那套颜色和光照分布。血涂片染色深浅、显微镜白平衡、相机型号一变模型就懵了。这不是过拟合是数据本身就太单一。解决训练前把一部分来自不同条件下的图像单独留出来做测试集不要参与划分。如果数据集里没有外部图像就在训练时故意增强亮度饱和度的扰动模拟不同染色条件。更专业的做法是做染色归一化比如用 Reinhard 方法把每张图的颜色分布对齐到标准涂片在训练前预处理一遍。这个操作对血细胞检测的泛化提升非常明显但要注意别在验证集上也用训练集的统计参数来归一化否则数据泄漏。5.4 Loss 为 NaN 或 CUDA OOM现象训练到第几个 epoch 时 loss 突然变成 nan命令行直接报错或者刚开始训练就提示 CUDA out of memorybatch 怎么降都不太对。原因loss 变成 nan 最常见的是三个来源一是训练数据里有坐标越界的标注转换时没 clamp归一化后出现负值或极大值二是混合精度训练下某些算子的梯度异常尤其在医学图像的半精度情况下更容易出现三是学习率太大优化器发散。CUDA OOM 则经常和高分辨率 imgsz 叠加了大 batch 有关血细胞数据集如果你想用 imgsz1280batch16 在 24G 卡上都会爆。解决先用第 4 章的巡检脚本把训练集里的越界框全部过滤掉确保 txt 里所有坐标都在 [0,1] 区间。然后在训练命令里加 ampFalse再不行把学习率从默认 0.01 降到 0.001在 yaml 里覆盖 lr0。OOM 的解决不是一味降 batch可以先降 batch 到 8 或 4如果还爆再把 imgsz 从 1280 降到 960 或 640。血细胞的检测精度和分辨率相关但模型训练不出来更亏。6. 用切片推理处理高分辨率血涂片一个让 mAP 变实用的技巧前面训练时你可能为了显存把 imgsz 设成了 640模型在验证集上表现不错但拿去推理一张 4000×3000 的血涂片直接把整图 resize 成 640 再预测很多小细胞会消失。这里有一个我习惯用的技巧切片推理把大图切成 640×640 的小窗逐个预测再把框映射回原图坐标。# 高分辨率血涂片切片推理stride 小于 window 保证窗口有重叠 import cv2 from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) img cv2.imread(full_slide.jpg) H, W img.shape[:2] window, stride 640, 512 all_boxes [] for y in range(0, H, stride): for x in range(0, W, stride): crop img[y:ywindow, x:xwindow] results model(crop, conf0.25, imgsz640, verboseFalse) for box in results[0].boxes.data.tolist(): x1, y1, x2, y2, conf, cls box # 小窗坐标加上窗口偏移量映射回原图坐标 all_boxes.append((x1 x, y1 y, x2 x, y2 y, conf, cls))这段脚本的思路很简单滑动窗口推理重叠部分用后续 NMS 合并。stride512 小于 window640同一个细胞会在相邻窗口里出现两次预测出来的两个框位置相同需要做一次 NMS 去重。直接用 cv2.dnn.NMSBoxes 处理 all_boxes 就行或者换成 SAHI 库它把切片、后处理都封装好了支持 YOLOv8 接口。切片推理的关键参数是 window 和 stridewindow 越大单窗看到的上下文越多但也不能超过模型训练时的 imgsz 太多stride 越小重叠越多检测越稳但耗时越长。我一般先用 window640、stride512 起看漏检情况再把 stride 降到 384。我最早做血细胞检测时直接把 4000 像素的涂片 resize 到 640 去推理结果一个白细胞都找不到。后来翻车翻多了才意识到不是模型不行是目标在 resize 过程中被抹掉了。从那以后凡是单边超过 1500 像素的医学图像我都默认走切片推理宁可多花几秒也不再迷信强制缩放。希望这个习惯能帮到你。本文还有配套的精品资源点击获取
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表