背景
22年养了一只很可爱的小狗狗,我其实就一个问题:为啥这么可爱的狗狗会拉屎撒尿呀?
自从崽崽来了我们家之后,最让我们头疼的就是它乱拉、乱尿的问题了,以前会在家里到处乱来,最近一段时间好了很多,已经只会在厕所拉/尿了。
虽然能都在厕所拉/尿,但是还是很耗费我们的精力。
我们家厕所是这样的,我们把它的"狗厕所"摆在了厕所里面,但是它老喜欢在厕所门口拉/尿,最恶心的是,老喜欢尿在这个透明的白箱子旁边。怎么训练才能让它在自己的厕所上拉/尿呢?
查阅了各种资料后,得出的结论就是,它尿/拉对了得给它奖励,然后它尿/拉错了,一定要当场抓获!并且训一顿,当场抓获特别重要!但是,我们家的崽崽可太会了,它每次都能趁我们不注意,悄悄地"溜进"厕所,"迅速"地尿/便完,完美撤退,我们根本就发现不了。这让我们想当场奖励,或当场训斥都没法做到。
于是,忍无可忍的我只能上高科技了。
场景分析+技术实现
画面捕捉
要想当场抓获崽崽干坏事,就必须及时发现它到厕所去了, 那就得有一个摄像头一直监控着,并且还能用程序捕获摄像头的画面,
这里使用了TP-LINK的摄像头,TP-LINK的摄像头默认会在本地起一个rtsp的串流服务器,只需要连上这个地址就能实时获取到摄像头捕捉的画面。
目标检测
捕捉了画面之后,还需要用一个模型去做目标检测,这样才能识别到崽崽。
这里直接使用了YOLOv5,这个库使用COCO数据集做训练,提供了好几个不同规模的训练好的模型,能直接使用。
提醒
家里最容易能提醒到我们的就是小爱音箱了,所以找个办法能主动让小爱说话就行了。
经过一番调研,选择了HomeAssistant来做这个事,使用HomeAssistant装上Xiaomi MIoT插件之后,就可以选择绑定账号,并且绑定设备。然后HomeAssistant就能提供API供我们调用了。
整体架构图
目标检测模型相关的细节
本来到此应该就圆满结束了的,但是关于模型,还有一些要展开说说的内容。
模型的通用性
一开始我以为咱家的崽崽还算是一条比较"狗"的狗,用训练好的模型直接去检测就ok了,谁能想到,由于视角的问题(摄像头是从上往下看的),崽崽根本就没被识别,看图也能发现,崽崽确实不太像狗,像是棉花:
所以我只能自己去训练一个模型了,
这里使用了roboflow进行数据的标注,标注起来还挺简单的,并且最终能很容易地导出YOLOv5所需的数据格式。
模型的训练
这里还发生了点小插曲,一开始按照官方教程,就训练了3个epoch,然后发现模型质量差的不行,mAP也很低,压根都识别不出来崽崽。
所以就训练了10个epoch,质量明显上来了:
模型的优化
虽然训练了10个epoch后,能完美地识别崽崽了,但是误识别太多了,可能崽崽就是太像棉花了,所以模型只识别了其毛茸茸的性质,以至于我的睡衣也被当成了崽崽:
所以得把这些图片也喂给模型,并且这些图片不做崽崽的标注,这样,模型如果不小心将我的睡衣识别成了崽崽,就会收到惩罚了。
顺便我还标注了一下自己,识别成人,之后可以扩展使用。
至此,模型的效果终于不错了,误识别也比较少发生了。
实用性提升
最后就是添加一些实用性的功能了
模型serving性能差
由于我有一台服务器,一台普通电脑(带GPU),服务器是7x24开机的,而电脑不是,所以模型就得放在服务器上,用cpu来做serving,这个时候,serving的性能就不是很够了,一个图片需要100ms才能识别完,相当于10FPS。而视频的输入是30FPS的,所以肯定没法直接使用。
这里我并没有针对模型的性能进行优化,而且取了个巧,先通过进行两帧图片的对比,识别出变化,在有变化产生后再进行模型的确认,所以模型serving的压力只有在崽崽或者我们进厕所的时候才会产生,而一旦厕所没有任何动静,模型自己慢慢就处理完了。
这里用的算法是网上找的代码片段,也不确定具体是啥算法,反正效果不错,知道的同学可以补充说明一下:
- 计算帧间的距离(Pythagorean distance)
- 在计算出来的距离矩阵上应用高斯模糊
- 使用一定的阈值进行过滤
- 计算标准差
- 标准差大于一定的阈值,认为检测到了运动,输出信息
记录下模型的结果
由于模型还是会有一些误识别,所以需要记录下来识别的结果,后续补充数据集,继续提升模型的性能。我这里会记录下识别结果图和识别前的图,识别图可以快速地看结果对错,原始图可以用来重新标记。
控制通知的时机
- 一旦发现崽崽后,不需要一直报告,可以隔一段时间再报告(意味着模型也可以隔一段时间再识别,顺便能节约一下计算资源),这里我设置了20秒。
- 晚上不能吵我们睡觉,所以有静默时间,这里设置了23点开始到7点结束。
效果
现在只要崽崽出现在厕所,都能百分百提醒,偶尔人进去的时候会误提醒,基本满足了当时的需求。
相应地,崽崽已经很久(哈哈哈,才1天)没有尿在厕所门口了,它现在能作案的时间只有晚上我们睡觉的时候,这个就没办法了。
下一步
说一下接下来可以扩展的点:
- 通过ONNX来提升模型serving的性能,之前测试过,在cpu做serving的前提下,ONNX可以将serving的性能提升好几倍,当然那是1年前的做的实验了,不确定现在还适应不,是一个值得尝试的方向。
- 加入狗厕所识别的功能,这样可以捕获狗厕所的信息和崽崽的信息进行匹配,如果是在狗厕所上,那么无需触动警报
- 可以搞个姿势识别的模型,发现崽崽尿/便对了,便对了就能识别出来,这样就能给予奖励了
- 再搞一个自动投喂的机器,可以远程控制投喂,这样一旦识别出来尿/便对了,就直接投喂好吃的零食,这样人就可以完全不用管了。