智能边缘BIE

    操作指南

    概述 当中描述了真实的 渣土抛洒 场景以及解决方案。因为渣土识别模型是私有模型无法公开,本章将使用已经在github开源的 ssd_mobilenet_v1_coco_2017_11_17 作为替代模型,完整演示边缘视频AI的操作指南。

    前提准备


    模拟场景

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

    通过本教程你将学习

    1. 搭建边缘AI硬件环境
    2. 配置边缘AI模块
    3. 验证边缘AI检测结果

    操作流程

    搭建边缘AI硬件环境

    摄像头可以使用树莓派摄像头模块USB摄像头IP摄像头,不同的摄像头有不同的配置方式:

    • 树莓派摄像头模块:针对树莓派摄像头模块的环境搭建,可以参考 树莓派3B摄像头安装与测试
    • USB摄像头:针对USB摄像头的环境搭建,请参考官方文档 使用标准USB摄像头

      默认情况下,在树莓派摄像头模块和USB摄像头连接树莓派以后,系统中会新增了 /dev/video0 这个设备,这个参数0将在后续的 video-infer模块配置 当中被用到。

    • IP摄像头:树莓派需要通过 rtsp 协议访问IP摄像头,可以先通过 VLC media player 等工具测试IP摄像头是否可以通过 rtsp 协议访问。如下图所示:

      vlc1.png

      vlc2.png

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

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

    配置边缘AI模块

    除了树莓派初始连接BIE建立的agent模块之外,还需要为树莓派这个边缘核心添加额外4个模块:

    序号 模块名 模块类型
    1 agent baetyl-agent 边缘核心与云端BIE通讯模块
    2 localhub baetyl-hub 边缘核心本地MQTT Broker消息模块
    3 function-manager baetyl-function-manager 边缘函数管理模块
    4 function-python baetyl-function-python36-opencv41 后处理函数,处理AI推断结果
    5 video-infer baetyl-video-infer AI推断模块,加载AI模型执行AI推断

    每个模块都需要做相应的配置,详细配置可点击此处下载 baetyl_video-infer-demo

    模块关系图

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

    module-arch.png

    模块功能详细说明

    1. video-infer

      • 采集视频数据
      • 对视频抽帧
      • 基于AI模型对抽帧图像进行AI推断
      • 通过GRPC接口调用后处理函数管理器function-manager
    2. function-manger

      • 接收video-infer模块的调用
      • 为video-infer分配具体的后处理函数function-python
    3. function-python

      • 真实的后处理函数,预装了opencv 4.1,对video-infer模块的AI推断结果进行后处理
      • 返回后处理结果给video-infer模块
    4. video-infer

      • 根据后处理函数的返回结果,决定是否保存抽帧图像,是否发送mqtt消息到hub模块

    模块1:localhub

    localhub模块需要绑定以下存储卷:

    存储卷 存储卷模板 版本 宿主机目录 容器目录 只读 配置文件
    mt-localhub-conf baetyl模块配置 V1 var/db/baetyl/mt-localhub-conf/V1 etc/baetyl true service.yml
    mt-localhub-log 空目录存储卷 V1 var/db/baetyl/mt-localhub-log var/log/baetyl false
    mt-localhub-data 空目录存储卷 V1 var/db/baetyl/mt-localhub-data var/db/baetyl/data false
    • mt-localhub-conf存储卷有对应的配置文件service.yml,配置详情参考baetyl_video-infer-demo/var/db/baetyl/mt-localhub-conf/V1/service.yml
    • localhub模块需要进行端口映射绑定,将容器的1883端口映射暴露出来,配置如下图所示:

      image.png


    模块2:function-manager

    function-manager模块需要绑定以下存储卷:

    存储卷 存储卷模板 版本 宿主机目录 容器目录 只读 存储卷配置文件
    mt-function-manager-conf baetyl模块配置 V3 var/db/baetyl/mt-function-manager-conf/V3 etc/baetyl true service.yml
    demo-log 空目录存储卷 V1 var/db/baetyl/demo-log var/log/baetyl false
    • mt-function-manager-conf存储卷有对应的配置文件service.yml,配置详情参考baetyl_video-infer-demo/var/db/baetyl/mt-function-manager-conf/V3/service.yml

    模块3:function-python

    function-python使用的镜像为: hub.baidubce.com/baetyl/baetyl-function-python36:0.1.6-opencv41, 如下图所示:

    image.png

    function-python模块需要绑定以下存储卷:

    存储卷 存储卷模板 版本 宿主机目录 容器目录 只读 存储卷配置文件
    mt-function-python-conf baetyl模块配置 V1 var/db/baetyl/mt-function-python-conf/V1 etc/baetyl true service.yml
    mt-function-python-code 自定义存储卷 V2 var/db/baetyl/mt-function-python-code/V2 var/db/baetyl/code true analyse.py
    mt-image-data 空目录存储卷 V1 var/db/baetyl/mt-image-data var/db/baetyl/image false
    demo-log 空目录存储卷 V1 var/db/baetyl/demo-log var/log/baetyl false
    • mt-function-python-conf存储卷有对应的配置文件service.yml,配置详情参考baetyl_video-infer-demo/var/db/baetyl/mt-function-python-conf/V1/service.yml
    • mt-function-python-code存储卷有对应的配置文件analyse.py,配置详情参考baetyl_video-infer-demo/var/db/baetyl/mt-function-python-conf/V1/analyse.py。在BIE控制台当中,找到mt-function-python-code这个自定义存储卷,进入存储卷,点击 创建可编辑文件 ,然后将analyse.py当中的python代码拷贝至界面右侧的文本框当中,点击 保存 完成配置,如下图所示:

      mt-function-python-code2.png

    analyse.py 处理函数解析:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    """
    function to analyse video infer result in python
    """
    
    import numpy as np
    
    location = "var/db/baetyl/image/{}.jpg"
    # 定义需要识别的物体,可识别的物体清单可以在本文提到的mscoco_label_map当中找到
    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:
            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
                # 后处理逻辑,如果AI推断结果的score得分<0.6分,则直接忽略,只有score>=0.6的物体才会被加入到对象数组当中
                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 = {}
        # 如果 len(objects) == 0 ,则表示没有识别到对象,会丢弃抽帧图片,否则video-infer模块会保存抽帧图片
        res["imageDiscard"] = len(objects) == 0
        res["imageObjects"] = objects
        res["imageScores"] = scores
        res["messageTimestamp"] = int(context["messageTimestamp"]/1000000)
        # 只有识别到物体,才发送消息到localhub
        if len(objects) != 0:
            res["imageLocation"] = location.format(context["messageTimestamp"])
            res["publishTopic"] = "video/infer/result"
    
        return res

    模块4:video-infer

    video-infer模块需要绑定以下存储卷:

    存储卷 存储卷模板 版本 宿主机目录 容器目录 只读 存储卷配置文件
    video-infer-conf baetyl模块配置 V4 var/db/baetyl/video-infer-conf/V4 etc/baetyl true service.yml
    infer-person-model 自定义存储卷 V1 var/db/baetyl/infer-person-model/V1 var/db/baetyl/model true frozen_inference_graph.pb,ssd_mobilenet_v1_coco_2017_11_17.pbtxt
    mt-image-data 空目录存储卷 V1 var/db/baetyl/mt-image-data var/db/baetyl/image false
    demo-log 空目录存储卷 V1 var/db/baetyl/demo-log var/log/baetyl false
    • mt-localhub-conf存储卷有对应的配置文件service.yml,配置详情参考baetyl_video-infer-demo/var/db/baetyl/mt-localhub-conf/V1/service.yml
    • 模型文件frozen_inference_graph.pb和ssd_mobilenet_v1_coco_2017_11_17.pbtxt需要打包成一个zip压缩包上传到自定义存储卷infer-person-model,上传以后系统会自动解压缩,如下图所示:

      model-file-zip.png

    • 如果是树莓派摄像头模块或者是USB摄像头,video-infer模块还需要挂载外部设备/dev/video0,配置如下图所示:

      image.png

    video-infer-conf配置解析

    本案例当中video-infer-conf的配置如下,参数的详细配置逻辑请参考baetyl-video-infer配置

    hub:
      address: 'tcp://localhub:1883'
      username: test
      password: hahaha
      cleansession: true
    video:
      uri: '0'
      # uri: 'rtsp://admin:admin@192.168.1.2:554/Streaming/channels/1/'
      limit:
        fps: 1
    infer:
      model: var/db/baetyl/model/frozen_inference_graph.pb
      config: var/db/baetyl/model/ssd_mobilenet_v1_coco_2017_11_17.pbtxt
    process:
      before:
        swaprb: true
        width: 300
        hight: 300
      after:
        function:
          name: analyse
    functions:
      - name: analyse
        address: 'function-manager:50051'
    logger:
      path: var/log/baetyl/infer-service.log
      level: debug
    • 如果是树莓派摄像头模块USB摄像头或者uri 配置为设备编号,假定摄像头对应/dev/video0,则uri配置为 0,同时需要将设备地址 /dev/video0 映射进容器
    • 如果是IP摄像头uri配置为IP摄像头的rtsp协议访问地址,假定IP摄像头的rtsp协议访问地址为rtsp://admin:admin@192.168.1.2:554/Streaming/channels/1/,则uri就配置为此地址
    • 如果是读取已有的视频文件信息抽帧分析,则uri配置为视频文件的地址,视频文件以 自定义存储卷 形式挂载到video-infer模块

    验证边缘AI检测结果

    step1:配置下发

    云端一切配置完毕,将配置发布为正式版本,下发至边缘核心设备,并检查模块已经正常启动。

    在BIE控制台查看下发的版本是否生效,以及当前边缘核心服务模块的状态,如下图所示:

    core-version.png

    登录到树莓派,通过docker ps命令检查服务模块运行状态,如下图所示:

    dockerps.png

    step2:使用MQTTBox订阅localhub

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

    localhub.png

    step3:使用摄像头检测物体

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

    scissors.png

    MQTT消息解析

    将MQTTBox订阅的消息进行Json格式化,得到如下结果:

    {
    		"imageCaptureTime": "2019-12-05T06:32:01.095503816Z",
    		"imageDiscard": false,
    		"imageHight": 480,
    		"imageInferenceTime": 0.680533552,
    		"imageLocation": "var/db/baetyl/image/1575527521095503816.jpg",
    		"imageObjects": [{
    			"bottom": 0.7979179620742798,
    			"class": "scissors",
    			"left": 0.4228750169277191,
    			"right": 0.7018369436264038,
    			"score": 0.9887169599533081,
    			"top": 0.29671576619148254
    		}],
    		"imageProcessTime": 0.691838184,
    		"imageScores": {
    			"book": 0.0685628280043602,
    			"cell phone": 0.040239665657281876,
    			"keyboard": 0.03728525713086128,
    			"person": 0.037795186042785645,
    			"scissors": 0.9887169599533081
    		},
    		"imageWidth": 640,
    		"messageTimestamp": 1575527521095,
    		"publishTopic": "video/infer/result"
    	}

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

    • 检测到物体是剪刀:"class": "scissors"
    • AI推断为剪刀的得分是0.988:"scissors": 0.9887169599533081
    • 图片已保存:"imageLocation": "var/db/baetyl/image/1575527521095503816.jpg"

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

    1. 登录到树莓派,查看已经保存了多张抽帧图片,如下图所示:

      pic.png

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

      1575527521095503816.jpg

    baetyl-video-infer 已适配模型列表

    video-infer模块已适配的模型如下表所示:

    框架 类型 模型
    TensorFlow Object Detection faster_rcnn_inception_v2_coco_2018_01_28
    faster_rcnn_resnet50_coco_2018_01_28
    mask_rcnn_inception_v2_coco_2018_01_28
    ssd_inception_v2_coco_2017_11_17
    ssd_mobilenet_v1_coco_2017_11_17
    ssd_mobilenet_v2_coco_2018_03_29
    ssd_mobilenet_v1_ppn_shared_box_predictor_coco14_sync_2018_07_03
    DarkNet Object Detection yolov3
    yolov3-ssp
    yolov3-tiny
    yolov2
    yolov2-tiny
    ImageNet Classification densenet201
    darknet
    extraction
    darknet19
    darknet19_448
    darknet53
    darknet53_448

    当前video-infer主要支持TensorFlowDarkNet两大框架的模型。如果要在边缘侧运行针对其他框架的模型,比如PaddlePaddleCaffe框架,可以参考 BIE与EasyEdge集成 。通过EasyEdge,可以将任意框架的模型转换成可在边缘侧运行的模型服务,实现Model as a Service。

    上一篇
    概述
    下一篇
    边缘流式计算Creek实战