• 利用 Video infer 服务实现摄像头图像采集与 AI 模型推断
    • 操作流程
    • 各服务配置
    • 测试及验证

    利用 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 服务发送消息的客户端为 MQTTBox

    操作流程

    • 步骤 1:在 Ubuntu18.04 上安装 Baetyl,相关内容可参考 快速安装 Baetyl
    • 步骤 2:依据本文测试需求,撰写各服务的配置文件,然后执行 sudo systemctl start baetyl 命令启动 Baetyl 服务,可以通过 sudo systemctl status baetyl 命令查看 Baetyl 服务的运行情况,关于各服务的配置情况请参考下文 各服务配置
    • 步骤 3:根据 Hub 服务的配置信息对 MQTTBox 进行连接配置,确保 MQTTBox 与 Hub 服务建立连接,更多可参考 与 Hub 服务建立连接
    • 步骤 4:MQTTBox 订阅主题 video/infer/result,观察其是否能够正常接收到模型的推断结果消息。上述步骤的操作流程示意图如下图所示。

    ../_images/video-infer-flow.png利用 video-infer 服务进行视频采集和 AI 模型推断

    各服务配置

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

    1. version: V0
    2. services:
    3. - name: localhub
    4. image: 'hub.baidubce.com/baetyl/baetyl-hub:latest'
    5. replica: 1
    6. ports:
    7. - '1883:1883'
    8. mounts:
    9. - name: localhub-conf
    10. path: etc/baetyl
    11. readonly: true
    12. - name: localhub-persist-data
    13. path: var/db/baetyl/data
    14. - name: demo-log
    15. path: var/log/baetyl
    16. - name: function-manager
    17. image: 'hub.baidubce.com/baetyl/baetyl-function-manager:latest'
    18. replica: 1
    19. mounts:
    20. - name: function-manager-conf
    21. path: etc/baetyl
    22. readonly: true
    23. - name: demo-log
    24. path: var/log/baetyl
    25. - name: function-python
    26. image: 'hub.baidubce.com/baetyl/baetyl-function-python36:0.1.6-opencv41'
    27. replica: 0
    28. mounts:
    29. - name: function-python-conf
    30. path: etc/baetyl
    31. readonly: true
    32. - name: function-python-code
    33. path: var/db/baetyl/code
    34. readonly: true
    35. - name: image-data
    36. path: var/db/baetyl/image
    37. - name: video-infer
    38. image: 'hub.baidubce.com/baetyl-beta/baetyl-video-infer:latest'
    39. replica: 1
    40. mounts:
    41. - name: infer-person-model
    42. path: var/db/baetyl/model
    43. readonly: true
    44. - name: image-data
    45. path: var/db/baetyl/image
    46. - name: demo-log
    47. path: var/log/baetyl
    48. - name: video-infer-conf
    49. path: etc/baetyl
    50. readonly: true
    51. volumes:
    52. - name: localhub-conf
    53. path: var/db/baetyl/localhub-conf
    54. - name: localhub-persist-data
    55. path: var/db/baetyl/localhub-persist-data
    56. - name: demo-log
    57. path: var/db/baetyl/demo-log
    58. - name: function-manager-conf
    59. path: var/db/baetyl/function-manager-conf
    60. - name: function-python-conf
    61. path: var/db/baetyl/function-python-conf
    62. - name: function-python-code
    63. path: var/db/baetyl/function-python-code
    64. - name: image-data
    65. path: var/db/baetyl/image-data
    66. - name: remote-mqtt-conf
    67. path: var/db/baetyl/remote-mqtt-conf
    68. - name: infer-person-model
    69. path: var/db/baetyl/infer-person-model
    70. - name: video-infer-conf
    71. path: var/db/baetyl/video-infer-conf

    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,配置信息如下:

    1. server:
    2. address: 0.0.0.0:50051
    3. hub:
    4. address: tcp://localhub:1883
    5. username: test
    6. password: hahaha
    7. functions:
    8. - name: analyse
    9. service: function-python
    10. instance:
    11. max: 10
    12. logger:
    13. path: var/log/baetyl/func-service.log
    14. level: "debug"

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

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

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

    1. hub:
    2. address: tcp://localhub:1883
    3. username: test
    4. password: hahaha
    5. video:
    6. uri: "rtsp://admin:admin@192.168.1.2:554/Streaming/channels/1/"
    7. limit:
    8. fps: 1
    9. infer:
    10. model: var/db/baetyl/model/frozen_inference_graph.pb
    11. config: var/db/baetyl/model/ssd_mobilenet_v1_coco_2017_11_17.pbtxt
    12. process:
    13. before:
    14. swaprb: true
    15. width: 300
    16. hight: 300
    17. after:
    18. function:
    19. name: analyse
    20. functions:
    21. - name: analyse
    22. address: function-manager:50051
    23. logger:
    24. path: var/log/baetyl/infer-service.log
    25. level: "debug"

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

    此外,Video infer 服务除支持抓取 IP 网络摄像头图片信息外,还支持抓取 USB 摄像头采集图像信息和读取视频文件进行抽帧。相应地,若为 USB 摄像头,则 uri 配置为设备编号,通用性配置为 “0”,同时需要将设备地址 /dev/video0 映射进容器;若配置读取视频文件进行抽帧,则直接配置 uri 内容为视频文件的地址,同时将该视频文件以(自定义)存储卷形式挂载到 Video infer 服务即可,更多关于存储卷的内容可以参考 如何正确地引入存储卷。

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

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

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

    1. version: V0
    2. services:
    3. - name: video-infer
    4. image: 'hub.baidubce.com/baetyl-beta/baetyl-video-infer:latest'
    5. replica: 1
    6. devices:
    7. - /dev/video0 # 将 USB 设备映射进容器
    8. mounts:
    9. - name: infer-person-model
    10. path: var/db/baetyl/model
    11. readonly: true
    12. - name: image-data
    13. path: var/db/baetyl/image
    14. - name: demo-log
    15. path: var/log/baetyl
    16. - name: video-infer-conf
    17. path: etc/baetyl
    18. readonly: true

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

    测试及验证

    如本文开头所述,本次测试我们采用 ssd_mobilenet_v1_coco_2017_11_17 模型,该模型可用于检测人、水果等多达 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. scores = {}
    21. for obj in mat:
    22. clazz = int(obj[1])
    23. if clazz in classes:
    24. score = float(obj[2])
    25. if classes[clazz] not in scores or scores[classes[clazz]] < score:
    26. scores[classes[clazz]] = score
    27. if score < 0.6:
    28. continue
    29. objects.append({
    30. 'class': classes[clazz],
    31. 'score': score,
    32. 'left': float(obj[3]),
    33. 'top': float(obj[4]),
    34. 'right': float(obj[5]),
    35. 'bottom': float(obj[6])
    36. })
    37.  
    38. res = {}
    39. res["imageDiscard"] = len(objects) == 0
    40. res["imageObjects"] = objects
    41. res["imageScores"] = scores
    42. res["publishTopic"] = "video/infer/result"
    43. res["messageTimestamp"] = int(context["messageTimestamp"]/1000000)
    44. if len(objects) != 0:
    45. res["imageLocation"] = location.format(context["messageTimestamp"])
    46.  
    47. return res

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

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

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

    ../_images/running-container-view.png 正在运行的容器列表

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

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

    ../_images/MQTTBox-connect-to-hub.png MQTTBox 与 Hub 服务建立连接

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

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

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

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

    至此,我们已经基于 Video infer 服务实现了 IP 网络摄像头图像的采集和 AI 模型的推断。