基于 YOLO11 的宠物皮肤病智能检测系统

举报
柠檬🍋 发表于 2026/10/20 23:41:05 2026/10/20
【摘要】 基于 YOLO11 的宠物皮肤病智能检测系统一套面向宠物家庭、繁育场和宠物医院的皮肤病初筛工具,使用 YOLO11n + Streamlit 构建。上传宠物皮肤照片或视频,AI 自动定位病灶并给出"细菌性皮肤病 / 蠕形螨病 / 跳蚤过敏性皮炎 / 真菌感染 / 炎症性皮炎 / 疥螨病"六类常见皮肤病的初步判断,辅助早期就医。一、背景1.1 行业痛点宠物皮肤病的早期识别有三难:症状隐蔽:脱毛...

基于 YOLO11 的宠物皮肤病智能检测系统

一套面向宠物家庭、繁育场和宠物医院的皮肤病初筛工具,使用 YOLO11n + Streamlit 构建。上传宠物皮肤照片或视频,AI 自动定位病灶并给出"细菌性皮肤病 / 蠕形螨病 / 跳蚤过敏性皮炎 / 真菌感染 / 炎症性皮炎 / 疥螨病"六类常见皮肤病的初步判断,辅助早期就医。

一、背景

1.1 行业痛点

宠物皮肤病的早期识别有三难:

  1. 症状隐蔽:脱毛、红斑、丘疹早期细微,铲屎官肉眼难分清是过敏、真菌还是螨虫;
  2. 病种相似:细菌性皮肤病、蠕形螨病和疥螨病在病灶视觉表现上高度相似,非专业人员极易误判;
  3. 就诊滞后:等到大面积溃烂、瘙痒搔抓出血才发现,往往已经错过最佳治疗窗口,治疗成本翻倍。

本项目把"看一眼像不像皮肤病"这件事用 AI 标准化下来:上传照片, 模型 给出病灶位置 + 类别 + 置信度,作为兽医诊断前的初筛工具,帮主人尽早决定要不要就医。

数据集包含 3000 张高质量标注图像,覆盖宠物毛发遮挡、病变初期、光照不均、毛色差异等真实养护场景,按 YOLO 格式组织(train / valid / test),六个类别 nc=6:细菌性皮肤病 / 蠕形螨病 / 跳蚤过敏性皮炎 / 真菌感染 / 炎症性皮炎 / 疥螨病。

视频演示与源码下载

https://www.bilibili.com/video/BV1tmHJ6tE31/

在这里插入图片描述

包含: 📦完整项目源码 📦 预训练 模型权重

🗂️数据集

1.2 项目运行效果

Web 界面总览(兽医诊室的薄荷绿 + 温暖琥珀橙主题,强调安心感):

在这里插入图片描述

在这里插入图片描述

单张图片检测效果(左原图,右标注图;下方会附"病种科普 + 护理提示"卡片):

在这里插入图片描述

1.3 项目介绍

创新点 / 亮点

维度 说明
多病种细分 一次推理覆盖 6 类常见宠物皮肤病,比"是否异常"二分类更可指导就医
病种科普卡片 每检出一类,前端自动渲染"病因 + 护理提示",让铲屎官看得懂、能行动
中文类别 训练即用中文标签,无需前端翻译
多源接入 单图 / 批量 / 视频 / 摄像头四种入口,门诊、家庭、繁育场都能用
免责声明 检测结果页固定显示"仅供初步筛查参考,最终诊断以执业兽医为准"

系统功能概览

  • 单张照片:上传患处照片 → 标注图 + 病种 + 护理建议
  • 多张照片:多图或 ZIP 批量推理,输出整窝/整群的病种分布
  • 视频检测:短视频逐帧分析,导出标注视频与明细 CSV
  • 摄像头实时:浏览器拉本机摄像头,对宠物体表做"边扫边看"

技术栈

层级 技术选型
检测模型 YOLO11n(Ultralytics)
Web 框架 Streamlit
图像处理 OpenCV、Pillow
数据 / 图表 Pandas、Streamlit 原生图表
视频编解码 imageio-ffmpeg
部署 Python 3.9+,本地 / 容器 / 边缘盒子

类别定义:nc=6,names=['细菌性皮肤病','蠕形螨病','跳蚤过敏性皮炎','真菌感染','炎症性皮炎','疥螨病']。


二、设计框架

系统架构

┌────────────────────────────────────────────────────────────┐
│            用户浏览器(铲屎官 / 宠物医生 / 繁育主)        │
│  📷 单张照片 │ 🗂 多张照片 │ 🎬 视频检测 │ 📹 摄像头        │
└──────────────────────┬─────────────────────────────────────┘
                       │ HTTP / WebSocket
┌──────────────────────▼─────────────────────────────────────┐
│              Streamlit App (app/streamlit_app.py)          │
│  · 模式路由 + 病种科普卡片                                 │
│  · 配色 / 标题 / 描述均由 project.yaml 驱动                │
│  · 渲染明细表 + 批量分析图                                 │
└──────────────────────┬─────────────────────────────────────┘
                       │ model.predict(conf=0.25, iou=0.7)
┌──────────────────────▼─────────────────────────────────────┐
│                 YOLO11n 推理引擎                           │
│  Backbone (C2f + SPPF) → Neck (FPN + PAN) → Decoupled Head │
│  + DFL(分布式回归) → NMS                                 │
└──────────────────────┬─────────────────────────────────────┘
                       │ result.boxes (cls, conf, xyxy)
┌──────────────────────▼─────────────────────────────────────┐
│  后处理:apply_class_display + 病种知识库映射              │
│  → 标注图 + 明细 + 护理提示卡片                            │
└────────────────────────────────────────────────────────────┘

YOLO11 网络结构

  • Backbone:连续 Conv + C2f 下采样 5 次 + 末端 SPPF 多尺度池化
  • Neck:FPN(自顶向下)+ PAN(自底向上)双向融合,对小面积病灶友好
  • Head:解耦头 + DFL 分布式回归,对边缘模糊、毛发遮挡的病灶定位更稳
  • 损失:BCE(分类)+ CIoU + DFL(回归)

检测流程:图像 → letterbox 缩放至 imgsz=640 → 推理 → conf 过滤(0.25) → NMS(iou=0.7) → 类别映射 → 病种知识库匹配 → 前端渲染。


三、代码结构(核心 50 行 + 解析)

项目结构:

宠物皮肤病检测/
├── app/streamlit_app.py             # Streamlit Web 入口
├── configs/project.yaml             # 业务配置(病种显示名、UI 配色)
├── model/best.pt                    # YOLO11n 训练权重
├── scripts/                         # 训练 / 评测 / 导出脚本
├── 宠物皮肤病目标检测YOLO数据集/      # 数据集(train / valid / test)
└── 宠物皮肤病检测yolo11_train/        # 训练产物(中英文两份)

核心 50 行(精简自 app/streamlit_app.py):

from pathlib import Path
import pandas as pd
import streamlit as st
import yaml
from ultralytics import YOLO

PROJECT_ROOT = Path(__file__).resolve().parent.parent
CONFIG_PATH = PROJECT_ROOT / "configs" / "project.yaml"
MODEL_PATH = PROJECT_ROOT / "model" / "best.pt"

APP_CFG = yaml.safe_load(open(CONFIG_PATH, "r", encoding="utf-8"))
APP_META = APP_CFG.get("app", {})
INFER_META = APP_CFG.get("inference", {})
CLASS_DISPLAY = APP_META.get("class_display_names") or {}
DEFAULT_CONF = float(INFER_META.get("conf", 0.25))
DEFAULT_IOU = float(INFER_META.get("iou", 0.7))

@st.cache_resource(show_spinner=False)
def load_model(model_path: str) -> YOLO:
    return YOLO(model_path)

def apply_class_display(name: str) -> str:
    return CLASS_DISPLAY.get(name, name)         # 支持英文 ↔ 中文病名映射

def infer_image(model: YOLO, image_path: Path, conf: float):
    result = model.predict(str(image_path), conf=conf, iou=DEFAULT_IOU, verbose=False)[0]
    annotated = result.plot()
    rows = []
    if result.boxes is not None:
        for box in result.boxes:
            cls_id = int(box.cls.item())
            raw_name = result.names[cls_id]
            rows.append({
                "class_id": cls_id,
                "class_name": raw_name,
                "display_name": apply_class_display(raw_name),  # 用于前端展示
                "confidence": round(float(box.conf.item()), 4),
                "x1": float(box.xyxy[0][0]), "y1": float(box.xyxy[0][1]),
                "x2": float(box.xyxy[0][2]), "y2": float(box.xyxy[0][3]),
            })
    return annotated[:, :, ::-1], pd.DataFrame(rows)   # BGR -> RGB

# ---------------- Streamlit 主流程 ----------------
st.set_page_config(page_title=APP_META.get("title"), layout="wide")
model = load_model(str(MODEL_PATH))
conf = st.sidebar.slider("置信度阈值", 0.05, 0.95, DEFAULT_CONF, 0.05)
mode = st.radio("接入源", ["📷 单张照片", "🗂 多张照片", "🎬 视频检测", "📹 摄像头"], horizontal=True)

if mode == "📷 单张照片":
    uploaded = st.file_uploader("上传宠物患处照片", type=["jpg", "png", "jpeg"])
    if uploaded is not None:
        tmp = Path("/tmp") / uploaded.name
        tmp.write_bytes(uploaded.getvalue())
        annotated, df = infer_image(model, tmp, conf)
        col1, col2 = st.columns(2)
        col1.image(uploaded.getvalue(), caption="原图")
        col2.image(annotated, caption="检测结果")
        if not df.empty:
            st.bar_chart(df["display_name"].value_counts())
        st.caption("AI 检测结果仅作初步筛查参考,最终诊断请以执业兽医为准。")

逐段解析

  1. project.yaml 的 class_display_names 做了"英文 → 中文病名"映射,训练样本英文标签也可以无缝在前端展示中文,对运营友好。
  2. @st.cache_resource 缓存权重,单图响应稳定在 100ms 级;置信度滑动条 + model.predict(conf=conf) 让用户自己控制宽严,皮肤病数据噪声大,调高一档可显著降误报。
  3. infer_image 同时返回 annotated(带框图)和 DataFrame(明细),DataFrame 可直接驱动 st.bar_chart 输出"本次检测各病种数量",也可导出 CSV 给宠物医生跟进。
  4. st.set_page_config + st.radio 四模式路由复用同一份推理逻辑,新增摄像头流只需再写一段 st.camera_input。
  5. 页脚强制提醒"仅作初筛参考",符合 AI 医疗类应用的合规要求,避免误导主人自行诊断。

四、训练效果

训练采用 YOLO11n 预训练权重 微调 ,epochs=200, imgsz=640, batch=16, patience=100。best.pt 对应的最佳指标:

指标 数值
Precision (B) 0.680
Recall (B) 0.649
mAP@0.5 0.681
mAP@0.5:0.95 0.413

训练结果总览

说明:当前 mAP@0.5 ≈ 0.68,模型仍在迭代中。皮肤病检测是已知比较"硬"的任务,主要原因有三:

  • 类内差异大:同一种皮肤病在长毛/短毛、白毛/深色毛宠物身上的视觉表现差异显著;
  • 类间高度相似:细菌性皮肤病、蠕形螨病和疥螨病早期病灶在 RGB 图像上几乎无法区分,需要纹理 + 局部细节联合判断;
  • 样本规模偏小:3000 张图分到 6 类,单类平均不足 500 张,长尾问题明显。

下一阶段优化方向:扩充难类样本(重点补 demodicosis / scabies)、引入毛发分割辅助任务、升级到 YOLO11s 并配合多尺度 TTA、训练时加入 Mosaic+Mixup 抑制过拟合。

由于本阶段 mAP 尚未达到放出 PR / 混淆矩阵的内部阈值(≥ 0.85),暂仅展示训练 loss / 指标随 epoch 的总览图。从曲线看,box / cls / dfl loss 平稳下降,P/R 在中后段趋于平台,未出现过拟合震荡,模型已经"学会"任务,差距主要在精度上限。


五、项目总结

做对了什么

  • 用六分类替代"是否异常"二分类,让 AI 的输出能直接对接铲屎官的下一步动作(科普 / 就医 / 复查)。
  • project.yaml 描述配色、病种显示名、批量上限,换品种、换语言都不用改代码。
  • 强制免责声明 + 病种科普卡片,让产品既"敢用"又"会用",符合 AI 医疗类应用的伦理与合规要求。

还能怎么做

  • 引入轻量分割模型(YOLO11n-seg)对病灶面积做量化,给出"皮损面积占比"这种可比指标,方便复诊跟踪。
  • 加入皮肤毛发预处理 / GAN 增强,提升毛发遮挡场景下的检测召回。
  • 接入兽医后台:检测明细 + 标注图自动归档到云端病历,复诊时调取,跟踪治疗效果。
  • 模型迭代到 mAP@0.5 ≥ 0.85 后,再开放"高置信度自动提示就医"功能,前期保持人工 in-the-loop。

一句话总结

YOLO11n + Streamlit 把"宠物皮肤病早期筛查"从经验判断变成了可量化、可复用、可合规的工程化能力,是 AI for Pet Health 一个非常落地的切入点。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。