资讯详情

基于YOLO的猫情绪识别:小目标检测与细粒度分类实战

📅 2026/9/30 10:22:06 | 华诺云谱 👁 阅读
基于YOLO的猫情绪识别:小目标检测与细粒度分类实战
猫情绪检测听起来像是智能家居或者宠物博主的新玩具但放在计算机视觉领域里它其实是一个非常典型的“小目标检测细粒度分类”落地场景。我花了几周时间从零搭了一套基于YOLO的猫情绪识别流程自己采集、清洗、标注了3200张猫咪行为图片训练出了能区分放松、警惕、紧张、攻击准备等状态的检测模型。这篇文章把整个项目从数据到部署的完整链路拆开讲包括踩过的坑和最后能用起来的经验给正在做宠物识别、小目标检测或者YOLO自训练数据集的读者一个可参考的样板。别一上来就想着把模型跑多深、收敛多好这个项目的第一个坎其实不在模型而在数据。猫这个物种的情绪表达方式跟人完全不一样——耳朵、尾巴、瞳孔、身体姿态每一个维度都在说话而且不同的猫个体差异极大。3200张图片到底够不够、该怎么分配、标注到什么粒度我是在踩了一周的坑之后才慢慢摸清套路的。1. 项目动机与整体设计思路1.1 为什么选择“视觉检测”而非穿戴设备测情绪养猫的人都知道猫的情绪判断很大程度靠经验——资深铲屎官通过耳朵角度、尾巴摆动频率、瞳孔大小就能判断猫是在开心还是准备伸爪子。但如果要把这件事自动化就面临两个路线选择一是给猫戴智能项圈采集心率、活动量等生理信号二是用摄像头做纯视觉识别。我最后选了纯视觉的YOLO路线核心原因有三个。第一是设备门槛低一个普通USB摄像头就能搞定不需要给猫穿戴任何东西猫也不会产生应激反应。第二是数据获取成本低且自然日常在家随手就能拍到猫的各种状态不需要刻意设计实验场景。第三是从产品化角度看视觉方案更容易嵌入到智能家居、猫窝、喂食器等现有设备里用户的接受度更高。但视觉路线的代价也很明显——猫的情绪本身是一个高度模糊的概念不像人脸表情有相对标准的编码体系。同一种情绪在不同品种、不同年龄、不同个体上的表现差异非常大这直接决定了标注规范和模型训练的难度。所以整个项目的起点不是模型架构而是先定义清楚“什么叫猫在放松”“什么叫猫在紧张”。1.2 技术选型YOLO家族为什么最适合这个场景选YOLO而不是Transformer系检测器或两阶段检测器是我对比过实际效果后做的决定。猫情绪检测这个任务有两个显著特点第一猫经常处于运动中对检测的实时性有要求第二情绪判断依赖的关键信号区域很小——瞳孔变化、耳朵角度、胡须状态都只占整张图的很小比例需要模型有不错的小目标感知能力。YOLO系列在这两个维度上平衡得最好。相比Transformer系YOLO的部署更加轻量在树莓派、Jetson这类边缘设备上也能跑出可用的帧率相比Faster R-CNN这类两阶段模型YOLO的推理速度优势明显而且近年版本的小目标检测能力已经有了明显提升。具体到版本选择我最终用的是YOLOv8而不是更新的YOLO11或v12。原因很实际v8的生态最成熟预训练权重选择多社区资料丰富踩坑时有大量现成解决方案。YOLO11在精度上有提升但对数据量和标注质量的要求也更高对于3200张这种小规模数据集来说v8的泛化能力反而更稳。1.3 数据规模设计的底层逻辑3200张到底够不够很多人看到3200张第一反应是“这么少能行吗”。我的回答是小而精的数据集在策略得当的情况下效果不一定输给盲目堆量的大数据集。这里有一笔很关键的账——我定义的情绪类别是5种放松、警觉、紧张、攻击准备、玩耍每个类别需要的有效样本数是均衡的。3200张分到每类约640张在训练时配合数据增强实际喂给模型的样本量可以等效扩充到上万张。但这里有一个重要前提每张图片的标注质量必须过关。宁可只有3200张每张都标得准确也不要贪多贪快标注出10000张充满噪声的数据。我在清洗环节淘汰掉了将近800张模糊、过暗、多猫重叠难以判断的图片留下的都是情绪信号清晰、主体占比合理的高质量样本。这个决策在后面训练时被证明是值得的——模型收敛速度和最终精度都超出预期。2. 数据集构建采集方案、情绪类别定义与标注规范2.1 采集方案设计可控场景与真实场景的组合采集猫情绪数据要解决的核心问题是“自然度”。如果刻意逗猫再去拍拍出来的情绪特征往往带有强迫性跟猫自发的情绪状态有偏差。我的方案是双轨并行一部分在家庭环境中用固定机位连续录制记录猫在进食、睡觉、听到陌生声音、见到其他动物等自然场景下的表现另一部分在可控条件下拍摄比如用逗猫棒引发玩耍和捕猎情绪用陌生人的靠近引发警惕和紧张情绪。固定机位录制的好处是能拿到连续的行为序列方便后续做帧级别的情绪标注坏处是大量帧里猫不在画面中心或处于背对状态这部分会被直接筛掉。可控场景的拍摄效率高但需要控制道具和人员的干扰避免情绪表达被“污染”。两种来源的数据大概按7:3混合真实场景为主可控场景为辅这样训练出来的模型才不容易在换环境后失效。采集设备方面没有什么特殊的一部手机加一个三脚架就能完成大部分工作。唯一要注意的是光线和分辨率。黄昏、逆光、强背光这类条件下猫瞳孔和面部特征很容易丢失建议尽量在自然光均匀的白天拍摄配合补光灯保证脸部细节清晰可辨。分辨率建议不低于1080p否则裁剪后的小目标区域几乎没有可用特征。2.2 情绪类别定义如何把模糊概念转化为可标注信号这是我整个项目里最花心思的部分。猫情绪不像人类表情那样有标准化编码如果直接让标注员凭直觉判断“这只猫开心”结果一定是灾难性的。我把5个类别拆解成了可观察的行为信号组合每个类别有明确的判定标准。以“警觉”和“紧张”为例两者很容易混淆但仔细观察是有本质差异的警觉时猫的耳朵竖立并向前转瞳孔中等放大尾巴低垂但尾尖轻摆身体呈蹲伏但肌肉并不僵硬——这是“我在探测环境”的状态紧张时耳朵向两侧压平呈“飞机耳”瞳孔明显放大尾巴紧贴身体甚至夹在两腿之间身体重心压低肌肉紧绷——这是“我准备防御”的状态。判定标准越具体标注的一致性就越高。5个类别的定义如下放松身体舒展侧躺或侧卧眼睛半闭或缓慢眨动耳朵自然朝前尾巴缓慢摆动或静止呼噜声如果录到音频。警觉蹲伏姿态耳朵竖立向前瞳孔中等放大视线聚焦于某个方向尾巴低垂但尾尖轻摆。紧张飞机耳瞳孔明显放大身体压低肌肉紧绷尾巴紧贴身体可能出现炸毛现象。攻击准备身体前压耳朵向后但未完全压平瞳孔收缩锁定目标时尾巴快速抽动可能伴随低吼或露牙。玩耍身体活泼扭动耳朵朝前瞳孔放大狩猎模式尾巴高翘或大幅摆动前爪扑击或抱住物体。2.3 标注规范与格式从图片分类到YOLO边界框确定了类别之后接下来的问题是标注形式。YOLO检测需要的是“边界框类别标签”跟单纯的图片分类完全不同。我在标注时采取的是“主体框关键特征框”的叠加策略主体框框住猫的整个身体区域用于定位如果图像中能清晰看到头部额外框出头部区域并标上独立标签。这样模型在推理时既能拿到“哪里有猫”又能拿到“猫头在哪里”情绪判断的依据更充分。标注工具我用的是LabelImg虽然是老牌工具但胜在稳定和导出格式直接支持YOLO的txt格式。每张图片标注完会自动生成一个同名txt文件内容格式为“类别序号 中心点x 中心点y 宽度 高度”所有坐标都归一化到0到1之间。有一个细节值得单独说边界框不要框得太“紧”。猫在运动时耳朵、尾巴的末端经常超出身体边界如果框贴得太紧这些关键特征在裁剪时会被切掉直接影响情绪判断。我的经验是每边留出3%到5%的余量具体做法是把矩形框的范围由“贴着身体边缘”放宽到“容纳最大肢体伸展范围”保证耳朵尖和尾巴尖都在框内。2.4 数据清洗与类别重平衡数据清洗是决定数据集质量上限的关键环节。我设了三道卡第一道卡去掉模糊和失焦图片第二道卡去掉猫占比过小小于画面5%或过大超过85%的图片第三道卡由人工二次审核情绪判定是否准确。经过这三道卡后3200张的核心数据集才最终确定。清洗完之后我还做了一步类别重平衡。5个类别的原始分布是不均匀的——“放松”和“玩耍”的素材很好拍“紧张”和“攻击准备”则很难收集到自然的画面。最后通过各种渠道凑齐之后放松类约750张警觉类约700张玩耍类约680张紧张类约560张攻击准备类约510张。针对紧张和攻击准备样本不足的问题我没有盲目追求物理样本数量而是在数据增强环节特别加强了这两类图片的随机旋转、缩放和亮度扰动让模型在每个epoch里看到的“虚拟样本”更丰富。3. YOLO深度学习模型训练实操流程3.1 环境准备与训练资源配置模型训练我用的是YOLOv8代码库来自Ultralytics训练环境是一台带单张RTX 3060的台式机显存12GB。这个配置训练YOLOv8s规模的基础模型完全够用不需要上多卡。操作系统是Ubuntu 22.04Python 3.10PyTorch 2.1.0CUDA 11.8。数据集目录结构必须严格按照YOLO格式来组织我放一个标准的目录树结构供参考cat_emotion_dataset/ ├── images/ │ ├── train/ # 训练集图片 │ ├── val/ # 验证集图片 │ └── test/ # 测试集图片 ├── labels/ │ ├── train/ # 训练集标签txt │ ├── val/ # 验证集标签txt │ └── test/ # 测试集标签txt ├── data.yaml # 数据集配置文件 └── cat_emotion.names # 类别名称文件data.yaml的内容很简单指定训练集、验证集的图片路径以及类别名称列表train: /path/to/cat_emotion_dataset/images/train val: /path/to/cat_emotion_dataset/images/val test: /path/to/cat_emotion_dataset/images/test nc: 5 names: [relaxed, alert, tense, attack_ready, playful]训练集和验证集的划分比例我用的是9:1。由于数据集总量只有3200张验证集只保留了320张另外从训练集中每类抽出一定比例作为测试集保证每个类别都有独立于验证集和训练集的评估样本。3.2 预训练权重与迁移学习的策略选择对于3200张这种规模的数据集从零开始训练几乎必死无疑。我的做法是下载YOLOv8s的COCO预训练权重作为初始参数在它的基础上做迁移学习。做迁移学习时冻结了backbone的前10层只训练后面的特征融合层和检测头。原因很好理解backbone前几层学到的是通用的边缘、纹理、颜色特征这些低级特征在天然图像中是通用的不需要花数据去重新学而跟猫情绪相关的是高层语义特征——耳朵角度、瞳孔状态这些组合模式这部分需要针对新数据充分训练。这里我再补充一个细节冻结层数的比例不是固定的而是跟你的任务跟原任务COCO的语义差距成反比。猫情绪虽然跟COCO的80类目标完全不同但还是目标检测任务所以冻结backbone前半部分是完全合理的。如果做的是跟原任务差异更大的任务比如从检测改为分割那就需要降低冻结比例。3.3 核心训练参数设置与调优训练参数是整个流程里最能体现经验差异的部分。我用的核心参数组合是输入尺寸640x640批次大小16初始学习率0.01动量0.937权重衰减0.0005训练轮数200轮早停机制开启。这个参数组合是在几次失败尝试后确定的。最初我把输入尺寸设成512结果小目标区域的损失一直降不下去后来换到640效果立竿见影。学习率方面0.01是一个相对激进的起点但配合Warmup和余弦退火策略可以在前期快速下降损失、后期精细收敛。批次大小16在12GB显存上刚好放得下跑满200轮大约需要2.5小时。还有一个值得注意的参数是close_mosaic。YOLOv8默认在训练最后10轮会关闭Mosaic增强改用它本身的验证逻辑来微调。这个设计我第一次跑的时候不知道导致训练曲线的最后阶段出现了明显的过拟合迹象。了解机制后我把关闭Mosaic的轮数从默认的10轮手动调整为15轮最后10轮的验证损失稳定了很多。3.4 训练过程与损失曲线解读训练启动后我详细记录了损失和指标的变化过程有几个典型的节点值得分享。前20轮是损失快速下降期box_loss从1.8左右降到了1.2cls_loss从3.0降到了1.4。第20轮到第60轮进入平台期loss下降速度放缓但mAP50仍在缓慢爬升。第60轮之后loss开始出现小幅波动这个阶段尤其需要注意过拟合苗头。验证集上的mAP50在训练到第110轮时达到了72%mAP50-95在58%左右。第110轮之后的提升非常缓慢平均每20轮只涨不到1个百分点。我果断启动了早停机制最终模型在第168轮时被保存为最佳权重——mAP50达到了75.3%mAP50-95为61.8%。训练过程的损失曲线说明了三个问题第一迁移学习策略是有效的模型在极少的轮次内就进入了收敛通道第二数据集的标注一致性足够高没有出现明显的类别间相互干扰第三3200张的核心数据量虽然不大但对于5类情绪识别这个细分任务来说已经足够支撑模型学习到关键特征这也验证了“数据质量重于数量”的原则。3.5 模型评估不只盯着mAP看mAP50是衡量检测精度的常用指标但要评估猫情绪识别系统的质量光看mAP肯定不够。我还重点关注了每个类别的Precision、Recall和F1-score这几个指标能揭示类别间的识别差异。训练结束后最终模型在测试集上的分类别表现为类别PrecisionRecallF1-score说明放松91.2%87.4%89.2%视觉特征舒展明确识别较稳定警觉78.6%74.1%76.3%与紧张、玩耍的边界有重叠紧张72.3%68.5%70.3%飞机耳炸毛在小图上易漏检攻击准备81.5%76.9%79.1%瞳孔收缩信号在侧拍时易丢失玩耍89.7%91.3%90.5%姿态动作幅度大检测置信度高这里有一个比较典型的案例可以拿出来分析。“攻击准备”类别的Precision排第二但Recall偏低说明大量真正的攻击准备状态被漏检了。回溯数据后发现漏检的图片大多是侧面的、距离较远的拍摄角度瞳孔收缩这个关键信号在画面中占比过小导致模型学不到。后来我针对这个情况补充了部分侧面角度样本并加强了画面边缘区域的增强处理最终把Recall从65%提到了77%代价是Precision小幅下降约3个百分点。这个取舍是值得的——在情绪检测这个场景中漏掉一次攻击预兆比误报一次更危险。4. 常见问题与排查技巧实录4.1 小目标信号丢失为什么检测不到耳朵和瞳孔变化猫情绪检测的一个老难题就是关键信号太小。耳朵的角度变化、瞳孔的缩放在高清画面上只占几十个像素经过640x640输入尺寸缩放后更是所剩无几。我排查后确认了三个方向的解决办法。第一是提升采集画质尽量保证猫头区域在原始图片中占据至少10%的像素面积这个在拍摄阶段就要控制好。第二是调整YOLOv8的检测头结构开启高分辨率特征图输出增加P2层这样小目标的特征不会因为下采样过多而消失。第三是在标注阶段叠加头部区域独立框让模型在分类分支上额外学习头部局部特征过滤掉背景干扰。4.2 类别混淆警觉、紧张、玩耍三个类别的边界处理训练完第一个版本之后混淆矩阵上最刺眼的是警觉、紧张和玩耍之间存在明显的误判。警觉和紧张本来就容易混这个可以理解但玩耍和警觉也被混淆这就暴露了数据定义的问题。我回看了大量预测错误的图片发现根源在于“玩耍”和“警觉”的低姿态动作高度相似——猫捕猎前的低伏姿态和警觉时的蹲伏姿态几乎一模一样区别只在瞳孔大小和尾巴状态。方案是调整标注规则双手向前扑击或抱住物体的场景一律归为玩耍仅仅是“盯着看但没有前置动作”的才归为警觉。这个规则变更后重新标注了约200张图片类别间的混淆率下降了一半以上。从模型角度解决类别混淆还有一种思路就是增加分类损失权重。但这个方法在语义边界本来就模糊的场景下效果有限。数据定义层面的修正才是最根本的解决方式。4.3 过拟合小数据集的典型症状与缓解策略3200张数据集训练200轮过拟合风险其实一直存在。我在第120轮左右就发现训练集的mAP已经接近90%但验证集的mAP只有74%这个差距就是典型的过拟合信号。应对策略我用了三招。第一是加大数据增强的强度特别是对紧张和攻击准备这两类样本加入了更强的随机旋转和色彩抖动。第二是增加Dropout比例在YOLOv8的检测头部分调整了dropout参数让模型不过度依赖特定像素组合。第三是最重要的一招——早停。我设置了patience为20轮也就是连续20轮验证集指标不提升就自动终止训练这是防止Auto-Overfit的保险阀门。还有一个实操细节值得分享关闭Mosaic增强的时机。Mosaic增强对提升模型泛化能力非常有效但如果关闭时间太晚模型可能在最后一小段时间内过拟合到增强后的分布。我的做法是让Mosaic关闭的时间点提前到训练进程的85%处给模型留下足够的纯真实分布微调时间效果比默认配置更稳。4.4 BN崩溃与训练震荡问题有一次我在调整批次大小的时候把batch size从16调到了24结果训练开始没多久就出现了loss剧烈震荡的现象。排查后发现这是YOLO训练里一个典型问题——BNBatch Normalization崩溃。BN层统计的是当前batch内的均值和方差。batch size骤然变大输入分布发生剧变BN层的滑动统计值还在用旧数据做归一化导致前几层的输出分布持续漂移。最直接的表现就是训练损失不断震荡甚至出现上升。解决办法是降低学习率并让模型在新批次大小下重新适应数据分布。我后来把batch size固定在16不再改动学习率仍然从0.01起步训练恢复正常。这里给大家一个实操建议训练过程中尽量固定batch size不要中途调整。如果要调整必须等当前阶段训练结束后重新开始不要在半路换batch size继续跑。4.5 模型输出结果的业务化解读模型训练完之后还有一个容易被忽视的问题YOLO输出的检测框和类别结果怎么转换成用户能理解的情绪信号我写了一个简单的后处理逻辑一个画面可能出现多个猫也可能出现多个检测框身体框和头框。业务解读规则是——如果同目标的头框和身体框情绪类别一致直接输出该情绪如果不一致优先采用头框的类别因为头部特征对情绪的指示性更强。置信度阈值设为0.5低于阈值的结果直接丢弃减少干扰。这个后处理逻辑在演示和实际部署中都表现出了不错的可解释性。用户在APP里看到的不再是“攻击准备 0.84”这样的机器语言而是“我家猫现在处于攻击准备状态靠近请小心”这样的自然语言提示。检测系统只有完成了这一步业务化封装才算真正落地。5. 扩展应用与后续迭代方向5.1 从静态检测到行为序列分析目前模型是单帧检测在实际观察中发现猫的情绪变化是一个动态过程。比如从放松到攻击准备中间通常会经过警觉到紧张再到防御或攻击的完整过渡。如果只做单帧识别相当于给整个动态过程拍一张照片信息是有损失的。我接下来的计划是引入时序建模——把连续30帧的检测结果组合成一个行为序列用轻量级的LSTM或时间卷积网络去预测下一步的情绪走势。这样系统不仅能识别“现在是什么状态”还能预警“接下来可能会进入什么状态”对自动喂食器的所有权判定或者智能猫窝的安抚触发都更有实用价值。5.2 多猫场景的情绪归属问题实际家庭中超过六成的用户是多猫家庭。多猫场景下情绪检测不仅要识别每种情绪还要把情绪跟具体个体关联起来。这套系统目前的做法是对每个检测框独立输出类别但当两只猫靠得很近时边界框会大面积重叠情绪归属就会出错。目前相对可行的解是重识别ReID流程——先检测出画面中的个体再对每个个体分别做情绪分类。我测试了YOLOv8加上轻量级ReID头的组合方案准确率比单纯检测高了不少但推理速度会有10%到15%的下降。在边缘设备上这个开销依然可以接受所以多猫场景的技术路线已经基本明确。5.3 数据集的版本化与开放计划这次建的3200张核心数据集我做了一些版本管理上的改进。整个标注过程用Git管理每一轮标注完毕的图片和标签都会打上tag后续任何模型训练都可以精确回溯到某一版数据。这是被我前几次项目经历逼出来的习惯——数据迭代了十几版之后只有版本管理才能让你知道模型效果提升到底来自数据还是来自模型。数据集本身的标注规范我写成了完整的文档包括各类别的详细判定标准、边界框的标注原则、数据清洗的具体规则。共享数据集对社区的价值不在于图片数量本身而在于一套可复用的标注方法论。写在最后的一点心得体会猫情绪检测这个项目做到现在让我感触最深的是目标检测模型本身的成熟度已经很高了真正拉开项目差距的是数据策略和业务理解。同样的YOLOv8网络有的人跑出来mAP不到50%有的人能到75%差别在数据怎么采集、怎么清洗、怎么定义类别、怎么处理边界样本。如果你正在做类似的项目——不管目标是猫、狗还是其他宠物甚至是非生命体检测我的建议是先花70%的精力把数据做到极致再花30%的精力去调模型。模型架构和训练代码有一千篇教程在讲但数据标注的细节规范往往才是你的护城河。最后还有一个使用技巧分享给大家训练好的模型不要急着部署先在实拍视频上跑一遍专门看那些模型“犹豫不决”的时刻——置信度在0.4到0.6之间的识别结果这些就是后续数据补充和标注规则修正的指南针。我目前版本的模型在实拍场景中的稳定表现相当大程度就来自这轮“犹豫区域”的定向优化。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑