拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于YOLOv8的痤疮图像目标检测:从数据标注到模型训练实战

基于YOLOv8的痤疮图像目标检测:从数据标注到模型训练实战 简介YOLOv8框架下的痤疮图像数据集是一份面向皮肤病变识别任务构建的标注图像集合适用于目标检测算法的训练与性能评估可服务医疗辅助诊断场景。整个压缩包共2000个文件约39.37MB以738张jpg痤疮图像和927个txt标注文件为主体标注内容符合YOLOv8格式要求每个目标包含定位框与整数类别标识另有少量md说明文档、Python脚本、yaml配置、pt权重及zbak备份文件便于理解数据组织与模型使用。目前已有75人浏览学习。数据集中图片覆盖不同阶段或类型的痤疮样本训练前可按需划分训练集、验证集与测试集并配合尺寸调整、归一化等预处理流程ignore.txt可用于排除无效样本保证模型聚焦有效特征。整体上这份数据适合作为痤疮识别、肤色病变检测等深度学习项目的起步数据能够帮助快速验证YOLOv8训练流程并推动医疗智能化应用。1. 皮肤科图像识别的第一步不是模型而是把痤疮数据集和标注规范一起定下来很多做痤疮图像识别的人一上来就卡在同一处YOLOv8 环境装好了、预训练权重也下下来了打开一张面部照片却不知道怎么下手标注。痤疮不是一个“整张脸是否患病”的图像分类问题而是一张脸上有多个小目标、多个类别、还有大量“像又不像”的皮损形态。这篇文章围绕 YOLOv8 框架讲清楚三件事数据从哪来、标注怎么定、训练参数怎么设。适合想用 YOLOv8 做皮肤影像目标检测的开发者、医工交叉方向的研究生以及对标注质量有硬要求的数据标注团队。2. 搭建环境到完成第一批标注跑通 YOLOv8 的最小闭环2.1 环境搭建CPU 版也能训练痤疮小数据集先别急着上 GPU。痤疮图像数据集在起步阶段通常只有几百张图CPU 跑 YOLOv8 的 detect 任务n/s 档位一次训练 100 个 epoch 也就几小时到十几小时完全够做数据质量验证。等确认标注没问题再考虑 GPU 或云服务。ubuntu20.04 上搭建 CPU 版本 YOLOv8 环境的常见做法是# 1. 创建虚拟环境避免污染系统 Python python3 -m venv yolov8_env source yolov8_env/bin/activate # 2. 安装 PyTorch CPU 版本 pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu # 3. 安装 ultralytics 包 pip install ultralytics逻辑说明先用 venv 隔离环境避免和系统里其他项目的包冲突。第二步装 CPU 版 PyTorch关键在--index-url参数指向 CPU 版 wheel 源——默认pip install torch会拉 CUDA 版本在无 GPU 机器上装了也会在运行时提示 CUDA unavailable。第三步装 ultralytics 官方包它会自动把 yolo CLI 装进 PATH。验证环境是否通yolo predict modelyolov8n.pt sourcetest.jpg能输出一张带框的预测图说明环境通了。CPU 上单张推理通常 1 到 3 秒这个速度用来做标注抽查和预测验证完全够。yolov8n是 nano 档位模型文件约 6MBCPU 推理最快适合起步阶段跑通流程后续精度不够再换yolov8s或yolov8m。2.2 labelme 标注痤疮图像哪些区域需要画框数据集的整体质量由标注环节决定。痤疮皮损的特点是单个区域小、边界模糊、多个类型密集排布。常见做法是用 labelme 的 rectangle 而不是 polygon原因有两点。第一YOLOv8 的原生输出就是矩形框多边形标注转换时会额外计算外接矩形遇到倾斜皮损区域会有信息损耗第二标注人员画矩形框的速度远快于描边同样时间能多标一倍的图起步阶段最缺的就是数据量。labelme --labels labels.txt --nodatalabels.txt 内容closed_comedo inflamed_papule pustule nodule_cyst参数说明--labels指定预定义类别文件让标注人员下拉选择而不是手敲避免同一类别出现大小写或空格不一致--nodata去掉 base64 图像数据JSON 文件体积能小不少转换脚本读写也更快。标注一张面部照片时的三条基本规则单个皮损独立画框两个粘连的痤疮尽量分开标。宁可两个框重叠后的 IoU 超过 0.5也不要漏掉一个目标。框的边界贴着皮损的可视边界不延伸到周围正常皮肤。对红肿晕染区域以颜色变化明显的地方为界。某块区域密度过高时比如鼻翼两侧密集闭口以“能数清轮廓的最小单位”为准融合成片的闭口就框成一个大框并归到closed_comedo。2.3 把 labelme 标注转成 YOLOv8 训练格式转换脚本与坐标换算labelme 生成的 JSON 是 polygon 点集YOLOv8 需要的是归一化中心点坐标和宽高。转换脚本是数据管线里的第一个坑。import json import os from glob import glob from PIL import Image def convert_labelme_to_yolo(json_path, class_names, out_dir): with open(json_path, r, encodingutf-8) as f: data json.load(f) img_path data[imagePath] img Image.open(os.path.join(os.path.dirname(json_path), img_path)) img_w, img_h img.size out_txt os.path.join(out_dir, os.path.basename(json_path).replace(.json, .txt)) with open(out_txt, w, encodingutf-8) as f: for shape in data[shapes]: label shape[label] if label not in class_names: continue # 用多边形所有点的外接矩形作为检测框 points shape[points] xs [p[0] for p in points] ys [p[1] for p in points] x_min, x_max min(xs), max(xs) y_min, y_max min(ys), max(ys) # 归一化到 0~1 x_center (x_min x_max) / 2 / img_w y_center (y_min y_max) / 2 / img_h box_w (x_max - x_min) / img_w box_h (y_max - y_min) / img_h class_id class_names.index(label) f.write(f{class_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}\n)转换逻辑说明labelme 的points是二维数组每个元素是[x, y]像素坐标。转换时取所有点的最小外接矩形替代多边形这是最稳妥做法——痤疮皮损形状不规则外接矩形能保证召回率。归一化坐标是 YOLOv8 的硬性要求中心点坐标除以图像宽高后取值范围必定落在 0 到 1。执行转换并整理目录mkdir -p datasets/acne/images datasets/acne/labels python convert.py # 把上述脚本落地为 convert.py 后执行原图放进 images 目录标注 txt 放进 labels 目录两个目录同一层级、文件名一一对应00001.jpg对应00001.txtYOLOv8 才能正确配对。3. 痤疮图像数据集的类目定义与数量设计标注规范是第一道闸门3.1 四分类还是二分类类目边界决定模型能力痤疮图像识别的类目定义不能拍脑袋。常见的是四分类闭口closed_comedo、炎性丘疹inflamed_papule、脓疱pustule、结节囊肿nodule_cyst。这个粒度对应临床面诊习惯——医生就是按皮损形态分型的。类别边界要写进标注规范文档几个容易混淆的边界闭口 vs 炎性丘疹闭口触摸是平的或微微凸起无明显红肿炎性丘疹基底部有红色晕染。拿不准时按轮廓是否隆起判断。脓疱 vs 炎性丘疹脓疱顶部有可见的白色或黄色脓点丘疹没有。结节囊肿直径通常大于 5mm按压有硬结感已经破溃流脓的仍按结节囊肿标注。如果标注人员非医学背景给每个类别配 3 张典型示例图和 3 张边界示例图贴在标注规范第一页。这不是文档工程是实际减少返工的必要投入。我见过团队因为“炎症性丘疹”和“脓疱”的定义纠缠了三天最后就是靠示例图统一了标准。3.2 数据规模怎么定小样本起底、按类别计数监控痤疮数据集没有公开的大规模标准库起步阶段的数据规模完全自己控制。经验值是这样第一版数据集凑 300 到 500 张图每张图平均 3 到 10 个标注框四分类合计约 1500 到 5000 个实例。用 YOLOv8n 在这个规模上训练mAP50 能做到 0.6 到 0.75足以验证标注规范是否一致、类别定义是否清晰。划分时按 7:2:1 切训练集、验证集、测试集。有个容易被忽略的规则按“患者”而不是按“图片”划分。同一个人的脸出现在训练集又出现在验证集模型会通过皮肤纹理而不是痤疮特征来识别验证分数会虚高。import os import random from shutil import copy2 imgs os.listdir(datasets/acne/images) random.seed(42) random.shuffle(imgs) n_total len(imgs) n_train int(n_total * 0.7) n_val int(n_total * 0.2) for idx, img in enumerate(imgs): split train if idx n_train else val if idx n_train n_val else test src_img fdatasets/acne/images/{img} src_lbl fdatasets/acne/labels/{img.replace(.jpg, .txt)} dst_dir fdatasets/acne/{split} os.makedirs(f{dst_dir}/images, exist_okTrue) os.makedirs(f{dst_dir}/labels, exist_okTrue) copy2(src_img, f{dst_dir}/images/{img}) copy2(src_lbl, f{dst_dir}/labels/{img.replace(.jpg, .txt)})划分逻辑说明先打乱所有图片再按比例切分固定随机种子保证可复现。这个简单方案对几百张的规模够用。如果要按“患者”划分先维护一张 image_to_patient 映射表把同一患者的图片全部放进同一个分片再做随机打乱。增强策略方面痤疮图像不适合做水平翻转之外的重度增强。人脸左右对称水平翻转不改变痤疮形态但颜色抖动、高斯噪声会破坏皮肤纹理的红肿信息——模型可能学会识别噪声纹理而不是皮损本身。YOLOv8 自带的 mosaic 增强在痤疮小目标场景下建议调低因为 mosaic 会把四张图缩到极小尺寸再拼贴痤疮目标缩小后几乎不可见模型学到的全是噪声。3.3 文件组织方式YOLOv8 支持的目录结构数据集目录建议这样组织和 YOLOv8 的 data yaml 直接对应path: datasets/acne train: train/images val: val/images test: test/images nc: 4 names: [closed_comedo, inflamed_papule, pustule, nodule_cyst]path是相对于 yaml 文件位置的根目录train/val/test 用相对路径指向 images 目录YOLOv8 自动在兄弟目录 labels 下找同名 txt。nc和names必须一一对应顺序和类别文件的 index 完全一致。这一步错了模型会静默地学错标签——它不会报错但预测输出的类别全是错位的。4. 训练痤疮检测模型参数含义、命令与曲线判读4.1 训练命令与关键参数数据结构和 yaml 就绪后启动训练一条命令yolo detect train \ datadatasets/acne/acne.yaml \ modelyolov8n.pt \ epochs150 \ imgsz640 \ batch8 \ lr00.01 \ patience30 \ devicecpu参数逐个拆解modelyolov8n.pt加载官方预训练权重。coco 数据集上训练过的模型对真实图像的纹理特征有很好的先验痤疮虽然不在 coco 类别里迁移学习仍能显著加速收敛。imgsz640训练输入尺寸。痤疮是小目标输入尺寸不够时一个 5 像素的闭口在特征图上可能只剩 2x2 个格子。算力允许就 640 起步数据量上来后再试 1280。batch8CPU 环境下默认 batch 是设备自适应的但经常白天是 16、内存一紧张就掉到 4。显式指定 batch避免训练中途因内存波动而中断。lr00.01初始学习率。fine-tune 场景通常用 0.01 以下第一个 epoch 出现 NaN 就说明学习率太大。patience30早停参数。连续 30 个 epoch 验证集指标不提升就自动停止防止过拟合浪费机器时间。devicecpu显式指定 CPU。不设的话 ultralytics 会自动检测偶尔会试图调 CUDA 结果报错。4.2 损失函数曲线与 mAP 曲线怎么读训练结束后runs/detect/train目录下会生成results.png包含 train/box_loss、train/cls_loss、train/dfl_loss 和对应的验证集曲线。判读要点box_loss 和 cls_loss 在训练集、验证集上都应持续下降。如果 train/box_loss 降但 val/box_loss 先降后升说明过拟合回退 epoch 或加大权重衰减。mAP50 和 mAP50-95。如果 mAP50 在 0.6 以上而 mAP50-95 只有 0.3 以下说明模型对框的位置不够准通常意味着闭口这类小目标漏检严重。yolo detect train \ datadatasets/acne/acne.yaml \ modelyolov8n.pt \ epochs300 \ imgsz640 \ batch16 \ lr00.005 \ cos_lrTrue \ plotsTruecos_lrTrue让学习率按余弦退火衰减在长训练中比线性衰减更容易收敛到低 loss 点plotsTrue确保每轮验证后生成混淆矩阵和预测样例图。训练完成后用验证集看实际效果yolo detect predict \ modelruns/detect/train/weights/best.pt \ sourcedatasets/acne/val/images/00001.jpg \ save_txtTruesave_txtTrue把预测结果输出成 txt每行是类别 id、置信度和归一化坐标。对比原标注 txt 能快速判断哪个类别混淆严重。5. 痤疮数据集标注避坑指南5 个必须提前知道的坑5.1 标注框画到头发和阴影上模型学的是皮肤纹理而不是痤疮现象模型在验证集上精度不低换到新患者脸上就大量误检在头发边缘、阴影交界处疯狂画框。原因标注规范里没有定义“皮损是否覆盖毛发”标注人员把头发遮挡的阴影当成了痤疮边界画进去。模型学到的特征是深色线条边界的组合恰好头发和阴影也有这个特征。解决在标注规范里加一条规则——皮损与头发重叠时不标整个框只标皮损肉眼可见的裸露区域阴影下的皮肤不标注除非皮损有明确的形状轮廓。加上这条规则重新标注一批数据误检率能明显下降。5.2 晚上手机拍的照片全部漏检现象训练集里大多是白天自然光照片模型在泛黄灯光下拍的图上几乎检不出炎性丘疹。原因白平衡和光照色温改变了皮损的红色特征。YOLOv8 输入是三通道 RGB模型学到的“红肿”特征高度依赖颜色分布灯光一偏黄就把红色信息淹没。解决数据采集阶段刻意加入三种光照条件——自然光、室内灯、手机闪光灯每类至少占总量 20%。如果数据集已经定死用颜色增强模拟不同色温import cv2 import numpy as np def apply_white_balance_augment(img, temp_shift): b, g, r cv2.split(img) r np.clip(r.astype(np.int16) temp_shift, 0, 255).astype(np.uint8) return cv2.merge([b, g, r])这段代码在训练前对图像做红通道偏移模拟不同色温代价是增加一点训练时间但对光照鲁棒性提升值得。5.3 同一张脸出现重复框现象验证时模型对同一个炎性丘疹输出两个几乎重叠的框置信度差异不大。原因痤疮检测的锚框分配机制对密集小目标会触发多个预测头同时命中YOLOv8 的 NMS 默认参数在目标过小、间距过密时不太好使。解决预测时调低置信度阈值并加大 NMS 的 IoU 阈值——conf0.25、iou0.4在痤疮数据上通常比默认的iou0.7产生更少重复框。如果训练集里密集区域重复框多先检查标注是否把两个紧挨着的皮损框成了一个整体。5.4 类别严重不平衡闭口标注了 2000 个结节囊肿只有 80 个现象训练后结节囊肿的 recall 只有 0.2闭口的 recall 有 0.85。原因四分类数据量差距太大YOLOv8 默认类别损失权重均等模型为了压低整体 loss 会偏向样本多的类别。解决两条路并行——先给少数类做离线增强旋转 90 度、180 度、270 度各生成一份把 80 个实例补到 300 个以上如果项目允许再收集更多结节囊肿样本数据增强只能缓解不能根治分布偏移。5.5 训练 loss 不降反升或第一个 epoch 就 NaN现象训练到 20 个 epochloss 还在 2 以上波动或者直接在第一个 epoch 出现 NaN。原因最常见的是学习率设置过高。CPU 环境小 batch 时梯度更新方差大lr00.01 对 batch8 来说太激进。解决把 lr0 降到 0.001batch 提到 16 以上或者显式配置warmup_epochs3让模型在前三个 epoch 用小学习率稳定梯度再接正式学习率。另外检查数据里有没有全黑坏图全黑图像的标注框坐标算出来是 0会造成梯度异常。6. 用小样本快速验证数据质量的三个手段数据量还没凑齐之前不要直接上全量训练。我常用的做法是先挑 50 张图人工标注一遍跑通全流程用三件事验证标注规范是否自洽。第一看类别分布。50 张图标注完统计每类实例数。如果四类里有一类为 0说明采集侧漏了这类皮损此时改标注规范没用要先补采集。第二看框的一致性。把同样的图给两个标注人员各自标一遍计算同一张图上两个版本标注框的 IoU。如果平均 IoU 低于 0.6说明标注规范的边界条款不够明确需要回炉。第三看训练损失能否降下去。50 张图跑 30 个 epoch如果 box_loss 能降到 1.2 以下说明数据管线是通的如果 loss 卡在 2 以上优先检查坐标转换脚本而不是盲目加数据。这三步都通过后再按第 3 章的规模扩大数据集。我自己的习惯是给每个批次的数据留一个校对步骤训练完用 best.pt 预测训练集本身把预测框和标注框画在同一张图上人工扫一遍。这一步基本能暴露 95% 的标注错误——漏标的、标错的、框画大的。这个过程很费眼但比模型训完上线后翻车再返工要省得多。以上是我在痤疮图像识别项目里踩过的坑和验证过的流程希望帮到你。本文还有配套的精品资源点击获取
返回列表