树莓派深度学习:使用 Raspberry Pi 和 YOLO 构建深度学习相机

Amazon 刚刚发布了 DeepLens,一款智能摄像头,它使用机器学习来检测物体,脸部和活动,比如在相机上弹吉他。DeepLens 目前尚不可用,但智能相机的想法是令人兴奋的。

想象一下,如果能够使用能够分辨出你弹吉他的时间,或者创造新的舞蹈,或者只是学习新的滑板技巧的相机。它可以使用原始图像数据来判断你是否有一招。或者,如果你正在做一个新的舞蹈,那么这一系列的姿势,以及它们如何适合音乐。

今天,我们将建立一个深度学习相机,检测网络摄像头图像中是否存在鸟类,然后保存鸟的照片。最终将给我们如下所示这样的图像:

深度学习相机是机器学习计算机全新平台的开端。

DeepLens 有 100 GFlops 的计算能力可用于推断,这只是一个有趣的深度学习相机计算机所需的计算能力的开始。未来,这些设备将变得更加强大,并允许每秒推断数百个图像。

但谁愿意等待未来?

哑相机,智能推断

我们将在边缘上使用一台 “哑巴” 相机电脑(如只售 $9 的 Raspberry Pi),将其挂接到网络摄像头,然后通过 WiFi 发送图像,而不是在我们的相机中构建深度学习模型。在多一点延迟的权衡之下,我们今天可以构建一个同样的 DeepLens 概念的原型,但是价格便宜得多。

所以在今天的帖子里,我们会这样做的。我们将用 Python 编写一个 Web 服务器,将 Raspberry Pi 的图像发送到另一台计算机进行推理或图像检测。

另一台具有更强处理能力的计算机,将使用名为 “YOLO” 的神经网络体系结构对该输入图像进行检测,并判断摄像机帧中是否有鸟。

我们将从 YOLO 体系结构开始,因为它是最快的检测模型之一。它有一个对应于 Tensorflow 的模型端口,它很容易安装,并可以在多个不同的平台上运行。作为奖励,如果您使用我们在本文中使用的 Tiny 模型,您还可以在 CPU 上进行检测,无需昂贵的 GPU。

回到我们的原型。如果在相机框架中检测到鸟,我们将保存该图像以供以后分析。

这只是一个真正的智能深度学习相机的开始,非常基础,但你必须从某个地方开始。 所以让我们跳进来,让我们的原型的第一个版本来敲开我们的门。

检测与成像

正如我们已经说过的那样,DeepLens 的成像正好建立在电脑之中。所以它可以做基准级别的检测,并确定进入的图像是否符合您的标准与机载计算能力。

但是像 Raspberry Pi 这样的东西,我们不一定有实时进行船上检测所需的计算能力。相反,我们将使用另一台计算机来对图像中的内容进行推理。

就我而言,我使用了一台基本的,带网络摄像头和 wifi 接入的简单 Linux 计算机(Raspberry Pi 3 和一个便宜的网络摄像头),为我的深度学习机器做一个服务器来做推理。

这是一个很好的技术栈,因为它允许保存许多便宜的相机,并在我的台式机上在一个地方完成所有的计算。

摄像头图像服务器技术栈

如果您不想使用 Raspberry Pi 相机,可以使用这些说明在您的 Raspberry Pi 上安装 OpenCV 3,不过在说明中用 OpenCV 版本 3.3.1 替代 3.3.0 以获得本地安装的最新版本。

作为旁注,我必须禁用 CAROTENE 编译才能在我的 Raspberry Pi 上获得 3.3.1。你可能也需要这样做。

一旦完成,我们只需要在 Flask 中设置我们的 Web 服务器,以便我们可以从网络摄像头加载图像。

我已经使用 Miguel Grinberg 出色的摄像头服务器代码作为起点,创建了一个简单的 jpg 端点而不是运动 jpeg 端点:

#!/usr/bin/env python
from importlib import import_module
import os
from flask import Flask, render_template, Response

# uncomment below to use Raspberry Pi camera instead
# from camera_pi import Camera

# comment this out if you're not using USB webcam
from camera_opencv import Camera

app = Flask(__name__)

@app.route('/')
def index():
    return "hello world!"

def gen2(camera):
    """Returns a single image frame"""
    frame = camera.get_frame()
    yield frame

@app.route('/image.jpg')
def image():
    """Returns a single current image for the webcam"""
    return Response(gen2(Camera()), mimetype='image/jpeg')

if __name__ == '__main__':
    app.run(host='0.0.0.0', threaded=True)

如果你想使用 Raspberry Pi 视频摄像头,请确保取消注释 camera_pi 行,并注释掉 camera_opencv 行。

你可以用一个 python3 app.py 或者 gunicorn 来运行这个服务器,就像在 Miguel 的文章中提到的一样。

它只是利用 Miguel 优秀的摄像头管理功能,在没有请求进入的时候关闭摄像头,并且如果有多台机器对从摄像头进入的图像进行推理,还可以管理线程。

一旦我们在 Raspberry Pi 上启动了它,我们就可以通过首先发现它的 IP 地址来测试并确保服务器工作,然后尝试通过我们的 Web 浏览器访问它。

该 URL 应该类似于 http://192.168.1.4:5000/image.jpg

拉取图像并从相机服务器进行推断

现在我们已经有一个 API 结点加载摄像头的当前图像,我们可以构建脚本来抓取和运行这些图像的推理。

我们将使用 requests,一个伟大的 Python 库来抓取来自 URL 的文件,以及 Darkflow,这是 Tensorflow 上的 YOLO 模型的实现。

不幸的是,没有安装 Darkflow 的 pip wheel,所以我们需要克隆这个项目,然后在计算机上自行构建和安装,以便进行推理。

在安装 Darkflow repo 之后,我们还需要下载我们将要使用的 YOLO 版本的权重和模型。

在这里,我使用 YOLO V2 微型网络,因为我想在较慢的计算机上运行我的推论,使用板载 CPU,而不是主要桌面上的 GPU。这个微小的网络与 YOLO v2 的完整版本相比,具有更低的准确性。

有了这个内置和下载,我们还需要在检测计算机上安装 PillownumpyOpenCV

最后,我们终于可以编写我们的代码来运行检测:

from darkflow.net.build import TFNet
import cv2

from io import BytesIO
import time
import requests
from PIL import Image
import numpy as np

options = {"model": "cfg/tiny-yolo-voc.cfg", "load": "bin/tiny-yolo-voc.weights", "threshold": 0.1}

tfnet = TFNet(options)

birdsSeen = 0
def handleBird():
    pass

while True:
    r = requests.get('http://192.168.1.11:5000/image.jpg') # a bird yo
    curr_img = Image.open(BytesIO(r.content))
    curr_img_cv2 = cv2.cvtColor(np.array(curr_img), cv2.COLOR_RGB2BGR)

    result = tfnet.return_predict(curr_img_cv2)
    print(result)
    for detection in result:
        if detection['label'] == 'bird':
            print("bird detected")
            birdsSeen += 1
            curr_img.save('birds/%i.jpg' % birdsSeen)
    print('running again')
    time.sleep(4)

有了这个,我们有一个非常基本的第一个版本的检测运行。我们可以在控制台上看到我们的 Raspberry Pi 检测到了什么,我们也可以看到每个被看到的鸟都保存在我们的硬盘上。

稍后,我们可以运行一个程序来对 YOLO 检测到的鸟类进行标记。

平衡:更多的假阳性或更多的假阴性?

有一点需要注意,我们创建的选项字典中的阈值键。

这个门槛说明我们需要具备什么样的置信水平,才能说我们已经发现了我们正在寻找的东西。

出于测试目的,我已经把它设置为 0.1。 但是,这个低的门槛会给我们带来很多误报。更糟糕的是,我们用于检测的 Tiny YOLO 模型比真正的 YOLO 模型不太准确,所以我们会有一些错误的检测结果。

降低或提高阈值可以提高或降低模型的总输出,具体取决于您要构建的内容。在我的情况下,我没有更多的误报,但是我更喜欢获得更多的鸟类图像。 您可能需要调整这些参数以符合您的需求。

等待鸟类

让鸟儿进入我的喂鸟器花了很长时间。我想在后面几天的时间里我会在后院喂鸟。

相反,它花了几天。松鼠一直在吃我留下的食物,似乎在头几天我几乎没有看到天空中的一只鸟。

最后,我打破了,并得到了第二个喂鸟器,这是一个更清晰可见,离开地面。有了这个,我终于开始获得一些像在开始的帖子的图像。

从这往哪儿走

这篇文章的代码一如既往在 Github 上。

因为这篇文章本身就是结合了以前的其他作品,所以并没有太多的东西。Miguel Grinberg 的 Flask 视频流示例和 Darkflow 和 Darknet 的深度学习模型都用于检测。

这篇文章是我将使用深度学习相机尝试与鸟类互动的一系列课程的开始。

原文链接:Building a Deep Learning Camera with a Raspberry Pi and YOLO