简介本资源为面向皮肤疾病检测的YOLO系列目标检测数据集适用于计算机视觉学习者、医学图像研究者及需要训练皮肤病灶识别模型的开发者。数据集覆盖怀特黑德、皱纹、皮肤发红、黑头、毛孔、痤疮等常见皮肤问题类别可直接用于模型训练与验证测试兼容YOLOv5、YOLOv8、YOLOv9、YOLOv7、YOLOv10及YOLO11等主流算法。压缩包共约2000个文件包含1792个VOC格式xml标注文件与208个YOLO格式txt标注文件整体约98.44MB并附带data.yaml配置文件数据集已按训练与验证划分完毕。YOLO格式采用类别索引与归一化中心点、宽高坐标便于直接读取训练VOC格式则保留原始XML结构方便转换与复核。目前已有107人学习下载适合希望快速搭建皮肤疾病检测基线、对比不同YOLO版本性能或开展医学图像目标检测实践的用户参考使用。1. 2343 张皮肤镜图像带标签这套 YOLO 数据集到底能跑出什么皮肤疾病检测这个方向公开可用的标注数据集一直不算多。手里这套 2343 张图像的数据包覆盖怀特黑德、皱纹、皮肤发红、黑头、毛孔、痤疮六类皮肤状态每张图都配了 YOLO 格式的 txt 标签同时保留了 VOC 格式的 xml 文件。拿到手第一件事不是急着训练而是先搞清楚它的标签体系能不能直接喂给 YOLOv5 到 YOLO11 这一系列算法。答案是能而且配置文件 data.yaml 已经写好了目录结构也按训练集/验证集划分完毕。适合谁用做皮肤检测原型的算法工程师、需要快速验证检测头改动的研究者、以及想拿真实医学图像练手 YOLO 微调的人。不适合指望它直接上临床的团队——2343 张的体量做 demo 够用做产品级精度还差得远。2. 拆开压缩包先看什么目录结构与标签格式的对应关系2.1 图像与标签的目录布局解压之后你会看到类似这样的结构skin_dataset/ ├── data.yaml ├── images/ │ ├── train/ │ │ ├── img_0279_190.jpg │ │ ├── img_0279_267.jpg │ │ └── ... │ └── val/ │ ├── img_0279_273.jpg │ └── ... ├── labels_yolo/ │ ├── train/ │ │ ├── img_0279_190.txt │ │ └── ... │ └── val/ │ └── ... └── labels_voc/ ├── train/ │ ├── img_0279_190.xml │ └── ... └── val/ └── ...这个布局是 YOLO 训练的标准范式images 和 labels 平行存放train/val 各自独立。注意 labels_yolo 和 labels_voc 是两套并行的标注内容等价但格式不同。训练时只用 labels_yololabels_voc 是给需要转 COCO 或做其他框架适配时用的备份。2.2 YOLO 标签的六列含义与坐标归一化打开任意一个 txt比如 img_0279_190.txt你会看到类似0 0.543 0.612 0.231 0.189 2 0.312 0.445 0.156 0.203每行五个值含义是class x_center y_center width height。class 从 0 开始索引对应 data.yaml 里的 names 列表顺序。x_center 和 y_center 是目标框中心点相对于图像宽高的比例width 和 height 也是比例值全部落在 0 到 1 之间。这意味着标签文件本身不携带图像尺寸信息训练时由 dataloader 根据实际读入的图像尺寸做反归一化。如果你自己写解析脚本千万别把比例值当成像素坐标直接用。2.3 data.yaml 里必须核对的三个字段data.yaml 通常长这样path: ./skin_dataset train: images/train val: images/val nc: 6 names: [whitehead, wrinkle, redness, blackhead, pore, acne]拿到手先核对三件事nc 是否等于 6names 的顺序是否和标签里的 class 索引一致path 是相对路径还是绝对路径。我见过太多人直接yolo train datadata.yaml然后报 “No labels found”九成是 path 写错了或者 train/val 的相对路径没对上。如果解压后目录名和 yaml 里写的不一样要么改 yaml要么改目录名别硬跑。3. 从零跑通一次训练YOLOv8 与 YOLO11 的配置差异3.1 环境准备与依赖安装假设你用 conda 管理环境基础依赖就这几样conda create -n skin_yolo python3.10 -y conda activate skin_yolo pip install ultralytics opencv-python pyyamlultralytics 这个包同时覆盖 YOLOv8 和 YOLO11YOLOv5 需要单独 clone 仓库。如果你要跑 YOLOv5建议用官方 repo 而不是 pip 包因为 v5 的 train.py 参数接口和 v8 之后的 CLI 风格差异不小。装完之后yolo checks看一眼环境确认 CUDA 可用、torch 版本匹配。3.2 用 YOLOv8 做第一次基线训练先跑一个最小配置确认数据管线没问题yolo detect train \ data./skin_dataset/data.yaml \ modelyolov8n.pt \ epochs50 \ imgsz640 \ batch16 \ device0 \ projectruns/skin \ namebaseline_v8n参数说明model 用 nano 版本先跑通epochs 给 50 看收敛趋势imgsz 640 是 YOLO 系列的默认输入尺寸batch 根据显存调8G 显存跑 16 差不多。project 和 name 控制输出目录训练日志、权重、混淆矩阵都会落在 runs/skin/baseline_v8n 下面。跑完看 results.csv 里的 mAP50 曲线如果前 10 个 epoch 就平了大概率是学习率或数据增强的问题不是模型容量不够。3.3 YOLO11 的迁移与参数微调YOLO11 的 CLI 接口和 v8 基本一致换模型权重即可yolo detect train \ data./skin_dataset/data.yaml \ modelyolo11n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ lr00.01 \ patience20 \ projectruns/skin \ namebaseline_v11n这里多了 lr0 和 patience。lr0 初始学习率默认 0.01如果 loss 震荡厉害可以降到 0.005。patience 是早停轮数20 表示 20 个 epoch 验证指标不提升就停。YOLO11 的 head 结构相比 v8 有调整在小目标上通常更稳但皮肤病灶这类纹理密集的场景nano 版本可能欠拟合建议同时跑一个 yolo11s 做对比。3.4 验证与推理确认标签没被错位训练完先跑验证yolo detect val \ modelruns/skin/baseline_v11n/weights/best.pt \ data./skin_dataset/data.yaml \ imgsz640 \ batch16然后拿几张验证集图像做推理肉眼核对框的位置yolo detect predict \ modelruns/skin/baseline_v11n/weights/best.pt \ source./skin_dataset/images/val \ conf0.25 \ saveTrue \ projectruns/skin \ namepred_checkconf 阈值先给 0.25看有没有明显漏检或误检。如果框整体偏移回去检查标签的归一化坐标是否被错误地乘以了图像尺寸。如果类别全错检查 data.yaml 的 names 顺序和标签 class 索引是否对应。4. 标签格式转换与数据增强VOC 转 YOLO 的脚本与边界情况4.1 VOC 转 YOLO 的完整脚本虽然数据集已经提供了 YOLO 格式但如果你要合并其他 VOC 来源的数据这个转换脚本能直接用import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, classes, output_path): tree ET.parse(xml_path) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in classes: continue cls_id classes.index(cls_name) bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 裁剪到图像边界内防止越界坐标 xmin max(0, min(xmin, img_w)) xmax max(0, min(xmax, img_w)) ymin max(0, min(ymin, img_h)) ymax max(0, min(ymax, img_h)) x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) with open(output_path, w) as f: f.write(\n.join(lines)) classes [whitehead, wrinkle, redness, blackhead, pore, acne] voc_to_yolo(labels_voc/train/img_0279_190.xml, classes, labels_yolo/train/img_0279_190.txt)逻辑说明先读 XML 里的图像宽高再遍历每个 object 取 bbox 坐标。关键在裁剪那一步——VOC 标注里经常出现 xmax 超过图像宽度的情况不裁剪的话归一化后 width 会大于 1YOLO 训练时直接报错。坐标转换公式就是中心点除以宽高、宽高除以宽高保留六位小数足够精度。4.2 针对皮肤图像的数据增强策略皮肤镜图像的特点是纹理细、对比度低、病灶边界模糊。默认的 mosaic 和 mixup 增强可以用但要注意两点一是随机裁剪的 scale 别设太小0.5 以下容易把病灶裁掉一半二是 HSV 增强的饱和度范围收窄皮肤发红和痤疮的区分很依赖颜色过度扰动会让模型学偏。在 data.yaml 同级加一个 aug 配置或者在训练命令里直接覆盖yolo detect train \ data./skin_dataset/data.yaml \ modelyolo11s.pt \ epochs100 \ imgsz640 \ scale0.3 \ hsv_s0.5 \ hsv_v0.3 \ mosaic0.8 \ projectruns/skin \ nameaug_tunedscale0.3 表示随机缩放范围控制在 ±30%hsv_s0.5 把饱和度扰动减半mosaic0.8 保留 80% 概率做马赛克增强。这些值不是拍脑袋是我在类似纹理数据集上试出来的经验区间你可以根据验证集 mAP 再微调。4.3 类别不平衡的处理六类里怀特黑德和痤疮的样本量通常比毛孔多如果直接训练毛孔类的召回会明显偏低。两个做法一是在 data.yaml 里给每类加权重但 YOLO 原生不支持二是用过采样把少样本类的图像在 train 列表里重复几次。更简单的办法是调 loss 的 cls 权重在训练命令里加cls1.5让分类损失占更大比重。跑完看混淆矩阵如果毛孔和黑头互相误判严重说明特征区分度不够考虑换更大的模型或者加注意力模块。5. 避坑与排查训练皮肤检测模型时最容易翻车的五件事5.1 现象训练 loss 正常下降但 mAP 始终为 0原因标签文件的路径和图像路径没有正确对应。YOLO 的 dataloader 会根据 images/train 里的文件名去 labels/train 找同名 txt如果 txt 文件名多了后缀或者目录层级不对就找不到标签模型学的是全背景。解决写个脚本检查 images 和 labels 的文件名是否一一对应import os img_files set(os.path.splitext(f)[0] for f in os.listdir(images/train)) lbl_files set(os.path.splitext(f)[0] for f in os.listdir(labels_yolo/train)) missing img_files - lbl_files print(f缺失标签: {len(missing)})5.2 现象验证集 mAP 比训练集低 30 个点以上原因train/val 划分时没有做随机打乱或者同一张图像的不同增强版本同时出现在 train 和 val 里造成数据泄漏。解决重新划分确保 val 里的图像在 train 中完全不出现。如果原始数据集已经划分好检查两个目录下有没有同名文件。有的话把 val 里的重复项删掉或者从 train 里移除。5.3 现象推理时框的位置整体偏移原因标签归一化时用错了图像尺寸。比如用 640 去归一化原图 1024 的坐标或者把 x_center 当成了左上角坐标。解决随机抽 5 张图用 OpenCV 画框可视化和原图对比。如果框整体偏左上或偏右下就是中心点和角点搞混了。YOLO 格式的 x_center 是框中心不是左上角。5.4 现象训练到一半突然报 CUDA out of memory原因YOLO 的 dataloader 在最后一个 batch 可能因为图像尺寸不一致导致显存峰值。或者 mosaic 增强拼接了四张图等效 batch 翻倍。解决把 batch 降到 8 或者 4同时开ampTrue混合精度。如果还不行把 imgsz 从 640 降到 512皮肤病灶的检测对分辨率要求没那么苛刻512 通常够用。5.5 现象模型对毛孔类几乎全部漏检原因毛孔在图像里尺寸极小YOLO 的 P3 特征图 stride 是 8小目标经过多次下采样后特征几乎消失。解决换用带 P2 检测头的模型配置或者在 YOLO11 里把 imgsz 提到 1024 再训练。另一个办法是切片推理把大图裁成 512×512 的小块分别检测再合并但这样会丢失全局上下文适合毛孔单独做一个检测分支。6. 进阶技巧用切片推理把毛孔类召回拉高 15 个点毛孔和黑头这类微小目标在 640 输入下经过 backbone 的 32 倍下采样后特征图上的响应可能只有一两个像素。我试过一个取巧的办法训练时用 640推理时用 1280 或者切片。切片推理的逻辑是把原图按 512×512 滑窗裁切每块单独过模型最后用 NMS 合并所有框。代价是推理时间线性增长但毛孔类的召回能从 0.4 拉到 0.55 左右。具体实现不复杂用 OpenCV 做滑窗把每块的检测结果映射回原图坐标import cv2 import numpy as np from ultralytics import YOLO model YOLO(runs/skin/baseline_v11n/weights/best.pt) img cv2.imread(test.jpg) h, w img.shape[:2] tile_size 512 overlap 64 all_boxes [] for y in range(0, h, tile_size - overlap): for x in range(0, w, tile_size - overlap): tile img[y:ytile_size, x:xtile_size] if tile.shape[0] 32 or tile.shape[1] 32: continue results model(tile, conf0.2, verboseFalse) for box in results[0].boxes: xyxy box.xyxy[0].cpu().numpy() xyxy[0] x xyxy[1] y xyxy[2] x xyxy[3] y all_boxes.append((xyxy, float(box.conf[0]), int(box.cls[0]))) # 用 NMS 合并重叠框overlap 给 64 是为了避免目标正好落在切片边界被截断。conf 阈值降到 0.2因为切片后单块的上下文变少模型置信度普遍偏低靠后续 NMS 和投票来过滤。合并的时候用 IoU 0.5 做 NMS同一目标被多个切片检测到会保留置信度最高的那个。这个方案有个副作用推理速度从 30 FPS 掉到 8 FPS 左右看你的场景能不能接受。如果只是离线分析完全值得如果要实时还是老老实实上 TensorRT 加速把 640 输入的延迟压到 10ms 以内再考虑用更大的输入尺寸。从那以后我每次拿到新的检测数据集都强制先跑一遍标签可视化确认框的位置和类别没错再开始训练。这个习惯帮我省了至少三次通宵排查的功夫。希望帮到你。本文还有配套的精品资源点击获取