TensorFlow on Edge,或-使用覆盆子PI构建“智能”安全摄像头

2020-06-22 03:07:29

我的户外相机被光线、风、汽车或任何人以外的东西触发的时间太长了,这简直是疯了。过度谨慎的安全摄像头可能是一个特点,但这也是一个令人恼火的特点。

我需要一个解决这个问题的办法,而不是完全走得太远。一些简单、优雅而又有效的东西。

各位,见见我亲切地称之为“稻草人凸轮”的人。这是一款由树莓PI驱动的相机,它可以通过TensorFlow对象检测功能探测到人们,当他们走进我的门廊时,它会用异常响亮和刺耳的音乐(或警告声)向他们问候。

通过使用TensorFlow、Raspberry PI、相机、扬声器和Wifi进行实时目标检测,这确保了夜晚的宁静。有点。

更严肃地说,使用实时视频流和机器学习进行对象检测是一个实际的真实用例。虽然大多数用例都可以说是令人难以置信的令人毛骨悚然,但我确实发现在私人安全摄像头上检测物体或人有一定的价值。

如果家里的安全摄像头网络能够检测到真实的、潜在的威胁-人类和松鼠-并做出相应的反应(例如,通过发送警报),这将极大地提高这些设备的有用性,这些设备主要依赖于运动检测或连续视频记录-要么非常容易出错,要么最多只能是被动的(向你展示事后发生的事情)。

然而,大多数消费级视频监控系统都很糟糕,简单明了。它们要么需要昂贵的硬接线,要么依赖于每10分钟设置一组的破旧红外线和运动检测,因为汽车会经过房子,依赖于第三方公司的优雅和软件更新,通常是以订阅模式提供的,通常无法通过API访问。

我的未具名的户外相机设置通常是由Old Glory在风中挥舞来触发的,而不是由一个人来触发。

我们将使用带有摄像头模块的Raspberry PI 4来检测视频。它可以连续运行,不需要依靠运动传感器来启动。

为了检测对象,我们将使用Google的张量流对象检测API。这个库使我们几乎可以开箱即用地使用对象检测(稍后将详细介绍),而不需要手动训练和调优模型,也不需要云部署。

现在,给您一个问题:我的旧RasPI运行的是32位版本的Raspbian。TensorFlow不适用于32位操作系统(当然,可能还有其他选择)。此外,虽然新的Raspberry是一台功能强大的小机器,但它远不能与现代电脑相提并论--特别是在3版和更早的版本上。

为了缓解这一问题,我们将在PI上通过网络将视频流式传输到功能更强大的机器-家庭服务器、NAS、计算机、旧笔记本电脑-并在那里处理信息。

这是一个叫做边缘计算的概念。使用此概念,我们基本上使用功能较弱的较小机器来实现低延迟通信,方法是在物理上靠近边缘节点的机器上执行繁重任务-在本例中,运行TensorFlow对象检测。通过这样做,我们避免了通过互联网往返,以及必须在AWS或GCP上支付云计算费用。

为了实现这一点,我们将使用VidGear,特别是它的NETGEAR API,这是一个使用ZeroMQ通过网络流式传输视频的API。只需提防需要您使用开发分支的bug。

一旦我们检测到流中有人,我们就可以使用ZeroMQ向Raspberry发送信号,播放一些非常响亮、令人讨厌的音频来吓跑人们。

(正如Reddit上的一些人所呼吁的那样-除了这一点,还有其他选择,即esp32cam和TFLite)

虽然可以说不是最有趣的部分,但首先,我们需要一个开发环境。为此,我在Linux上使用带有Python3.7的Jupyter笔记本。

附注:由于我使用的是TensorFlow2.0beta,我不得不在~/.local/lib/python3.7/site-packages/object_detection/utils/label_map_util.py.中将tf.gfile的接口破译为tf.io.gfile。

克隆笔记本,按照说明设置虚拟环境,并安装所有依赖项。

一旦完成,我们可能希望使用测试数据循环本地视频,而不必真正连接实时摄像机。

我们在这里真正需要做的就是更改“While True”循环以绑定到OpenCV会话。VideoCapture可以方便地接受整数(对于网络摄像头)或视频文件的路径。

(为了隐私,图像的某些部分被手动模糊-此外,这些部分是邀请访客😊)。

一旦运行笔记本,您就应该看到检测模型的覆盖。太棒了,这个模型很管用,我们可以稍后再微调。

如前所述,我们不会依赖我们的Rasberry PI来运行检测-所以我们将设置一些网络通信。我原本想自己写这篇文章(我现在正在学习围棋,所以这将是一个很好的用例),但是如果有库又何必费心呢?[1]

以下是关于我如何设置PI的示例记录:

接下来,我们将不得不使用VidGear的开发分支,因为在撰写本文时,主服务器上还没有某个bug修复程序。

您应该看到视频正在回放。您会注意到多处理库的一些用法-出于开发目的,我们使用它来确保WHILE循环在定义的超时后终止。

[1]笑话放一边:SQLite的创建者理查德·希普(Richard Hipp)在Changelog Podcast的采访中给出了很多很好的理由来解释为什么这可能是一个坏主意-但为了简单起见,我们将坚持使用库。

接下来,让我们将其实际部署到两台不同的机器上-只要将执行TensorFlow的服务器运行64位风格的Linux(就像Linux内核一样),我们就应该可以运行了。在家里,我有一个本地的GitLab和Jenkins实例为我做这件事。但实际上,任何部署选项都有效-SCP可以成为您的朋友。

我们需要通过指定IP地址和端口对代码进行一些小调整:

客户端=NETGEAR(地址=';192.168.1.xxx,端口=';5454';,协议=';TCP';,模式=0,接收\_模式=True,日志=True)服务器=NETGEAR(地址=';192.168.1.xxx,端口=';5454';,协议=';TCP';,模式=0,接收\_模式=。

现在,我们可以在服务器上启动sender.py,在客户机上启动Receiver.py,然后就可以开始了:网络上的视频。干净利落!

在这一点上,TensorFlow的集成是微不足道的:因为我们已经确定了如何执行以下操作:

最后一步只需导入我们的TensorFlow_Detector模块,将接收到的图像转换为Numpy数组(因为这是API所期望的),然后调用“Run_Inference_for_Single_Image(2)”即可。轻而易举!

现在,我们可以调整服务器代码以实际使用TensorFlow来检测来自不同机器的图像。但我们不想要录制的图像,我们需要的是实况转播。

幸运的是,这非常简单,因为我们已经在PI设置期间启用了相机模块:将相机的带状电缆连接到PI,启动它,然后运行:

为了对Python执行同样的操作,OpenCV的API同样简单:通过将源从视频文件更改为摄像机的ID-0,因为我们只有一个-在pi的一端,OpenCV将拾取摄像机流并将其发送到我们的服务器。

现在,我们可以将Raspberry上的视频流式传输到服务器,并检测到有人。现在缺少的一环是使用PlaySound库播放音频,GStreamer在引擎盖下。其他备选方案正在使用OS子进程调用或pyGame-可以设置配置选项来更改此行为。

为此,我们将再次使用ZMQ,方法是在PI上启动一个侦听器线程,等待来自服务器的输入,并设置预定义的枚举值。一旦客户端接收到这些信息,它就会触发音频信号并播放声音。

所有这些都阻塞了各自的线程-这意味着,只要音频播放,监听器就不会关心新消息,服务器也就无法发送新消息。

为了避免爆破相同的信息,我们可以采用简单的Sempahore结构。

启动服务器和客户端,看看我们走进房间会发生什么!

正如你可以看到的,它需要一秒钟就能检测到我-部分原因是摄像头的角度,我们选择的型号,以及一些网络延迟。在现实生活中,一个人需要走出家门,这就不是什么问题了。

虽然这个功能已经运行得相当不错了--它可以流式传输视频、检测人并发送发送音频的信号--但这里肯定还有很多工作要做。

然而,为了这个项目的目的,我们忽略了几件事:我们使用的模型只是一个预先训练的模型,既没有针对我们的特定用例进行调整,也不一定为我们正在使用的机器提供最佳的平衡。

此外,代码中的某些方面可以进行一些改进--网络延迟还不错,但可能需要做一些工作,音频会很快被连续触发,并且使用我们当前的ZeroMQ模式,我们只能支持一个客户端。

虽然使用纸板箱几乎就是完美的定义,但定制的3D打印树莓外壳和稍好的散热性可能是一个好主意。

无论如何-我对这个小项目很满意,因为它说明了在不使用任何公共云产品的情况下,构建自己的安全摄像头、将其连接到网络、运行对象检测并触发外部因素(在本例中是音频,但很容易是电话通知或其他内容)是多么简单,从而节省了住宅互联网上的延迟和成本。

所有开发都是在POPO!19.04下进行的,在Kernel 5.5.1上使用12个Intel i7-9750H [email protected] Ghz,在2019 System76 Gazelle笔记本电脑上使用16 GB RAM,在Raspian 10上使用Raspberry PI 4 4 GB。