利用 Video infer 服务实现摄像头图像采集与 AI 模型推断

    • 本文测试所用设备系统为 Ubuntu 18.04
    • 本文测试所用摄像头为海康威视 IP 网络摄像头,其型号为 DS-IPC-B12-1
    • 本文测试的 AI 推断跑在 CPU 使用官方的 video-infer 模块
    • 本文测试采用的 AI 模型为 ssd_mobilenet_v1_coco_2017_11_17
    • 模拟 MQTT client 向本地 Hub 服务发送消息的客户端为
    • 步骤 1:在 Ubuntu18.04 上安装 Baetyl,相关内容可参考 快速安装 Baetyl
    • 步骤 2:依据本文测试需求,撰写各服务的配置文件,然后执行 命令启动 Baetyl 服务,可以通过 sudo systemctl status baetyl 命令查看 Baetyl 服务的运行情况,关于各服务的配置情况请参考下文
    • 步骤 3:根据 Hub 服务的配置信息对 MQTTBox 进行连接配置,确保 MQTTBox 与 Hub 服务建立连接,更多可参考 与 Hub 服务建立连接
    • 步骤 4:MQTTBox 订阅主题 video/infer/result,观察其是否能够正常接收到模型的推断结果消息。上述步骤的操作流程示意图如下图所示。

    利用 video-infer 服务进行视频采集和 AI 模型推断

    Baetyl 主程序的配置文件位置 var/db/baetyl/application.yml,配置信息如下:

    Hub 服务配置文件位置 var/db/baetyl/localhub-conf/service.yml,配置信息如下:

    1. listen:
    2. - tcp://0.0.0.0:1883
    3. principals:
    4. - username: test
    5. password: hahaha
    6. permissions:
    7. - action: 'pub'
    8. permit: ['#']
    9. - action: 'sub'
    10. permit: ['#']
    11. logger:
    12. path: var/log/baetyl/localhub-service.log
    13. level: "debug"

    Function manager 服务配置文件位置 var/db/baetyl/function-manager-conf/service.yml,配置信息如下:

    Function python 服务配置文件位置 var/db/baetyl/function-python-conf/service.yml,配置信息如下:

    1. functions:
    2. - name: 'analyse'
    3. codedir: 'var/db/baetyl/code'
    4. logger:
    5. path: "var/log/baetyl/python-service.log"
    6. level: "debug"

    Video infer 服务配置文件位置 var/db/baetyl/video-infer-conf/service.yml,配置信息如下:

    需要注意的是,这里 uri 配置代表的是 IP 网络摄像头的地址,其通用格式为 rtsp://<username>:<password>@<ip>:<port>/Streaming/channels/<stream_number>,其中, 和 <password> 为激活成功后的 IP 摄像头的登录认证口令,<ip> 为该摄像头的IP地址,<port> 为 RTSP 协议的端口号,默认为 554,后面内容为信道,其中 <stream_number> 为 1 代表抓取主码流,为 2 代表抓取次码流。

    Video infer 服务捕获 USB 摄像头采集图像配置可参考:

    1. video:
    2. uri: "0"
    3. limit:
    4. fps: 1

    同时在 application.yml 配置中将 /dev/video0 设备地址映射到容器中,相关配置可参考:

    不难发现,从容器内读取宿主机的 USB 、串口等设备,均可采用上述设备映射的方式配置。

    如本文开头所述,本次测试我们采用 模型,该模型可用于检测人、水果等多达 90 项物品。这里,我们给出用于检测人的 Python 脚本仅供参考,具体如下:

    1. #!/usr/bin/env python
    2. # -*- coding:utf-8 -*-
    3. """
    4. function to analyse video infer result in python
    5. """
    6. import numpy as np
    7.  
    8. location = "var/db/baetyl/image/{}.jpg"
    9. classes = {
    10. 1: 'person'
    11. }
    12.  
    13. def handler(event, context):
    14. """
    15. function handler
    16. """
    17. data = np.fromstring(event, np.float32)
    18. mat = np.reshape(data, (-1, 7))
    19. objects = []
    20. for obj in mat:
    21. clazz = int(obj[1])
    22. if clazz in classes:
    23. score = float(obj[2])
    24. if classes[clazz] not in scores or scores[classes[clazz]] < score:
    25. scores[classes[clazz]] = score
    26. if score < 0.6:
    27. continue
    28. objects.append({
    29. 'class': classes[clazz],
    30. 'score': score,
    31. 'left': float(obj[3]),
    32. 'top': float(obj[4]),
    33. 'right': float(obj[5]),
    34. 'bottom': float(obj[6])
    35. })
    36.  
    37. res = {}
    38. res["imageDiscard"] = len(objects) == 0
    39. res["imageObjects"] = objects
    40. res["imageScores"] = scores
    41. res["publishTopic"] = "video/infer/result"
    42. res["messageTimestamp"] = int(context["messageTimestamp"]/1000000)
    43. if len(objects) != 0:
    44. res["imageLocation"] = location.format(context["messageTimestamp"])
    45.  
    46. return res

    若检测其他物品,直接在这里添加或修改即可,可支持检测物品列表参考 。

    一切就绪后,启动 Baetyl 服务,然后通过 sudo systemctl status baetyldocker ps 命令查看 Baetyl 服务的运行状态及正在运行的容器列表。

    ../_images/running-status-of-baetyl.png Baetyl 服务运行情况

    可以发现,Baetyl 服务处于 active (running) 状态,系统现在正在运行了 baetyl-hubbaetyl-video-inferbaetyl-function-managerbaetyl-function-python36 四个容器。

    然后,我们启动 MQTTBox,根据 Hub 服务配置完连接信息后,可以发现 MQTTBox 已经与 Hub 服务建立连接。

    MQTTBox 与 Hub 服务建立连接

    然后,通过 MQTTBox 订阅主题 video/infer/result,若服务运行正常,则 MQTTBox 会收到消息。

    ../_images/model-infer-result-none-person.png MQTTBox 接收消息,未检测到人

    MQTTBox 接收消息,检测到人

    如上所示,MQTTBox 通过订阅主题 video/infer/result 正确收到了消息。对比上述两条消息,可以发现一个检测到了人,一个未检测到人,如果模型检测到了人,则会在接收到的信息中给出类别 类别信息,同时给出检测到的人在捕获图片中的位置信息,可以用于后续的画框标记操作,感兴趣的可以参考 代码