YOLO皮肤镜图像检测实战:2343张标注数据集训练与调优
简介本资源为面向皮肤疾病检测的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 以内再考虑用更大的输入尺寸。从那以后我每次拿到新的检测数据集都强制先跑一遍标签可视化确认框的位置和类别没错再开始训练。这个习惯帮我省了至少三次通宵排查的功夫。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

AI古诗短视频制作全流程:从文生图到电影感剪辑

AI古诗短视频制作全流程:从文生图到电影感剪辑

我先把话说在前面:网上那些"AI生成古诗视频,第一条就破万赞"的标题,水分很大,任何一个做内容的人都没法保证你抄了就能破万。但有一点是真的——古诗短视频是AI视频领域里最适合普通人上手的方向,素材成本极…

2026/10/9 6:24:16 阅读更多 →
滑动窗口解最小覆盖子串:双指针与哈希表实现 O(n) 匹配

滑动窗口解最小覆盖子串:双指针与哈希表实现 O(n) 匹配

“滑动窗口”这四个字,在算法面试里的出场率高到离谱;而“最小覆盖子串”又是滑动窗口家族里最能检验功力的那一道。字符串覆盖怎么判断、窗口什么时候该收缩、计数器状态怎么同步,哪一环掉链子,代码表面上跑得通,换一…

2026/10/9 6:24:16 阅读更多 →
Redis为什么快?五层设计原理与生产性能优化实践

Redis为什么快?五层设计原理与生产性能优化实践

今天聊聊一个经典到不能再经典的面试题:Redis 为什么这么快?这题几乎每次招人都会问,但答好的人真不多。多数人上来就甩一句“因为它是内存数据库”,然后就没有然后了。这个回答对不对?对,但只说明你背过答…

2026/10/9 6:24:16 阅读更多 →

最新新闻

可靠性测试别只会跑温箱振动台:失效物理与加速寿命是关键

可靠性测试别只会跑温箱振动台:失效物理与加速寿命是关键

干我们这行的,提起“可靠性测试”,不少人第一反应是:把样品扔进温箱里烤一烤、冻一冻,再放振动台上摇一摇,出来没坏就算通过。要是真这么想,那可靠性测试就白做了。作为一个和温箱、振动台、耐久跑法打了十…

2026/10/9 7:02:48 阅读更多 →
JVM内存模型与调优实战:从Minecraft OOM到HMCL配置

JVM内存模型与调优实战:从Minecraft OOM到HMCL配置

很多朋友第一次真正意识到 JVM 的存在,不是在 Java 课堂上,而是在一个完全不相关的场景里——玩游戏的时候。我用 HMCL 启动器给 Minecraft 装了个整合包,点了启动,等了两分钟,游戏闪退。把日志拉到最底部,…

2026/10/9 7:02:48 阅读更多 →
VS Code AI 语言模型配置全指南:模型切换、思维强度与 BYOK 自有密钥接入

VS Code AI 语言模型配置全指南:模型切换、思维强度与 BYOK 自有密钥接入

文档教程 【免费下载链接】vscode-docs Public documentation for Visual Studio Code 项目地址: https://gitcode.com/gh_mirrors/vs/vscode-docs 点击查看 免费下载 本文基于 Visual Studio Code 官方文档仓库(vscode-docs)中的 docs/agen…

2026/10/9 7:02:48 阅读更多 →
多标签文本分类实战复盘:从Embedding到Transformer的TAAC优化之路

多标签文本分类实战复盘:从Embedding到Transformer的TAAC优化之路

1. 从"vibe coding"说起:一个新手小白的TAAC复盘到底在复盘什么第一次看到"vibe coding"这个词,我脑子里蹦出来的画面是:一个人对着编辑器,凭感觉敲代码,跑通了就欢呼,跑不通就换一种写…

2026/10/9 7:02:48 阅读更多 →
内容团队如何用Qoder构建标准化AI工作流与协作机制

内容团队如何用Qoder构建标准化AI工作流与协作机制

团队里六个人,过去半年试过不下四个AI工具,从网页版问答到各种套壳应用,最后都回到同一个问题:AI确实能干活,但每个人干出来的活参差不齐,提示词散落在各自收藏夹里,换个项目就抓瞎。真正让我下…

2026/10/9 7:02:48 阅读更多 →
日期处理陷阱:从1月25日看时区与历法边界

日期处理陷阱:从1月25日看时区与历法边界

我很少拿一个日期当文章标题,但1月25日这个数字,我记了快一整年。不是因为它特殊——公历里它既不是节日也不算节气,每年对应的星期几、农历日子完全不一样。正因为它"每天都在变、又好像什么都没变",才在交付前一周把我…

2026/10/9 7:01:47 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →