ARTICLE DETAIL

资讯详情

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

基于YOLO的猫情绪检测数据集构建与训练实践

基于YOLO的猫情绪检测数据集构建与训练实践 去年给一家做智能宠物用品的团队做技术顾问需求听上去很简单在智能猫窝里加一个摄像头识别猫当前是放松还是紧张。我原本以为调个YOLO模型就能交差结果周末之后就被现实打脸——市面上的宠物数据集要么是品种分类的老古董要么标注的是“猫在爬树”这种与情绪无关的动作能找到的猫情绪数据大多是论文里的几百张小图标注格式和YOLO完全不搭。没办法只能自己从零攒数据3200张图片、7类常见情绪/行为状态、全部按YOLO格式标注并把训练、评估、部署的一整条链路跑了一遍。这篇文章就把数据集的构建思路、标签规范、训练结果、踩坑过程全部摊开讲给准备做宠物AI或行为识别的朋友一个可以直接参考的样本。1. 猫情绪检测为什么难3200张图能支撑什么1.1 猫没有“表情包”情绪藏在多个信号里做猫情绪检测和做人体姿态估计完全是两个思路。人脸有明确的表情肌肉愤怒和开心可以靠眉眼口的形变判断猫的面部肌肉很少一张猫脸在放松和轻微警觉时的差异非常小真正传递信号的反而是耳朵朝向、瞳孔大小、尾巴位置、身体重心和动作速度。猫的情绪更像一套多模态信号系统飞机耳可能是恐惧也可能是愤怒的开始瞳孔放大可能是捕猎兴奋也可能是受到惊吓呼噜声在放松和疼痛时都会出现。也就是说单帧图像里往往只能看到“信号片段”要判断准确的情绪状态必须把耳朵、尾巴、姿态、上下文场景组合起来看这正是它和普通目标检测的本质区别。这也是为什么很多第一次做猫情绪识别的团队会掉进坑里把“猫脸检测”当成“猫情绪检测”来做只在头部区域找特征。实际上猫在恐惧时会压低身体、夹紧尾巴这些信息必须在全身框或半身框里才能被模型学到。所以这个数据集从一开始就定位为“行为状态检测”用整只猫或主体躯干作为检测目标而不是只找脸。1.2 3200张能训练出什么效果的模型3200张图在CV领域不算多但对猫情绪检测这个细分方向来说这是一个非常务实的中等规模。参考我实际训练的经验在类别相对均衡、标注一致性到位的情况下用它从头微调YOLOv8n或YOLOv5smAP0.5:0.95大概能到0.65到0.75之间简单类别relaxed、playful的单独AP可以到0.85以上复杂易混类别fear和anger通常只有0.6左右。这个精度水平意味着什么它足够支持一个MVP产品智能猫窝判断猫咪是否进入放松状态、自动喂食器判断猫是否处于紧张回避状态、宠物摄像头输出每日行为倾向报表。但如果要做严肃的临床辅助判断或高精度行为研究3200张是远远不够的需要按10倍量级扩数据并且引入多目视角和连续视频标注。1.3 和公开数据集的横向对比我找过的公开数据集要么是牛津Pet数据集这类品种分类任务要么是像COCO这种通用物体检测宠物只是几百个类中的一个。COCO里虽然有猫这个类别但只标“猫”这个对象完全没有情绪维度而且很多训练图里的猫是远距离小目标情绪相关的肢体细节完全丢失。另有一些行为学论文用的小型私有数据集图少且是旧版VOC格式转换到YOLO反而费劲。这个数据集和它们最大的不同是它把“情绪/行为状态”直接作为类别标签放进YOLO格式里使用方拿到后不需要做任何格式转换目录一摆、配置文件一写就能直接开始训练。关于标签体系的细节下一节详细说。2. 标签体系与YOLO标注规范先定行为学标准再开标注工具2.1 七类状态的定义与判定依据为了不让标注员凭感觉乱标我在标注前写了一份行为学判定手册把每个类别对应的耳朵、瞳孔、尾巴、身体姿态特征做了量化描述。最终确定下来的7个类别如下类别ID类别名核心判定依据0relaxed耳朵自然竖立或略后瞳孔细长尾巴自然下垂/松弛弯曲身体舒展或缓慢眨眼1alert耳朵竖直朝前瞳孔中等放大身体前倾尾巴竖直或末端勾起2fear飞机耳明显瞳孔放大尾巴夹紧或蓬松膨胀身体低伏/后缩3anger飞机耳加瞳孔收缩尾巴快速甩动或炸毛露出牙齿身体僵直/弓背4playful瞳孔较大耳朵正常/稍后臀部抬高、前身压低尾巴高翘或左右甩动5hunting瞳孔微收缩身体贴地匍匐尾巴低位缓慢摆动眼神锁定前方6distress母鸡蹲/蜷缩隐藏耳朵压低眼睛眯起尾巴紧贴身体可能伴随持续呼噜这里要特别强调一句这个是单帧图像的简化判定标准。真实猫行为学中情绪判断需要观察时间窗口和行为序列但目标检测数据集能提供的就是“某一帧里最明显的状态”所以我在手册里约定的原则是如果一帧图像里有多个状态特征冲突按“最具有判别力的那个信号”来定标。例如飞机耳加瞳孔放大但尾巴夹紧的优先标注为fear而不是anger。2.2 为什么框选主体而不是头部最初的标注尝试阶段我让标注员只框猫头理由是情绪看脸。但很快就暴露了问题耳朵和瞳孔确实在头部但尾巴和身体姿态在头部框完全看不见加上很多图片里猫在运动头部常被虚化而身体相对清晰。后来改成统一框选“猫主体”——包括躯干和头部尾巴末端如果超出画面就只框到画面边缘。这个选择还有另一个实际好处YOLO是检测模型框住主体可以让模型同时学习“猫在画面的哪个位置”和“这个位置上的猫处于什么状态”。如果只框头模型对尾巴和身体姿态的判别能力会完全丢失如果框全身边界框会频繁因为尾巴摆动而抖动。框主体是一个折中方案经过实测对模型收敛速度和定位准确度都是最优解。2.3 YOLO格式与坐标归一化的换算细节数据集里的每张图片对应一个同名txt文件每一行格式是类别ID x_center y_center width height这里的x_center、y_center、width、height全部是归一化坐标。例如一张分辨率为1280x720的图左上角起点是(0,0)右下角是(1,1)。如果某个目标的边界框在原图中是从像素(360, 180)开始宽500、高420那么归一化换算方式是x_center (360 500/2) / 1280 0.4766 y_center (180 420/2) / 720 0.5417 width 500 / 1280 0.3906 height 420 / 720 0.5833实际标注时不需要手工算这些。用X-AnyLabeling或LabelImg导出YOLO格式工具会自动完成换算。但作为项目负责人至少要能看懂txt里的数字代表什么否则训练结果异常时容易抓瞎。我项目里遇到过一位同学把所有类别的ID从1开始编结果和data.yaml里的0编号对不上模型一直报错“class index out of range”排查半天才发现是标签起始编号问题。2.4 几个容易让标注质量崩盘的细节第一个是遮挡规则。多猫场景里后面那只猫被挡住超过30%就跳过不标单猫但被家具挡了一半如果关键部位耳朵或尾巴还能看清就标否则跳过。第二个是极远小目标。猫在画面里占比小于5%时不标。因为这种小目标对情绪识别没有任何意义反而会引入大量低质量标签干扰模型学习。第三个是同一张图里的多只猫。我建议分开两个独立bbox标注即使它们状态完全相同也不要合并成一个框。合并框会让模型学到“两只要在一起才是某种情绪”的错误相关性。3. 数据采集、清洗与双重标注审核3.1 三种采集渠道与比例分配数据采集我分了三个渠道自己实拍、视频抽帧、开放许可图片筛选。实拍占了最大头大概1600张覆盖了不同光线环境白天窗边、夜晚暖光、室内昏暗、不同品种英短、美短、狸花、橘猫、布偶、无毛猫等这是控制基础质量的关键。视频抽帧约1200张从十几段日常视频中按场景变化抽帧用这种方式补充连续行为的中段状态比如从警戒到炸毛的过渡帧。开放许可图片大概补充了400张主要是上文说的那两个公开数据集中许可明确、内容干净的部分图片。很多团队因为求量会直接从网上爬图。我的建议是网络图版权风险不可控且很多是经过滤镜和美化的猫图真实监控场景完全用不上。如果确实需要补量优先选择明确标注了可商用License的图库或在合作群里让朋友提供自家猫咪的实拍。3.2 视频抽帧去重的关键操作视频抽帧最容易出的问题是“看似3200张实际有效信息只有400帧的量”。因为视频相邻帧高度相似直接按固定间隔抽帧会产生大量近重复图片。我的做法是先按每10帧抽一次得到原始候选集然后用感知哈希算法pHash计算相似度把相似度超过0.85的帧归为一簇每簇只保留1到2张且优先保留姿态差异大的帧。这个去重步骤非常关键。如果做得不彻底模型会在验证集上出现虚假高分看起来mAP很高等模型部署到真实环境下立刻原形毕露因为它的训练集和验证集里的“不同图片”其实是同一只猫几乎相同的两帧。3.3 清洗标准什么图片必须扔筛选一共过滤掉约700多张原始素材主要有四类严重运动模糊的模糊到耳朵轮廓都看不清、猫占比过小的面积小于画面的5%、过暗或过曝的、以及滤镜或贴纸遮挡了关键部位的。这里我想多说一句运动模糊不是绝对要扔掉如果只有头部略有模糊但尾巴和身体姿态清晰我会保留并标注因为真实监控场景的运动模糊比例不低训练阶段见得到这类样本部署时才不容易垮。3.4 标注工具选择和标注手册先行工具上我推荐X-AnyLabeling它可以加载SAM模型做预标注标注员只需要修正边界和确认类别速度比我早几年用的LabelImg快很多。LabelImg不是不能用而是它对大图和批量操作的流畅度不高3200张图全靠手动框会标到怀疑人生。但工具只是辅助标注规范才是生命线。我的流程是先让两位标注员各标同一批20张图我拿这40份结果和手册比对把分歧点当场讨论清楚正式标注阶段采用背对背双人标注同一批图两个人都标约25%的比例做交叉验收对每张验收图计算检测框IoUIoU低于0.5或者类别不一致的一律退回重新标这套流程下来标注整体耗时大约7个工作日换来的是最终数据集里极低的比例错误标签。有人可能觉得双人标注太贵、太慢但猫情绪检测本来就是一个模糊标签任务如果标注标准都不统一后面模型训练和调优的所有时间都会被白白浪费。3.5 类别不平衡的处理数据比增强更优先3200张原始图里的类别分布并不均匀relaxed最多、hunting和distress最少。这也是可以预见的日常环境里猫大部分时间确实在放松。我在归并时先把hunting和distress的原始素材优先补齐到和中间类别接近的数量然后才用在线增强去扩充。顺序很重要数据增强只能增加样本的表观多样性没法凭空创造真实的“尾巴夹紧”和“身体低伏”组合。训练阶段我保留了YOLO自带的mosaic增强把4张图拼起来对小目标检测很有帮助。但有一个增强必须关掉随机垂直翻转。猫不常倒挂垂直翻转会产生大量违反猫行为常识的训练样本模型容易学到错误姿态。YOLOv5和v8如果想关闭需要调整flipud的参数或在增强配置里确认不启用。4. 用YOLO训练猫情绪检测模型的完整实操4.1 数据集目录与训练文本的准备拿到这份数据集后第一步不是直接丢进训练脚本而是把目录结构整理成YOLO约定俗成的样子。我的推荐结构是这样的cat-emotion-dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── data.yaml ├── train.txt ├── val.txt └── test.txtimages和labels按train/val/test划分后每一张图片的同名txt标注文件必须放在labels下对应的同一级目录。不要图省事把所有图片放一个文件夹再自己写脚本按列表找标签那会在后续迭代时埋很多坑。train.txt、val.txt、test.txt这三个文本文件里写的是对应图片的路径YOLOv5和YOLOv8都支持直接在yaml里指定images目录不一定需要txt文本。但老一点的代码分支还是习惯读txt保留一份没有坏处。路径建议统一写绝对路径或相对路径绝对路径换机器后要批量替换相对路径要保证运行目录正确两选一都行关键是全项目统一。4.2 编辑yaml配置文件训练前会用到一个数据配置文件内容如下path: /data/cat-emotion-dataset train: images/train val: images/val test: images/test nc: 7 names: 0: relaxed 1: alert 2: fear 3: anger 4: playful 5: hunting 6: distress值得注意的坑有两个一是类别ID必须从0开始连续编号中间不能跳号二是names列表的顺序必须和标注txt里“行首那个数字”的含义完全对应。我遇到过有人把names写成从1开始看起来没毛病但训练时模型预测的类别总是整体偏移一位所有指标一塌糊涂。4.3 训练命令与关键参数选择以YOLOv8n为例训练命令是yolo train modelyolov8n.pt datacat-emotion/data.yaml epochs120 imgsz640 batch16 device0 projectcat-emotion nameexp1那这里的几个参数怎么定先说预训练权重虽然COCO数据集和猫情绪完全不同但COCO上预训练模型学到的边缘、纹理、轮廓特征对任何检测任务都有迁移价值用yolov8n.pt做起点比从空白权重训练能少用大概60%的epoch达到同等精度这是通用物体特征的功劳。再说imgsz640是一个性价比很高的默认值如果猫在画面里很小可以上调到1024但训练时长和显存占用都显著上升且对小情绪细节的提升不一定值得那个成本。最后说batch它受显存限制遇到爆显存先别急着急着降低分辨率优先调小batch或开启梯度累积保分辨率比保batch size更重要。额外建议训练时把mosaic等在线增强打开。3200张的数据规模其实不大没有强增强的话模型很快就过拟合了。4.4 评估指标怎么读常见的坑有哪些训练完看结果时不要只盯着mAP0.5:0.95。我自己的习惯是优先看三张图混淆矩阵、类别单独的AP曲线、特征图可视化结果。混淆矩阵能直接暴露易混类别比如fear和anger这对。我第一版训练出来的mAP0.5:0.95是0.66看起来好像还行但打开混淆矩阵发现fear和anger互相错判得离谱有很大比例的anger被标成了fear。后来复盘原因标注手册里“炸毛露齿”才能定anger但在很多图里猫已经炸毛但嘴没张按手册会被标成fear导致数据本身的边界不够干净。我重新把这两类样本挑出来把“炸毛且尾巴剧烈甩动”的情况也归为anger重新标注后再训练两个类的AP各自上涨了约10个点。另外一个小坑是置信度阈值。很多人训练完直接拿默认confidence0.25去跑推理结果看到满屏“狗皮膏药”一样的预测框。这个数据集的类别本身有模糊性建议推理时把置信度阈值调到0.35到0.45之间以实测效果为准。阈值的具体数字没有标准答案在部署时拿一段真实视频跑一遍看漏报率和误报率之间的平衡点再定。5. 从单帧检测到情绪状态判定时序聚合与追踪5.1 单帧检测结果不能直接当成情绪结论这是我做猫情绪检测项目时体会最深的一点。YOLO在单帧上输出一个“anger”的概率高不代表猫此刻一定在愤怒。猫打哈欠时嘴巴张开、耳朵后压非常容易被误判成恐惧或愤怒猫在玩耍时瞳孔放大、身体翻滚单帧也可能和恐惧状态高度相似。所以我在实际部署时永远不会直接拿某一帧的分类结果下结论而是用滑动窗口做时序聚合。具体做法是以最后一秒为一个状态评估窗口对窗口内的帧检测结果按类别投票投票权重是每帧的置信度窗口里连续有超过60%的帧都投给同类才输出一次状态变更。这样打哈欠的孤立误报会被平滑掉而真正的愤怒状态因为持续时间通常会超过一秒能被稳定捕捉到。5.2 多猫场景要用追踪关联单只猫智能猫窝和家庭摄像头遇到的多猫场景远比单猫复杂。如果画面里有两只猫A猫在玩、B猫在哈气直接把所有检测框拉进同一个时序投票池状态会被冲淡。我的做法是引入追踪器按检测框的IoU给每一帧的猫分配持续ID然后按ID分别做状态聚合。ByteTrack在这个场景下就够用计算量也不大CPU上也能跑得动。还有一个容易被忽略的细节猫离开画面再回来追踪ID会变。这时候不要强行把前后两段拼接成同一条状态序列重新开一条即可否则会在一只猫“离开又回来”时出现状态跳变很难解释。5.3 边缘设备上的轻量化部署参数参考在Jetson Nano或树莓派4B这类边缘设备上部署时我实测的推荐是yolov8n加TensorRT加速imgsz保持640单帧推理大概在20到30毫秒级别如果想更快可以用352或416输入但mAP会下降特别是小目标类别hunting会掉得很明显。树莓派等纯CPU设备如果跑不动可以先尝试把模型转成ONNX再走量化用半精度或INT8。但量化后务必重新用数十段真实场景视频验证精度不要只看公开评测指标。我在CPU设备上遇到过量化后hunting类的AP从0.7掉到0.4的情况后来发现是量化校准集里刚好缺少低光猎杀姿态的样本再补一段校准数据才恢复。5.4 最终产品输出建议说是“行为倾向”而不是“情绪结论”基于这套模型做产品时我强烈建议对外文案和交互逻辑都使用“行为倾向”的表述比如“猫目前表现为警惕倾向”而不是断言“猫现在很愤怒”。原因很现实单帧和短时序的自动识别天然存在误差一旦产品给到用户“猫咪很不开心”这样斩钉截铁的结论后续解释成本极高。行为倾向的表达既诚实又给系统留了误差空间。6. 后续扩展方向从数据集到完整宠物AI产品6.1 应用场景拆解并不只有智能摄像头猫情绪检测的实际产品价值比很多人第一反应要大。智能猫窝可以通过放松状态的持续时长判断猫是否适应新环境自动调整温控减少应激智能喂食器能在识别到anger或fear时暂停出粮避免猫咪护食引发攻击宠物智能摄像头可以每天输出“活跃/放松/警惕”时长曲线给长期出差的主人一个观察窗口。此外在宠物医院场景里情绪检测视频可以用作辅助记录帮医生了解陌生环境下猫咪的应激水平这比主人回忆“它在家很乖”可靠得多。6.2 进一步提升精度的两条路线如果你拿这份数据集做训练后效果不够优先走两条路而不是直接换结构怪异的backbone。第一条是补数据把真实部署场景里录到的误判样本回收按这套标注规范补标后加入训练集每轮迭代补个200到500张新场景数据效果往往比把模型从n换成s还要明显。第二条是多模态给图像模型加上麦克风音频通道呼噜声和嘶吼声是最强的情绪判别线索之一结合音频事件标签可以显著降低fear和anger的混淆率。6.3 跨品种泛化的注意事项数据集里英短和橘猫占比高导致布偶这种面部结构和毛色差异极大的品种在初期验证中掉点明显。解决思路是验证时专门准备一个跨品种测试集把每种品种单独跑一次mAP而不是混在测试集里让平均值掩盖问题。后续扩充数据时也优先找无毛猫、长毛猫、异瞳白猫这类表观差异大的品种它们对模型的域泛化能力贡献极大。6.4 合规与伦理边界做宠物AI产品的同行要注意情绪识别属于带有主观推断的系统不是医疗诊断设备。如果产品向用户输出“猫可能处于痛苦状态”之类的分析必须有免责声明和人工介入的渠道避免用户仅凭AI结论延误就医。另外采集猫咪视频图像并进行标注建议获得宠物主人的明确同意涉及第三方图库素材时按授权范围使用这些底线问题不能碰。最后补一个项目里反复验证过的经验决定数据集价值上限的不是张数是标注一致性。这3200张图如果内部标注标准不统一训练时模型学到的只是标注员之间的摇摆反过来标准一致的小数据比混乱的大数据更容易训练出稳定的模型。所以不管你是自己要做一个新数据集还是拿这份现成数据去训练第一步永远是抽50张图做一致性检查让团队所有人的判断标准和判定手册对齐。这一步能帮你省掉后面一个月的调参时间。
返回列表