所有文档

          智能边缘 BIE

          使用Movidius VPU加速边缘视频推断


          本章将使用已经开源的 ssd_mobilenet_v1_coco_2017_11_17 模型完整演示边缘视频AI的demo。

          一、前提准备


          二、搭建边缘硬件环境

          搭建边缘硬件环境,如下图所示:

          WechatIMG975.jpeg

          搭建步骤如下:

          1. 给边缘节点硬件供电
          2. 网络摄像头连接到POE口
          3. 无线网卡和Movidius随便插一个USB口

          整体环境信息如下:

          1. 边缘节点

            • 无线网卡IP:172.30.196.93
            • 与网络摄像头连接的IP:192.168.100.14
          2. 网络摄像头IP

            • 网络摄像头IP:192.168.100.10
            • rtsp流地址:rtsp://b:a1234567@192.168.100.10:554/Streaming/channels/1/,这个后续会用到。

              rtsp协议地址通用格式为 rtsp://<username>:<password>@<ip>:<port>/<Streaming/channels/stream_number> ,各参数解释如下:

              • <username> :摄像头登录用户名 ,一般可以在摄像头底座当中找到
              • <password> :摄像头登录密码,一般可以在摄像头底座当中找到
              • <ip> :路由器/交换机分配给摄像头的IP地址
              • <port> : RTSP 协议的端口号,一般默认为 554
              • <Streaming/channels/stream_number> :摄像头信道

          三、模拟场景

          1. 摄像头连接边缘盒子,实时探测视野范围内的物体
          2. 当检测到目标物体以后,保存抽帧图像,并同步发送一条消息到边缘broker服务。如果没有检测到目标物体,丢弃抽帧图像。
          3. 支持检测多目标物体,本场景实验检测的物体包括:剪刀笔记本电脑书本键盘

          四、边缘应用描述

          除了边缘节点连接云端是自动部署的baetyl-core和baetyl-function两个系统应用,还需要在边缘节点上部署以下四个应用

          序号 应用名 用途
          1 vi-broker 边缘节点本地MQTT Broker消息模块
          2 vi-function 模型推断结果后处理函数,将模型推断结果解析成可识别数据
          3 video-infer 模型推断应用,负责加载AI模型并执行AI推断
          4 remote-object 将边缘推断图片上传到云端对象存储

          最终边缘节点上将会有6个边缘应用,如下图所示:

          image.png

          五、边缘应用关系

          各模块之间的调用关系如下图所示:

          image.png

          整个视频推断流程如下:

          1. 视频抽帧
          2. 加载模型执行AI推断
          3. 调用函数对推断结果做后处理
          4. 基于函数返回结果,保存达到指定阈值的图片
          5. 将推断结果发送到
          6. 订阅本地broker消息,将满足条件的推断图片上传云端对象存储minio

          六、边缘应用配置

          vi-broker配置

          1. 创建配置项:vi-broker-conf,配置信息如下图所示:

          image.png

          添加一条数据配置项,变量名为:service.yml,变量值如下:

          logger:
            level: debug
          1. 创建应用:vi-broker,添加容器服务:broker,如下图所示:

          image.png

          • 服务名称:broker
          • 镜像:hub.baidubce.com/baetyl/broker:v2.0.0
          • 端口映射

            • 宿主机端口:1883
            • 容器端口:1883
            • 协议:TCP

          vi-function配置

          1. 创建函数配置项:vi-function-code,如下图所示:

          image.png

          • 标签:baetyl-function: python3-opencv
          • 配置数据变量名:analyse.py,此变量名analyse后续会作为函数入口
          • 配置数据变量值为python代码,代码如下:
          #!/usr/bin/env python
          # -*- coding:utf-8 -*-
          """
          function to analyse video infer result in python
          """
          
          import time
          import numpy as np
          
          location = "var/lib/baetyl/image/{}.jpg"
          classes = {
                  1: 'person',73: 'laptop',76: 'keyboard',77: 'cell phone',84: 'book',87: 'scissors'
          }
          
          def handler(event, context):
              """
              function handler
              """
          
              data = np.fromstring(event, np.float32)
              mat = np.reshape(data, (-1, 7))
              objects = []
              scores = {}
              for obj in mat:
                  # print("obj:", obj)
                  clazz = int(obj[1])
                  if clazz in classes:
                      score = float(obj[2])
                      if classes[clazz] not in scores or scores[classes[clazz]] < score:
                          scores[classes[clazz]] = score
                      if score < 0.6:
                          continue
                      objects.append({
                          'class': classes[clazz],
                          'score': score,
                          'left': float(obj[3]),
                          'top': float(obj[4]),
                          'right': float(obj[5]),
                          'bottom': float(obj[6])
                      })
          
              res = {}
              res["imageDiscard"] = len(objects) == 0
              res["imageObjects"] = objects
              res["imageScores"] = scores
              path = location.format(time.time())
              if len(objects) != 0:
                  res["imageLocation"] = path
                  res["publishTopic"] = "video/infer/result"
                  res["type"] = "UPLOAD"
                  content = {}
                  content["localPath"] = path
                  content["remotePath"] = path
                  res["content"] = content
          
              return res
          1. 创建函数应用:vi-function,添加函数服务:vi-function-service,如下图所示:

          image.png

          • 服务名称:vi-fucntion-service
          • 服务类型:函数服务,非容器服务
          • 函数配置项:使用之前创建的配置项:vi-function-conf
          • 运行时:python3-opencv
          • 函数入口:analyse.handler。

            函数的完整路径是 [服务名称/函数入口] ,则上述 analyse 这个python函数的完整调用路径就是:vi-fucntion-service/analyse

          video-infer配置

          1. 创建配置项:video-infer-conf,如下图所示:

          image.png

          • 创建配置数据,变量名为:conf.yml,变量如下:
          video:
            uri: 'rtsp://b:a1234567@192.168.100.10:554/Streaming/channels/1/'
            limit:
              fps: 1
          infer:
            model: var/lib/baetyl/model/frozen_inference_graph.pb
            config: var/lib/baetyl/model/ssd_mobilenet_v1_coco_2017_11_17.pbtxt
            backend: openvino
            device: vpu
          process:
            before:
              swaprb: true
              width: 300
              hight: 300
            after:
              function:
                name: vi-fucntion-service/analyse # 与前面创建的vi-function函数对应。
          logger:
            path: var/lib/baetyl/app-log/video-infer.log
            level: debug
          broker:
            address: 'tcp://broker:1883' # 与前面创建的vi-broker应用对应。
            clientid: video-infer
          function:
            address: 'http://baetyl-function.baetyl-edge-system'
          • 通过 backend: openvinodevice: vpu 这两个配置项,实现让video-infer这个应用使用Movidius加速棒的vpu算力来执行边缘推断计算。如果没有这两个配置项,则默认使用cpu推断。
          • video-infer执行AI推断以后会调用分析函数 vi-fucntion-service/analyse
          • 分析函数返回的消息会发布到本地MQTT Broker tcp://broker:1883
          1. 创建配置项:video-infer-model,如下图所示:

          image.png

          • endpoint:对象存储访问地址
          • bucket名称:在对象存储当中创建的bucket名称,此处为:model-upload
          • 文件名称:模型文件在对象存储当中的文件名,如果在在目录当中,则这里需要填写目录名称+文件名称,此处为:ssd_mobilenet_v1_coco_2017_11_17.zip
          • AK/SK:对象存储访问凭证
          • MD5:模型文件ssd_mobilenet_v1_coco_2017_11_17.zip的MD5值为:acc050a4e8fcea32edcb30ab510e63b7。边缘节点在下载完ssd_mobilenet_v1_coco_2017_11_17.zip模型文件以后,会对模型文件执行MD5校验,以验证下载文件的完整性。
          • 是否解压:选择 ,解压格式为ZIP。边缘节点下载模型文件ssd_mobilenet_v1_coco_2017_11_17.zip以后,会负责将其解压。在本案例当中,ssd_mobilenet_v1_coco_2017_11_17.zip解压以后会得到frozen_inference_graph.pbssd_mobilenet_v1_coco_2017_11_17.pbtxt这里两个模型文件。
          1. 创建应用:video-infer,添加容器服务:video-infer-openvino,如下图所示:

          image.png

          image.png

          • 服务名:video-infer-openvino
          • 镜像:hub.baidubce.com/baetyl/video-infer:v2.0.0-openvino-amd64
          • 卷配置:

            • conf:添加 video-infer-conf 配置项,作为模块配置
            • model:添加 video-infer-model 配置项,边缘节点会自动下载ssd_mobilenet_v1_coco_2017_11_17模型文件并解压至/var/lib/baetyl/model目录,然后video-infer应用会从此处加载模型文件frozen_inference_graph.pbssd_mobilenet_v1_coco_2017_11_17.pbtxt
            • image:将AI推断保存的图片从容器内目录/var/lib/baetyl/image映射到宿主机目录。此处参数填写的是video-infer-image,对应宿主机目录/var/lib/baetyl/app-data/video-infer-image
            • dev:Movidius USB插入到边缘盒子以后,会在宿主机/dev目录下多出一个设备,将宿主机的/dev目录映射到容器内的/dev目录下。
          • 特权选项

            • 启用特权模式:是

          remote-object配置

          1. 创配配置项:remote-mino-conf,如下图所示:

          image.png

          添加配置数据变量名为:service.yml,对应的变量值如下所示:

          hub:
            address: 'tcp://broker:1883'
          clients:
            - name: minio
              address: 'http://ip:port'
              ak: AKIAIOSFODNN7EXAMPLE
              sk: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
              timeout: 10m
              kind: CEPH
              pool:
                worker: 100
                idletime: 30s
              bucket: image-upload
          rules:
            - clientid: remote-minio-1
              subscribe:
                topic: video/infer/result
                qos: 1
              client:
                name: minio
          logger:
            path: var/lib/baetyl/app-log/minio.log
            level: debug
          1. 创建应用:remote-object,然后添加容器服务:remote-object,如下图所示:

          image.png

          • 服务名称:remote-object
          • 镜像地址:hub.baidubce.com/baetyl-beta/baetyl-remote-object:0.1.6
          • 卷配置

            • minio-conf:挂载remote-object服务的配置项
            • image:将宿主机当中的推断图片映射至容器内目录,这样remote-object服务才能拿到图片将其上传至minio对象存储当中。
            • app-log:如果需要将模块的日志文件映射到宿主机,需要配置此项。

          七、验证边缘AI检测结果

          step1:应用部署至边缘节点

          1. 将上述应用全部部署至边缘节点,如下图所示:

          image.png

          1. 检查边缘节点上的应用部署情况,如下图所示:

          image.png

          step2:使用MQTT Box订阅边缘节点本地broker服务

          模拟场景当中提到“当检测到目标物体以后,保存抽帧图像,并同步发送一条消息到边缘broker服务”,为了监测发送到broker服务的消息,我们使用MQTT Box工具提前订阅 video/infer/result 这个topic的消息,如下图所示:

          image.png

          step3:使用摄像头检测物体

          1. 手持摄像头,旋转一周,让摄像头能够扫描到办公桌上的剪刀笔记本电脑书本键盘,以及坐在工位上的
          2. 实时查看订阅了hub模块的MQTT Box的消息界面,每检测到一个目标物体,MQTT Box就能订阅到一条消息。

          image.png

          1. 将MQTTBox订阅的消息进行Json格式化,得到如下结果:
          {
              "content":{
                  "localPath":"var/lib/baetyl/image/1602639487.0222735.jpg",
                  "remotePath":"var/lib/baetyl/image/1602639487.0222735.jpg"
              },
              "imageCaptureTime":"2020-10-14T01:38:06.971394704Z",
              "imageDiscard":false,
              "imageHight":720,
              "imageInferenceTime":0.046391136,
              "imageLocation":"var/lib/baetyl/image/1602639487.0222735.jpg",
              "imageObjects":[
                  {
                      "bottom":0.9267578125,
                      "class":"scissors",
                      "left":0.166259765625,
                      "right":0.505859375,
                      "score":0.97412109375,
                      "top":0.233154296875
                  }
              ],
              "imageProcessTime":0.082386501,
              "imageScores":{
                  "book":0.09637451171875,
                  "cell phone":0.0443115234375,
                  "person":0.0282135009765625,
                  "scissors":0.97412109375
              },
              "imageWidth":1280,
              "publishTopic":"video/infer/result",
              "type":"UPLOAD"
          }

          通过上述消息,可以得出如下结论:

          • 检测到物体是剪刀:"class": "scissors"
          • AI推断为剪刀的得分是0.974:"scissors": 0.974121093751
          • 图片已保存:"imageLocation": "var/lib/baetyl/image/1602639487.0222735.jpg",对应宿主机目录:/var/lib/baetyl/app-data/video-infer-image/1602639487.0222735.jpg

          step4:验证被保存的图片当中的对象

          1. SSH登录到边缘节点,查看已经保存了多张抽帧图片,如下图所示:

          image.png

          1. 1602639487.0222735.jpg 下载到本地电脑,确认该图片当中物体是剪刀,与MQTT Box接收到消息一致,如下图所示:

          1602639487.0222735.jpg

          step5:验证推断结果图片上传至云端对象存储

          打开minio控制台,进入到选择image-upload这个bucket,然后进度到目录var/lib/baetyl/image,我们可以看到从边缘节点上传的图片,如下图所示:

          image.png

          上一篇
          操作指南
          下一篇
          将EasyEdge模型部署至边缘节点