自制开放智能低成本的监控摄像头

最近开始有一些安防监控方面的需求。看了一圈市场上现有的产品有三个顾虑,第一是它们的数据都要从互联网上走一圈,不是很放心;第二这种云存储/识别等服务需要月费;第三除了昂贵的专业产品,一般的民用摄像头很少有提供开放的接口,不方便进一步处理。所以决定自己从头做一个。因为手头正好有ESP32-Cam这个片子,感觉非常适合,所以花了一两天时间撸了一个版本,分享一下经验和踩到的坑。

最终的成品是这样的:

Final product

Micro-USB口供电,有图形化Web界面,可以在电脑和手机上访问串流,支持基于深度学习的物体检测和报警。同时和Alexa可以联动。比如可以跟Alexa说,"turn on camera one",手机就会收到一个推送,上面是这个相机的画面,点进去可以跳转到图形化界面里面去看实时场景。

Notification

下面我们主要从三个方面简单介绍一下这个系统搭建的技术细节。其中所有代码都开源到了github上。

v0: 基于ESP32-Cam的监控相机

首先介绍一下ESP68266, ESP32, ESP32-Cam这几个片子。 ESP8266是一个类似Arduino升级版的单片机(也许可以这么叫?)。 它的CPU,内存,存储空间都比Arduino强很多,带Wifi,而且开发板也很便宜,贸易战前只要不到2美元。 可以用Arduino IDE或者Visual Studio开发调试,用Arduino C或者MicroPython。 这里走个题,我觉得ESP8266其实也是树莓派的直接竞争对手。 你看网上那些树莓派的使用示例,很多是用GPIO口拿来读传感器的。 毕竟现在家里都有老电脑,如果只是拿来当个媒体服务器啊啥的,直接用老电脑一分钱都不花没有购买树莓派的动力。 但读传感器这种事情ESP8266也可以干,带Wifi也很方便,稳定性更好,买一个树莓派的钱能买20个,它不香吗?

扯远了。ESP32是ESP8266这个经典片子的升级版,主要是CPU升成双核,加了一些内置传感器(霍尔效应磁场传感器,电容触摸传感器),加了BLE蓝牙。 价格贵了1美元。 开发方法不变。 然后ESP32-Cam是在上面加了一个烂怂相机模块OV2460,最大分辨率1600x1200,1/4寸的底。 板子连相机大概4美元可以买到。

The camera module

其实这个板子就提供了监控相机的主要功能。 我们只要解决供电就好了。 找一个micro USB的breakout板子,把VCC用杜邦线接到5V,地线接地线就搞定了。 然后板子自己带了示例程序,会加入家里的无线网络,并启动一个Web服务器。 这样用浏览器访问这个网站就可以控制片子预览拍照和视频串流了。 打印一个壳子以后和充电宝连起来,在电脑端写一个程序每过10秒钟读取一次图像,进行神经网络处理和存储,一个简单的监控相机就做出来了。

Surveillance set up

v1: 改善速度和自动曝光

Photos

上面是这样的v0猴版相机的样子和拍出来的照片。 在坚持拍摄一个上午以后就被松鼠啃了。。 我还测试了一下续航时间。 72Wh的充电宝可以撑大约72小时(每10秒钟做一个Web请求拿照片,偶尔连上去看串流)。 这么看功率还是蛮大的,大约要1W。 还是需要一个有线的供电比较好,充电宝也许可以用来做临时的延时摄影等等。

除了功率以外,这个监控相机还有一个问题是速度。 即使分辨率这么低,串流的时候还是一卡一卡的。 这个原因主要是它的天线是在PCB板上的,增益很低。 ESP32-Cam其实也允许加装外置天线。 只要把一个地方的焊锡除掉让它断路,然后焊上另一个地方即可。 弄了一个外置天线以后,信号好了很多,视频串流也可以到6fps左右,够用了。

External antenna

这里还有一个比较有意思的项目是ESP32 NAT Router,可以把ESP32变成一个简单的路由器。 我用振旺的盒子拍深空有段时间了,什么都好,就是Wifi信号比较弱。 用ESP32和外置天线做了一个小路由以后,接收距离增加了,网速也变快了,感觉是个低成本改善信号的好方法。

这样我们就有了一个在白天堪用的监控相机。 但我发现它到夜里会严重欠曝,原因是它的自动曝光的算法非常保守。 这个也可以用一些简单的算法加以解决。 一种方法是根据当前照片的直方图手动指定下一张照片的相关参数。 这个在github里面的代码中有所实现。 另一种方法是拍几张照片,然后在电脑上进行叠加拉伸。 这个还在进一步的实验中。

v2: 和Alexa和Apple Watch的集成

v1虽然已经是一个比较实用的监控相机了,但用起来还是不够爽。 比如很多时候我只想瞄一眼画面,看看有没有松鼠,或者有没有人。 这种时候要掏出手机,打开浏览器,打开收藏夹,点进网页,单击拍照,就还是很麻烦。 有没有可能我们直接跟Alexa说:把这个相机的画面推送到我的Apple Watch上面呢? 这样就人性化了很多。

调研之后我发现了这个repo,可以把ESP32模拟成一个Wemo的智能插座。 这样Alexa就可以搜索到,并且可以通过语音控制了。 在集成这个库的时候,我遇到了两个问题,首先这个模拟需要有自己独立的消息泵来响应Alexa的各种请求。 这个消息泵和我们前面的Web服务器是冲突的。 如果直接把两个消息泵分别执行的话,一个都跑不起来。 好消息是,ESP32有一个双核处理器(主频80MHz 23333),所以我们可以用ESP的API把Alexa的库放到0号核上面执行,相机的库放到1号核上面执行。 这样就实现了两个消息泵独立并发的执行。 但光这样还是不够的,因为Wemo需要占用80端口,这和Web服务器又冲突了。 所以还需要更改Web服务器的C代码和HTML代码。 这里一个有意思的地方是,这个Web服务器里面的静态内容都是gzip以后,直接把二进制写死在C语言里面的。 想想的确有道理,这样一方面可以节约单片机上宝贵的存储空间,一方面可以直接在http头里面指定,我们输出的是gzip内容,从而提升响应速度。 所以我们还需要解压,拿到HTML,更改,压缩,然后写程序生成C代码放进去。 相关的代码也放在github上了。

第二个问题是,这个Wemo智能插座是有开和关两种状态的。 比如我说Alexa打开XX相机,如果它本身就处于开的状态的话,就不会调用相关函数,不会做任何事情。 难道我还要硬记某个开关原来是开还是关吗? 那也太麻烦了。 所以这里我又深入模拟Wemo开关的库,更改了相关代码,加入了一个相关接口来直接操纵开关的内部状态。 这样我们就可以实现打开开关以后自动关上这个功能,所以以后只要说Alexa打开XX相机就行了。 易用性得到了很大的提升。

解决了语音控制的问题,第二步就是和Apple Watch集成起来了。 这里我用的是IFTTT这个服务。 它也是个老牌的智能家居的服务了,提供WebHook功能,也就是如果某个URL被访问的话,就可以做一些动作,比如在手机上弹个提醒之类。 这个提醒是可以有一些更多的数据的,比如提供一个缩略图,可以点进一个链接等等。 所以我们就是在这个Wemo插座打开的回调函数里面向IFTTT发送一个请求就好,然后手机和Apple Watch就会弹出通知和缩略图了。

解决了这些问题以后,我一下从aliexpress上面买了10个ESP32-Cam,下面就是真的部署在房子周围了。 现在主要的工作是,测试供电,做一个类似保安监控室那样的集成网页,提升神经网络检测的吞吐量,还有进一步优化夜间的画质。 通过这样的方法,踩了很多坑,终于做了一个不经过互联网,可以拿到视频帧进行进一步处理,也很便宜的系统了。 希望可以做成一个实用的家防系统吧。

Comments