news 2026/9/14 18:25:33

Kvasir-SEG息肉检测数据集:YOLO格式解析与医疗目标检测实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kvasir-SEG息肉检测数据集:YOLO格式解析与医疗目标检测实战

简介:本资源是面向医学图像AI初学者与目标检测实践者的YOLO格式息肉检测专用数据集,基于Kvasir-SEG公开数据构建,聚焦单类别(息肉)的端到端训练需求,适用于结肠镜辅助诊断模型开发、课程实验及竞赛基线训练。压缩包共2000个文件,含999张高分辨率RGB图像(332×487至1920×1072)、1000个YOLO标准txt标签文件(含归一化中心坐标与宽高),以及1个开箱即用的数据可视化Python脚本——无需修改参数,运行即可随机加载图像并叠加边界框,支持快速验证标注质量与数据读取逻辑。资源总大小57.01MB(7z格式),已按YOLO目录规范组织为train/val两级结构(800+200图像对),附带classes.txt明确类别定义,可直接接入Ultralytics等主流框架训练。目前已有313人学习下载,显著降低数据预处理门槛,节省从原始数据清洗、格式转换到可视化调试的全流程时间成本。

1. 这不是普通医学图像数据集:Kvasir-SEG 息肉检测数据集专为 YOLO 目标检测而优化,开箱即用但需理解其坐标逻辑

你拿到的不是一堆带框的 JPG 文件,而是一个经过严格 YOLO 格式对齐的临床级息肉检测数据集。它不依赖分割掩码(mask),也不提供像素级标注,而是以「单类别、高置信边界框」为核心——这恰恰是部署端侧结肠镜辅助诊断系统最需要的输入形式。800 张训练图 + 200 张验证图,全部按images/labels/两级目录组织,classes.txt仅含一行polyp,所有.txt标注文件均采用 YOLOv5/v8/v9 兼容的归一化格式:class_id x_center y_center width height。关键在于,这些坐标并非原始图像尺寸下的绝对值,而是基于每张图实际宽高动态归一化后的浮点数(例如0.623 0.481 0.217 0.305),这意味着你不能直接套用固定尺寸的预处理 pipeline。分辨率跨度从 332×487 到 1920×1072,说明该数据集天然适配多尺度训练策略,但同时也要求你在train.py中显式启用rect=Truemosaic=0.5等参数,否则小图会被强制拉伸导致 bbox 失真。如果你正准备复现一篇内镜 AI 论文、调试边缘设备上的轻量模型,或验证 YOLOv8n 在医疗场景下的泛化能力,这个数据集就是跳过数据清洗、标注转换、格式校验三道坎的起点——但前提是,你得先读懂它的坐标生成逻辑。

2. YOLO 格式解析与数据结构验证:从 classes.txt 到 label 文件的归一化机制拆解

2.1 Kvasir-SEG 的 YOLO 标注规范与坐标生成原理

Kvasir-SEG 原始标注为像素级分割掩码(PNG),本数据集已将其转换为边界框(Bounding Box)。转换过程并非简单取 mask 最小外接矩形(Min Area Rect),而是采用cv2.boundingRect()提取连通域轮廓后,对每个息肉实例生成 tight-fitting bbox。重点在于归一化逻辑:

  • x_center = (bbox_x_min + bbox_width / 2) / image_width
  • y_center = (bbox_y_min + bbox_height / 2) / image_height
  • width = bbox_width / image_width
  • height = bbox_height / image_height

该计算在每张图上独立执行,因此即使同一息肉出现在不同分辨率图像中,其.txt文件中的数值也完全不同。这种设计保证了模型学习的是相对空间关系,而非绝对像素位置,是 YOLO 系列能跨设备部署的基础。若你尝试用 OpenCV 读取某张图并手动验证,可执行以下脚本:

import cv2 import numpy as np # 替换为你的实际路径 img_path = "datasets-images-train/cju0sr5ghl0nd08789uzf1raf.jpg" label_path = "datasets-images-train/cju0sr5ghl0nd08789uzf1raf.txt" # 读取图像获取原始尺寸 img = cv2.imread(img_path) h, w = img.shape[:2] # 读取YOLO标注 with open(label_path, 'r') as f: line = f.readline().strip() if not line: raise ValueError("Label file is empty") parts = list(map(float, line.split())) cls_id, x_cen, y_cen, box_w, box_h = parts # 反归一化得到像素坐标 x_min = int((x_cen - box_w / 2) * w) y_min = int((y_cen - box_h / 2) * h) x_max = int((x_cen + box_w / 2) * w) y_max = int((y_cen + box_h / 2) * h) # 绘制验证框 cv2.rectangle(img, (x_min, y_min), (x_max, y_max), (0,255,0), 2) cv2.putText(img, "polyp", (x_min, y_min-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2) cv2.imwrite("debug_bbox.jpg", img) print(f"Original image size: {w}x{h}") print(f"YOLO coords: {x_cen:.3f} {y_cen:.3f} {box_w:.3f} {box_h:.3f}") print(f"Pixel bbox: ({x_min},{y_min}) → ({x_max},{y_max})")

提示:运行此脚本前请确认label_pathimg_path文件名严格一致(不含扩展名),且.txt文件中仅含单行(因本数据集为单类别单目标)。若出现IndexError,说明该图存在多息肉标注——此时需循环读取所有行,但 Kvasir-SEG 原始数据中单图多息肉比例低于 3%,本数据集已做筛选。

2.2 数据集目录结构合规性检查与常见错误修复

YOLO 训练器(如 Ultralytics)要求train/val目录下必须存在images/labels/子目录,且同名文件一一对应。本数据集已满足此结构,但仍需验证三项硬性规则:

检查项合规标准验证命令不合规后果
文件名一致性xxx.jpgxxx.txt(扩展名除外)diff <(ls datasets-images-train/*.jpg | sed 's/\.jpg$//') <(ls datasets-images-train/*.txt | sed 's/\.txt$//')DataLoader报错KeyError,训练中断
标签文件非空每个.txt至少含 1 行有效标注find datasets-images-train/labels -name "*.txt" -exec grep -q "[^[:space:]]" {} \; -o -print模型在 batch 中遇到空标签会触发ZeroDivisionError
归一化值合法性0 ≤ x_cen,y_cen ≤ 10 < width,height ≤ 1`awk '{if($2<0

执行上述命令后,若输出为空则表示结构完全合规。若发现不一致文件名,可用以下 Bash 脚本批量修复(假设你使用 Linux/macOS):

# 进入 labels 目录修正文件名 cd datasets-images-train/labels for txt in *.txt; do base=$(basename "$txt" .txt) if [[ ! -f "../images/$base.jpg" ]]; then # 查找匹配的 jpg(忽略大小写和可能的 png) match=$(find ../images -iname "$base.*" \| head -n1) if [[ -n "$match" ]]; then new_name=$(basename "$match" | sed 's/\.[^.]*$//') mv "$txt" "${new_name}.txt" echo "Renamed $txt → ${new_name}.txt" fi fi done

2.3 classes.txt 的隐含约束与 multi-class 扩展可能性

classes.txt内容仅为单行polyp,表明该数据集严格限定为单类别检测任务。但 YOLO 架构本身支持多类别,若你计划融合其他消化道病变(如溃疡、出血点),需同步修改三处:

  1. classes.txt:追加新类别,每行一个,顺序即 class_id(polyp为 0,新增ulcer为 1)
  2. 所有 label 文件:将原0替换为对应 class_id(如sed -i 's/^0 /1 /' *.txt
  3. 模型配置文件:Ultralytics 的model.yamlnc: 1必须改为nc: 2

注意:Kvasir-SEG 原始数据包含 8 类病变,但本数据集仅提取polyp类别。若需其他类别,必须重新下载原始 Kvasir-SEG 并运行官方转换脚本(kvasir2yolo.py),不可直接修改本数据集的classes.txt——因为其 label 文件未包含其他类别的 bbox 坐标。

3. 可视化脚本深度解析与定制化增强:不只是画框,更是数据质量审计工具

3.1 自带 visualize.py 的执行逻辑与参数暴露

项目提供的visualize.py是一个轻量级审计工具,核心功能是随机选取一张图,加载其对应 label,绘制 bbox 并保存。其默认行为隐藏了两个关键参数:--source指定图像路径,--save-dir指定输出目录。但原始脚本未暴露这些参数,需手动修改才能实现定向可视化。以下是增强版脚本(保存为visualize_enhanced.py):

import argparse import cv2 import os import random import numpy as np def parse_args(): parser = argparse.ArgumentParser(description="YOLO label visualization tool") parser.add_argument('--source', type=str, required=True, help='Path to image file or directory') parser.add_argument('--save-dir', type=str, default='./visualized', help='Output directory for annotated images') parser.add_argument('--label-dir', type=str, default=None, help='Directory containing .txt labels (if different from image dir)') parser.add_argument('--show', action='store_true', help='Show image in window instead of saving') return parser.parse_args() def main(): args = parse_args() os.makedirs(args.save_dir, exist_ok=True) # 支持单图或目录模式 if os.path.isfile(args.source): img_paths = [args.source] else: img_paths = [os.path.join(args.source, f) for f in os.listdir(args.source) if f.lower().endswith(('.jpg', '.jpeg', '.png'))] # 随机选一张(可注释掉此行实现全量可视化) img_path = random.choice(img_paths) # 推导label路径 label_dir = args.label_dir if args.label_dir else args.source.replace('images', 'labels') label_path = os.path.join(label_dir, os.path.splitext(os.path.basename(img_path))[0] + '.txt') # 加载图像和标签 img = cv2.imread(img_path) if img is None: raise FileNotFoundError(f"Cannot load image: {img_path}") if not os.path.exists(label_path): print(f"Warning: No label found for {img_path}, skipping...") return with open(label_path, 'r') as f: lines = f.readlines() h, w = img.shape[:2] for line in lines: parts = list(map(float, line.strip().split())) cls_id, x_cen, y_cen, box_w, box_h = parts # 反归一化 x_min = int((x_cen - box_w / 2) * w) y_min = int((y_cen - box_h / 2) * h) x_max = int((x_cen + box_w / 2) * w) y_max = int((y_cen + box_h / 2) * h) # 绘制绿色边框和类别文字 cv2.rectangle(img, (x_min, y_min), (x_max, y_max), (0,255,0), 2) cv2.putText(img, f"polyp", (x_min, y_min-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2) # 输出处理 output_path = os.path.join(args.save_dir, os.path.basename(img_path)) if args.show: cv2.imshow("Annotated", img) cv2.waitKey(0) cv2.destroyAllWindows() else: cv2.imwrite(output_path, img) print(f"Saved to {output_path}") if __name__ == "__main__": main()

执行示例:

# 可视化训练集第一张图 python visualize_enhanced.py --source datasets-images-train/images --save-dir ./train_viz # 可视化指定图片并显示窗口 python visualize_enhanced.py --source datasets-images-val/cju7eea9b2m0z0801ynqv1fqu.jpg --show

3.2 可视化结果的质量审计维度与异常模式识别

可视化不仅是“看框”,更是数据质量的显微镜。重点关注以下四类异常模式:

异常类型视觉特征根本原因解决方案
Bbox 截断框超出图像边界(部分框线消失)归一化计算时未做 clip,x_cen±w/2超出 [0,1]visualize.py中添加np.clip(x_min, 0, w-1)
多框重叠同一息肉被标注多个紧密相邻框分割掩码存在噪声或连通域分割错误cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)闭运算预处理原始 mask
框体过小bbox 长宽 < 5 像素(视觉上呈点状)息肉尺寸过小或标注误差在训练前过滤box_w * box_h < 0.0005的样本(对应 1920p 图中约 10×10px)
无框图像图像干净无任何标注框原始 mask 为空或转换脚本漏处理运行grep -L "polyp" datasets-images-train/labels/*.txt定位空标签文件

提示:执行python visualize_enhanced.py --source datasets-images-train/images --save-dir ./audit后,人工抽查 50 张可视化结果,若发现 >5% 存在截断或重叠,建议退回原始 Kvasir-SEG 数据集,用skimage.measure.regionprops重新提取 bbox,而非依赖本数据集的转换结果。

4. YOLOv8 训练全流程实操:从环境配置到 mAP 验证的完整链路

4.1 环境依赖与 GPU 加速配置要点

本数据集推荐使用 Ultralytics 官方ultralytics==8.2.0(截至 2024 年 Q2 最稳定版本)。安装命令需明确指定 CUDA 版本以避免 PyTorch 冲突:

# 假设你使用 NVIDIA Driver 535 + CUDA 12.1 pip install torch==2.1.0+cu121 torchvision==0.16.0+cu121 torchaudio==2.1.0 --extra-index-url https://download.pytorch.org/whl/cu121 pip install ultralytics==8.2.0 # 验证CUDA可用性 python -c "import torch; print(torch.cuda.is_available(), torch.version.cuda)"

关键配置项说明:

  • torch==2.1.0+cu121:必须与你的nvidia-smi显示的 Driver 版本兼容(Driver ≥ 535 对应 CUDA 12.1)
  • ultralytics==8.2.0:避免使用main分支,因其频繁引入 breaking changes(如v8.2.1val参数名变更)
  • 若使用 A10/A100 等 Ampere 架构显卡,需额外安装nvidia-cudnn-cu12==8.9.2.26以启用 TensorRT 加速

4.2 训练配置文件编写与超参调优策略

创建polyp_train.yaml配置文件,内容如下:

# polyp_train.yaml train: data: ./data.yaml epochs: 100 batch: 16 imgsz: 640 optimizer: auto lr0: 0.01 lrf: 0.01 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 3 warmup_momentum: 0.8 box: 7.5 cls: 0.5 dfl: 1.5 hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4 degrees: 0.0 translate: 0.1 scale: 0.5 shear: 0.0 perspective: 0.0 flipud: 0.0 fliplr: 0.5 mosaic: 1.0 mixup: 0.0 copy_paste: 0.0

核心参数解释:

  • batch: 16:基于 A10G(24GB VRAM)的实测上限,若显存不足可降至8,但需同比例降低lr0(如batch=8lr0=0.005
  • mosaic: 1.0:强制启用马赛克增强,对小尺寸息肉(<50px)检测提升显著,但会增加显存占用
  • hsv_s: 0.7&hsv_v: 0.4:大幅增强饱和度与明度扰动,模拟内镜白光/染色模式切换,提升泛化性
  • fliplr: 0.5:水平翻转概率设为 0.5,因息肉在肠道中无左右对称性,禁用flipud(垂直翻转会扭曲解剖结构)

4.3 data.yaml 结构定义与路径映射

data.yaml是 YOLO 训练的入口文件,必须精确指向数据集路径:

# data.yaml train: ../datasets-images-train/images val: ../datasets-images-val/images nc: 1 names: ['polyp']

注意:路径为相对于data.yaml文件所在目录的相对路径。若data.yamldatasets-images-train同级,则train: datasets-images-train/images;若data.yaml放在项目根目录,而数据集在./data/下,则train: data/datasets-images-train/images。路径错误会导致AssertionError: train set not found

4.4 训练启动与关键指标监控

执行训练命令:

yolo detect train data=data.yaml model=yolov8n.pt epochs=100 batch=16 imgsz=640 name=polyp_v8n

监控重点:

  • train/box_loss:应从 ~3.0 降至 ~0.8 以下,若停滞在 2.0+ 说明学习率过高或数据噪声大
  • val/mAP50-95(B):最终值应 ≥ 0.65(YOLOv8n 在 Kvasir-SEG 上的 SOTA 水平),若 < 0.55 需检查val图像是否混入训练集
  • gpu_mem:A10G 上应稳定在 18~22GB,若持续 >23GB 说明batch过大或mosaic未生效

验证最佳权重:

yolo detect val data=data.yaml model=runs/detect/polyp_v8n/weights/best.pt

输出的results.csvmetrics/mAP50-95(B)即为最终 mAP。

5. 模型推理与临床场景适配技巧:如何让 YOLO 输出真正可用的息肉定位结果

5.1 推理时的 confidence threshold 动态调整策略

默认conf=0.25会召回大量低置信假阳性(如褶皱、污渍),但在结肠镜实时场景中,漏检代价远高于误报。推荐采用双阈值策略:

from ultralytics import YOLO model = YOLO("runs/detect/polyp_v8n/weights/best.pt") results = model("test_image.jpg", conf=0.25, iou=0.7, verbose=False) # 提取所有检测框 boxes = results[0].boxes.xyxy.cpu().numpy() # [x1,y1,x2,y2] confidences = results[0].boxes.conf.cpu().numpy() classes = results[0].boxes.cls.cpu().numpy() # 高置信区(确信息肉):conf ≥ 0.6 → 直接报警 high_conf = confidences >= 0.6 # 中置信区(疑似息肉):0.25 ≤ conf < 0.6 → 触发二次确认(如放大 ROI 区域再检测) mid_conf = (confidences >= 0.25) & (confidences < 0.6) # 输出结构化结果 detections = [] for i in range(len(boxes)): det = { "bbox": boxes[i].tolist(), "confidence": float(confidences[i]), "class": int(classes[i]), "level": "high" if high_conf[i] else "mid" if mid_conf[i] else "low" } detections.append(det) print(detections)

5.2 边缘设备部署的量化与加速技巧

在 Jetson Orin(32GB)上部署时,需进行 INT8 量化以提升 FPS:

# 导出 ONNX 并量化 yolo export model=best.pt format=onnx dynamic=True half=True # 使用 TensorRT 优化(需安装 trtexec) trtexec --onnx=yolov8n_polyp.onnx \ --saveEngine=yolov8n_polyp.engine \ --int8 \ --calib=./calibration_data/ \ --workspace=4096

关键点:

  • --int8:启用 INT8 量化,Orin 上可提速 2.3×,精度损失 <1.2% mAP
  • --calib:需提供 500 张无标注的内镜图像作为校准集(calibration_data/目录)
  • --workspace=4096:分配 4GB 显存用于优化,避免编译失败

5.3 与内镜设备集成的关键接口设计

YOLO 输出需转换为内镜系统可识别的坐标协议。假设内镜视频流分辨率为 1920×1080,而模型输入为 640×640,需做坐标映射:

def yolov8_to_endoscope(bbox_xyxy, input_size=640, endoscope_size=(1920,1080)): """ 将YOLO输出的归一化坐标转换为内镜设备像素坐标 bbox_xyxy: [x1,y1,x2,y2] 归一化坐标(0~1) """ x1, y1, x2, y2 = bbox_xyxy # 转换为输入图像像素坐标 x1_px = int(x1 * input_size) y1_px = int(y1 * input_size) x2_px = int(x2 * input_size) y2_px = int(y2 * input_size) # 按等比缩放映射到内镜分辨率(保持长宽比,黑边区域忽略) scale = min(endoscope_size[0]/input_size, endoscope_size[1]/input_size) resized_w = int(input_size * scale) resized_h = int(input_size * scale) # 计算黑边偏移 pad_w = (endoscope_size[0] - resized_w) // 2 pad_h = (endoscope_size[1] - resized_h) // 2 # 映射到内镜坐标系 final_x1 = int(x1_px * scale + pad_w) final_y1 = int(y1_px * scale + pad_h) final_x2 = int(x2_px * scale + pad_w) final_y2 = int(y2_px * scale + pad_h) return [final_x1, final_y1, final_x2, final_y2] # 示例:将模型输出转换为内镜坐标 yolo_output = [0.2, 0.3, 0.5, 0.7] # 归一化 bbox endoscope_bbox = yolov8_to_endoscope(yolo_output) print(f"Endoscope coordinates: {endoscope_bbox}") # [416, 216, 992, 756]

此函数确保 YOLO 的检测框能精准叠加在内镜实时画面上,无需额外几何变换。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 18:24:41

Scrapy-Redis分布式爬虫架构与实战指南

1. Scrapy框架与分布式爬虫基础解析Scrapy作为Python生态中最强大的爬虫框架之一&#xff0c;其设计哲学遵循"Dont Repeat Yourself"原则。单机模式下&#xff0c;Scrapy通过内置的调度器&#xff08;Scheduler&#xff09;管理请求队列&#xff0c;使用基于内存的集…

作者头像 李华
网站建设 2026/9/14 18:24:31

AI葡萄智能绑蔓机器人 Qt信创完整项目

# AI葡萄智能绑蔓机器人 Qt信创完整项目 ## 项目定位 适配**统信UOS/银河麒麟**国产信创平台(飞腾/龙芯aarch64、x86),Qt5.15/Qt6 + OpenCV4; 业务:轻量化YOLOv8视觉识别葡萄架面**新梢、老蔓、钢丝架线、交叉密枝**,自动判定合规绑缚点位;区分**第一次嫩梢绑蔓(20–3…

作者头像 李华
网站建设 2026/9/14 18:23:28

SpringBoot3.x多数据源配置与Druid监控实战

1. 项目概述在当今企业级应用开发中&#xff0c;多数据源支持已成为标配需求。无论是读写分离、分库分表&#xff0c;还是对接不同业务系统的数据库&#xff0c;都需要我们掌握多数据源配置的核心技术。最近我在一个金融项目中实践了SpringBoot3.x MybatisPlus Druid的多数据…

作者头像 李华
网站建设 2026/9/14 18:20:55

LCD淘汰潮下的硬件工程师生存指南

1. “LCD之死”不是一句玩笑话&#xff1a;它正在从供应链、产线到终端被系统性清退“好吧我都科技树彻底被锁死了——LCD之死”——这句话在电子工程师群、硬件创客论坛和二手屏交易频道里反复刷屏&#xff0c;语气里混着自嘲、疲惫和一丝真实的慌乱。它不是段子&#xff0c;而…

作者头像 李华