基于 YOLO11 的宠物皮肤病智能检测系统
一套面向宠物家庭、繁育场和宠物医院的皮肤病初筛工具,使用 YOLO11n + Streamlit 构建。上传宠物皮肤照片或视频,AI 自动定位病灶并给出"细菌性皮肤病 / 蠕形螨病 / 跳蚤过敏性皮炎 / 真菌感染 / 炎症性皮炎 / 疥螨病"六类常见皮肤病的初步判断,辅助早期就医。
一、背景
1.1 行业痛点
宠物皮肤病的早期识别有三难:
- 症状隐蔽:脱毛、红斑、丘疹早期细微,铲屎官肉眼难分清是过敏、真菌还是螨虫;
- 病种相似:细菌性皮肤病、蠕形螨病和疥螨病在病灶视觉表现上高度相似,非专业人员极易误判;
- 就诊滞后:等到大面积溃烂、瘙痒搔抓出血才发现,往往已经错过最佳治疗窗口,治疗成本翻倍。
本项目把"看一眼像不像皮肤病"这件事用 AI 标准化下来:上传照片, 模型 给出病灶位置 + 类别 + 置信度,作为兽医诊断前的初筛工具,帮主人尽早决定要不要就医。
数据集包含 3000 张高质量标注图像,覆盖宠物毛发遮挡、病变初期、光照不均、毛色差异等真实养护场景,按 YOLO 格式组织(train / valid / test),六个类别 nc=6:细菌性皮肤病 / 蠕形螨病 / 跳蚤过敏性皮炎 / 真菌感染 / 炎症性皮炎 / 疥螨病。
视频演示与源码下载

包含: 📦完整项目源码 📦 预训练 模型权重
🗂️数据集
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 检测结果仅作初步筛查参考,最终诊断请以执业兽医为准。")
逐段解析
project.yaml的class_display_names做了"英文 → 中文病名"映射,训练样本英文标签也可以无缝在前端展示中文,对运营友好。@st.cache_resource缓存权重,单图响应稳定在 100ms 级;置信度滑动条 +model.predict(conf=conf)让用户自己控制宽严,皮肤病数据噪声大,调高一档可显著降误报。infer_image同时返回annotated(带框图)和DataFrame(明细),DataFrame 可直接驱动st.bar_chart输出"本次检测各病种数量",也可导出 CSV 给宠物医生跟进。st.set_page_config + st.radio四模式路由复用同一份推理逻辑,新增摄像头流只需再写一段st.camera_input。- 页脚强制提醒"仅作初筛参考",符合 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 一个非常落地的切入点。