硬件
这两天花一百多,捡垃圾淘了一块带刷脸支付的安卓13寸单屏机,因为带摄像头,又不带电池,准备拿来当智能家居中控屏。配置还行,rk3399,4G RAM。
屏幕上方有四个摄像头样子的传感器,本身估计是带传感器能识别人靠近的,但是刷机之后,驱动不了,唯一能驱动的是那个1080p的主摄像头。所以很自然的想到使用这一枚摄像头来做人来亮屏。
需求
作为智能家居中控屏,人来亮屏,人走息屏是必备功能。同时在捡垃圾群里看到有人收到的同款屏幕有严重烧屏痕迹,所以不做息屏的话,也担心烧屏。
具体需求是人出现在摄像头画面中,并不要马上亮屏,而是需要人足够靠近屏幕时,再亮屏。等人离开屏幕足够远后再息屏。
思路
安卓屏上的摄像头推RTSP流,工控机中的Frigate拉流,并对流做Person识别。在HomeAssistant中添加Frigate插件,并对该摄像头创建自动化,在person count从0变为任意值时,触发发送MQTT的topic。安卓屏上再安装MQTT Client APP,订阅该topic。安卓屏上再安装Tasker,与MQTT Client联动,在收到该topic时,触发点亮屏幕的动作。人走息屏同理,只是把触发条件,改为person count从任意值变为0,把Tasker中的触发动作变为熄灭屏幕。
注意点
- 安卓屏上摄像头推流,推荐使用IP Webcam这个APP。下载地址为 https://play.google.com/store/apps/details?id=com.pas.webcam ,免费版也够用了,可以将摄像头的流以RTSP推出去,而且同时具备RTSP server的功能,意味着不需要再在工控机中额外搭建一个simple-rtsp-server这样的服务,可以直接获取到RTSP地址,填入Frigate中。
- 安卓屏的摄像头推荐在上述APP中设置推流分辨率为最低(我配置的是320*240),作为TensorFlow Lite的person识别够用了,并且低分辨率能降低Frigate的CPU占用。但是如果你想将这个摄像头同时作为Frigate中的监控摄像头来用的话,倒是可以考虑将分辨率调高。
- 由于中控屏挂在客厅中,所以只要人在客厅活动,大概率就是能识别出person的,但是我们的目标是人足够靠近屏幕时才点亮屏幕。做法是在Frigate中,控制min_score和min_area,使得确定是人,并且人的方框面积足够大时,才触发事件。min_area可以在Frigate中的debug模式下,点击show options,再打开Bounding box,然后人走到你认为可以亮屏的位置,看画面中你身上的方框上显示的面积是多大,取一个整作为min_area就可以。注意当摄像头的分辨率变化的时候,这个值需要重新取。
- 需要提前在工控机中安装HomeAssistant。
- 需要提前在工控机中安装Frigate作为NVR,并在HomeAssistant中添加了Frigate插件。
- 需要提前在工控机中安装mosquitto作为MQTT broker,并在HomeAssistant中添加了MQTT插件。
- 安卓屏上的MQTT Client APP使用 https://play.google.com/store/apps/details?id=in.dc297.mqttclpro ,可以直接跟Tasker联动,生成Tasker中的配置。
- 对于像我这样,碰到安卓屏的ROM把锁屏息屏功能给删了,导致通过adb发送power按键事件、通过Tasker息屏锁屏,都无动于衷的情况,可以下载 https://play.google.com/store/apps/details?id=in.binarybox.blackscreen 这个APP,在Tasker触发亮屏的时候,将屏幕亮度改为255,并跳转到HomeAssistant面板,在Tasker触发息屏的时候,将屏幕亮度改为0,并跳转到该APP,模拟息屏效果。
实操环节
IP Webcam
分辨率取最低,降低Frigate的物体识别功耗。由于我的摄像头方向不对,所以同时设置了竖屏上下颠倒。
将音频禁用,接着开启服务器,就可以看到摄像头画面了。
接着电脑打开http://安卓的ip:8080,可以进入web控制台,能看到RTSP地址:
Frigate
Frigate中该摄像头的配置(在cameras节点下)如下,创建了一个名为panelcamera的摄像头,path设置为上述安卓摄像头的推流地址。重点是打开detect功能,设置只识别person,并配置min_score和min_area减少误操作。
panelcamera: ffmpeg: inputs: # 摄像头地址 - path: rtsp://192.168.66.223:8080/h264.sdp roles: - detect detect: # 开启检测 enabled: True width: 320 height: 240 fps: 10 # 不检测的区域,可降低计算负载,可以先不设置,在Frigate的debug模式下获取后再复制过来 # motion: # mask: # - 1198,134,1243,299,1552,289,1530,0,0,0,0,145 # - 482,1440,457,408,0,416,0,1440 # 区域,可降低计算负载,可以先不设置,在Frigate的debug模式下获取后再复制过来 # zones: # zone_0: # coordinates: 766,1440,1103,591,1241,442,1616,535,1697,193,1802,1440 objects: track: - person # 定制过滤器减少误报 filters: person: # 检测到的对象的边框的最小面积,宽度*高度(默认:0) min_area: 20000 # 检测到的对象的边框的最大面积,宽度*高度 (默认: 24000000) #max_area: 100000 # 启动跟踪的对象的最低分数 (默认: 0.5) min_score: 0.7
这样当人出现在摄像头画面中,置信度大于0.7且方框面积大于20000时,就会触发Frigate的event。
Frigate的HomeAssistant插件
我们还需要将此event传给HomeAssistant。需要在HomeAssistant中安装Frigate插件。需要通过HACS进行安装:https://docs.frigate.video/integrations/home-assistant
在HomeAssistant中Frigate插件中的摄像头设备中创建人来亮屏自动化:
alias: panel人来亮屏 description: "" trigger: - platform: state entity_id: - sensor.panelcamera_person_count from: "0" to: null condition: [] action: - service: mqtt.publish data: qos: 0 retain: false topic: mqtt_panel_screen_on mode: single
对应的UI操作是:
再创建人走灭屏自动化:
alias: panel人走灭屏 description: "" trigger: - platform: state entity_id: - sensor.panelcamera_person_count from: null to: "0" condition: [] action: - service: mqtt.publish data: qos: 0 retain: false topic: mqtt_panel_screen_off mode: single
对应的UI操作是:
含义是当panelcamera摄像头检测到的person的数量从0变为其他任意数时,通过MQTT发送mqtt_panel_screen_on这个topic,当panelcamera摄像头检测到的person的数量从任意数变为0时,通过MQTT发送mqtt_panel_screen_off这个topic。
MQTT Client
安卓屏上安装MQTT Client这个APP,先添加broker,连接的是工控机中启动的MQTT broker
再绑定亮屏和灭屏这两个MQTT Topic
Tasker
Tasker可以接收MQTT Client传递过来的事件,来触发安卓屏幕的开关。
先在“配置文件”tab页,点击右下角的加好,选择创建
选择事件-插件-MQTT Client-Message Arrived
点配置右边那根笔
此时会跳入MQTT Client的界面,
Broker默认选择之前创建的那个,Topic选择之前绑定的亮屏事件mqtt_panel_screen_on,varmessage和varmqtttopic随便输入,例如aaa,点左上角返回按钮回到Tasker,为该配置文件创建亮屏任务。由于我这块安卓屏无法锁屏和灭屏,所以我使用Black Screen APP来模拟灭屏。所以亮屏的时候将屏幕亮度调整为255,并跳转到浏览器显示HomeAssistant界面。
同理,在Tasker的配置文件中再创建一个灭屏用的配置文件,绑定MQTT Client中的灭屏事件mqtt_panel_screen_off,创建的灭屏任务,就是灭屏时将屏幕亮度调整为0,并跳转到Black Screen APP来模拟灭屏。
最终Tasker中的配置文件和任务如下: