Press "Enter" to skip to content

在ARM盒子上使用IEF和Tensorflow运行边缘AI

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

场景介绍

 

由于视频流占用很多网络带宽,越来越多的场景下,希望在视频流产生的地方,对图像进行处理,在节省网络带宽的同时,能够快速处理,也能避免网络延迟和抖动带来的不确定性。典型应用场景为:化工厂内部通过图像检测火情,园区内人脸匹配进行安检,建筑工地施工人员是否佩戴安全帽。

 

在ARM盒子(以atlas500为例,arm64v8架构可以直接使用代码和镜像)上,通过网络接入网络摄像头,使用tensorflow框架对图像进行对象检测模型推理,检测结果通过MQTT协议推送到web页面上进行展示。

 

运行环境

 

1)网络摄像头,rtsp协议,ipc网络地址格式

 

2)智能小站(atlas500),EulerOS

 

3)tensorflow1.4.0(python2.7)

 

4)mosquitto 1.6.5

 

5)python: opencv-python 4.1.1, paho-mqtt 1.4.0

 

6)nodejs: mqtt 3.0.0, react 16.9.0

 

我使用atlas500智能小站,来看看是个什幺样的设备,性能还是很强大的。( https://e.huawei.com/cn/material/enterprise/030106f2129145efa9c9bb472c7b0058
)。

 

7)CPU:海思Hi3559A处理器

 

双核ARM Cortex [email protected],32KB I-Cache,64KB D-Cache /512KB L2 cache

 

双核ARM Cortex [email protected],32KB I-Cache,32KB D-Cache /256KB L2 cache

 

8)GPU:双核ARM Mali [email protected],256KB cache

 

9)处理器内存规格DDR4 4GB,64bit,2400Mbps

 

10)Atlas 200 AI加速模块

 

2个DaVinci AI Core

 

CPU:8核A55,max 1.6GHz

 

乘加计算性能:8TFLOPS/FP16,16TOPS/INT8

 

内存规格:LPDDR4X,128bit,容量8GB/4GB,接口速率3200 Mbps

安装运行步骤

 

为了构建系统,分步来做:

 

通过IEF对智能小站进行纳管

 

连接网络摄像头并测试视频流

 

使用MQTT协议建立消息服务,并测试数据的发布和订阅

 

通过tensorflow对图像进行推理

 

对检测结果进行展示

 

1

 

通过IEF对智能小站进行纳管

 

1)打开华为云网站产品:智能边缘平台(https://www.huaweicloud.com/),使用自己账户登入,打开页面后,点击“注册边缘节点”,填写边缘几个信息。在“名称”里面可以填写名字。这次暂时不使用atlas500上AI加速卡。

 

 

2)接下来在“是否启用docker”选择“是”,在“系统日志”和“应用日志”中可以按照自己实际选择。

 

 

3)第三步,由于atlas500芯片是arm64架构,务必选择“arm64”方式,先下载文件。

 

 

下面在atlas500上进行安装

 

1)根据设备上标识的账户和密码,以及设备IP地址,从电脑上使用ssh方式登入到atlas500上。

 

2)在atlas500上,使用命令:docker version,检查docker是否存在,如果未安装,参考arm64版本的docker ce进行安装

3)根据上述1.3步骤中命令安装,把atlas纳入IEF管理之中

 

sudo tar -zxvf edge-installer_1.0.5_arm64.tar.gz -C /opt
sudo mkdir -p /opt/IEF/Cert; sudo tar -zxvf atlas500_training.tar.gz -C /opt/IEF/Cert
cd /opt/edge-installer; sudo ./installer -op=install

 

在华为云智能边缘平台上查看运行状态,状态从“未纳管”显示为“运行中”

 

 

 

在atlas500上安装边缘计算平台,已经完成。

 

2

 

连接网络摄像头并测试视频流

 

1)购买的摄像头为IPC格式,我把所有设备接入到同一个路由器下面,通过产品手册提供的内容,查看到摄像头相应的IP地址,可以获取到摄像头RTSP协议的URL为:”rtsp://admin:[email protected]:554//Streaming/Channels/1″。

 

2)在电脑上安装和打开VLC播放器,并点击导航栏“媒体”,“打开网络串流”,填入摄像头的地址”rtsp://admin:[email protected]:554//Streaming/Channels/1″,点击“播放”,我就可以看到摄像头拍摄的视频。表面摄像头可以使用,整个RTSP协议也是正常的。

3)使用python连接网络摄像头。首先通过命令行安装所需的opencv库。

 

pip install opencv-python

 

首先我想确认下opencv是否安装正确,启动下面代码后,如果在界面上可以展示视频流,表面安装没有问题。

 

•import cv2


cap = cv2.VideoCapture("rtsp://192.168.1.164:554/user=admin&password=&channel=1&stream=1.sdp?")
ret,frame = cap.read()
while ret:
    cv2.imshow("frame", frame)
    ret, frame = cap.read()
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break


cv2.destroyAllWindows()
cap.release()

 

也可以通过保存图像,或者录制成视频文件格式,查看摄像头是否工作正常。

 

最后通过web页面查看摄像头是否工作正常,由于浏览器对rtsp协议支持并不好,当前只在IE11浏览器中查看到相应视频流,通过IE11加载下面页面,点击允许控件(根据自己实现情况修改下面的rtsp视频流地址),就可以看到摄像头视频流。

 

<html>
<title>camera rtsp check</title>
<meta charset="utf-8">


<body>
     <object  type='application/x-vlc-plugin' id='Object1' width="500" height="400" events='True' pluginspage="http://www.videolan.org" codebase="        http://downloads.videolan.org/pub/videolan/vlc-webplugins/2.0.6/npapi-vlc-2.0.6.tar.xz" >
         <param name='mrl' value='rtsp://192.168.1.164:554/user=admin&password=&channel=1&stream=1.sdp?' />
         <param name='autoplay' value='true' />
         <param name='loop' value='false' />
         <param value="transparent" name="wmode"> 
     </object >
</body>
</html>

 

3

 

使用MQTT协议建立消息服务

 

1)使用mosquitto程序做为mqtt的broker,使用python发布消息,以nodejs订阅消息,为下一步使用tensorflow检测结果并用mqtt发送检测结果,使用nodejs构建前端页面订阅消息并展示,建立消息服务的系统建立基础。

 

2)使用mosquitto构建消息服务,构建的dockerfile如下,使用主机网络模式,以命令/usr/sbin/mosquitto启动,启动后默认使用1883的端口进行通信

 

 FROM arm64v8/ubuntu:19.10


RUN set -ex; \
  apt-get update; \
  apt-get -y install mosquitto; \
  rm -rf /var/lib/apt/lists/*

 

3)使用nodejs订阅消息使用mqtt的库,填写默认的端口号1883,订阅“object_detection”的topic,参考代码如下

 

 //mqtt_sub.js
const mqtt = require('mqtt');
const PORT = 1883;
const HOST = 'localhost';
const defualtPubSettigs = {retain: true, qa: 0};


var options = {
    port: PORT,
    host: HOST,
    rejectUnauthorized: false,
};


client = mqtt.connect('mqtt://localhost', options);
client.subscribe('object_detection',{qos:1});


client.on('message',function(top,message) {  
    console.log(message.toString());  
});

 

4)以此为基础建立docker,dockerfile如下

 

•FROM arm64v8/node:10.16.3


COPY mqtt_sub.js /root/


WORKDIR /root


RUN set -ex; \
  npm install --save mqtt

 

5)使用python发送消息使用paho.mqtt的库,填写默认的端口号1883,发布“object_detection”的topic,参考代码如下:

 

#mqtt_pub.py
import paho.mqtt.client as mqtt
import json


client = mqtt.Client()
client.connect("127.0.0.1", 1883, 600)


obj_ret = json.dumps({
    "num_detections": 1,
    "detection_classes": 1,
})
client.publish('object_detection', obj_ret, qos=0)

 

以此为基础建立docker,dockerfile如下

 

FROM arm64v8/python:2.7


RUN set -ex; \
  pip install paho-mqtt


COPY mqtt_pub.py /root/


ENTRYPOINT ["/usr/local/bin/python", "/root/mqtt_pub.py"]

 

6)通过构建和下发镜像,之后可以通过docker logs查看镜像消息,如果能看到相应的log信息,表面整个消息服务已经成功建立

 

4

 

通过tensorflow对图像进行推理

 

使用Opencv,通过RTSP协议连接网络摄像头,再对图像帧进行对象检测,最终通过mqtt协议把检测结果发送到消息服务中。对于连接摄像头,参考上述步骤中的“连接网络摄像头并测试视频流“, 发送检测效果参考”使用MQTT协议建立消息服务”,剩余部分主要针对使用tensorflow对图像进行检测。

 

参考 https://github.com/tensorflow/models/tree/master/research/object_detection
中的object_detection_tutorial.ipynb,添加使用opencv对rtsp协议进行解析,获取每一帧图像,针对图像数据,使用已经训练好的模型,对图像进行推理。

 

检测模型可以从 https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md
中获取,制作好的镜像中包含了测试模型:ssd_mobilenet_v2_coco。推理的结果最终使用MQTT协议把结果发送出来。

 

推理模型的参数:

 

MODEL_NAME = ‘ssd_mobilenet_v2_coco_2018_03_29’

 

摄像头的参数:

 

RTSP_URI = ‘rtsp://192.168.1.164:554/user=admin&password=&channel=1&stream=1.sdp?’

 

参考代码od_atlas.py如下:

 

#od_atlas.py
import numpy as np
import os
import sys
import tensorflow as tf
import cv2
import json
import paho.mqtt.client as mqtt


sys.path.append("..")
from object_detection.utils import ops as utils_ops
from utils import label_map_util


client = mqtt.Client()
client.connect("127.0.0.1", 1883, 600)


cv2.setUseOptimized(True)


MODEL_NAME = 'ssd_mobilenet_v2_coco_2018_03_29'
PATH_TO_FROZEN_GRAPH = MODEL_NAME + '/frozen_inference_graph.pb'


# List of the strings that is used to add correct label for each box.
PATH_TO_LABELS = os.path.join('data', 'mscoco_label_map.pbtxt')
print("PATH_TO_LABELS", PATH_TO_LABELS)


detection_graph = tf.Graph()
with detection_graph.as_default():
    od_graph_def = tf.GraphDef()
    print("PATH_TO_FROZEN_GRAPH", PATH_TO_FROZEN_GRAPH)
    with tf.gfile.GFile(PATH_TO_FROZEN_GRAPH, 'rb') as fid:
        serialized_graph = fid.read()
        od_graph_def.ParseFromString(serialized_graph)
        tf.import_graph_def(od_graph_def, name='')


category_index = label_map_util.create_category_index_from_labelmap(PATH_TO_LABELS, use_display_name=True)


cap = cv2.VideoCapture("rtsp://192.168.1.164:554/user=admin&password=&channel=1&stream=1.sdp?")
fps = cap.get(cv2.CAP_PROP_FPS)
cap.set(cv2.CAP_PROP_FPS, 1)
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)


num = 0


with detection_graph.as_default():
    with tf.Session() as sess:


        ops = tf.get_default_graph().get_operations()
        all_tensor_names = {output.name for op in ops for output in op.outputs}
        tensor_dict = {}
        for key in [
            'num_detections', 'detection_boxes', 'detection_scores',
            'detection_classes', 'detection_masks'
        ]:
            tensor_name = key + ':0'
            if tensor_name in all_tensor_names:
                tensor_dict[key] = tf.get_default_graph().get_tensor_by_name(
                    tensor_name)
        if 'detection_masks' in tensor_dict:
            detection_boxes = tf.squeeze(tensor_dict['detection_boxes'], [0])
            detection_masks = tf.squeeze(tensor_dict['detection_masks'], [0])


            real_num_detection = tf.cast(tensor_dict['num_detections'][0], tf.int32)
            detection_boxes = tf.slice(detection_boxes, [0, 0], [real_num_detection, -1])
            detection_masks = tf.slice(detection_masks, [0, 0, 0], [real_num_detection, -1, -1])
            detection_masks_reframed = utils_ops.reframe_box_masks_to_image_masks(
                detection_masks, detection_boxes, height, width)
            detection_masks_reframed = tf.cast(
                tf.greater(detection_masks_reframed, 0.5), tf.uint8)


            tensor_dict['detection_masks'] = tf.expand_dims(
                detection_masks_reframed, 0)
        image_tensor = tf.get_default_graph().get_tensor_by_name('image_tensor:0')


        while True:
            ret, image_np = cap.read()
            if ret == False:
                continue
            num = num + 1
            print("frame num", num)


            image_np_expanded = np.expand_dims(image_np, axis=0)
            output_dict = sess.run(tensor_dict,
                                   feed_dict={image_tensor: image_np_expanded})


            output_dict['num_detections'] = int(output_dict['num_detections'][0])
            output_dict['detection_classes'] = output_dict[
                'detection_classes'][0].astype(np.int64)
            output_dict['detection_scores'] = output_dict['detection_scores'][0]


            output = {}
            num_detections = int(output_dict['num_detections'])
            for i in range(num_detections):
                detection_class = int(output_dict['detection_classes'][i])
                class_name = category_index[detection_class]['name']
                score = output_dict['detection_scores'][i]
                scores = "scores %.f%%" % (score * 100)
                output[class_name] = scores


            print("output ", output)
            if num_detections > 0 :
                obj_ret = json.dumps(output)
                client.publish('object_detection', obj_ret, qos=0)
            else:
                client.publish('object_detection', "", qos=0)


cap.release()

 

完整的docker image可以参考braveyuyong/tf_on_atlas:tagname:0.2.1,参考dockerfile如下:

 

FROM python:2.7


ENV DEBIAN_FRONTEND=noninteractive


RUN set -ex; \
  apt-get update; \
  apt-get -y install python-opencv; \
  apt-get -y install protobuf-compiler; \
  pip install numpy; \
  pip install paho-mqtt; \
  pip install pillow; \
  apt-get -y install libhdf5-dev; \
  rm -rf /root/.cache/; \
  rm -rf /var/lib/apt/lists/*


RUN ln -s /usr/lib/python2.7/dist-packages/cv2.aarch64-linux-gnu.so /usr/local/lib/python2.7/site-packages/cv2.aarch64-linux-gnu.so


RUN curl -OL "https://github.com/lhelontra/tensorflow-on-arm/releases/download/v1.14.0-buster/tensorflow-1.14.0-cp27-none-linux_aarch64.whl" && \
    pip install tensorflow-1.14.0-cp27-none-linux_aarch64.whl && \
    rm tensorflow-1.14.0-cp27-none-linux_aarch64.whl




RUN mkdir /models
WORKDIR /models


RUN git init && \
        git remote add origin https://github.com/tensorflow/models.git && \
        git config core.sparsecheckout true && \
        echo "resarch/object_detection" >> .git/info/sparse-checkout && \
        git pull --depth 1 origin master && \
        rm -rf .git research/object_detection/test*


WORKDIR /models/research/object_detection
RUN protoc /models/research/object_detectionobject_detection/protos/*.proto --python_out=.
COPY . /models/research/object_detection




ENTRYPOINT ["/usr/local/bin/python", "od_atlas.py"]

 

5

 

通过web页面对结果进行展示

 

使用nodejs订阅主题:object_detection,之后通过websocket把推理结果推送到前端页面。前端页面把推理结果和网络摄像头的视频流在页面上展示出来。

 

关于RTSP协议的插件,当前只支持IE11,注意在public/rtsp.html中设置rtsp地址()

 

在src\components\Visual\index.jsx中设置atlas500的IP参数。

 

代码片段如下:

 

//public/rtsp.html
client.addListener('object_detection', (topic, message) => {
    if (sock) {
        sock.emit('object_detection', `${message.toString()}`);
    }
});
//src\components\Visual\index.jsx
this.state = {
      url: 'http://192.168.1.111:3001',
};


socket.on('object_detection', (data) => {
  this.setState({
    ob_ret: data.toString(),
  });
});


render() {
  const { ob_ret } = this.state;
  let component;
  if (ob_ret) {
    component = <p>{ob_ret}</p>;
  } else{
    component = <p></p>;
  } 
}

最终效果

 

先把eclipse-mosquitto的镜像(https://hub.docker.com/_/eclipse-mosquitto )下载,
并上传到华为云SWR上,并通过IEF新建应用下发到节点上,构建mqtt的broker。整个软件架构图如下:

 

 

把页面展示镜像(已经制作好的镜像参考docker pull braveyuyong/visual_rtsp:0.1)进行同样操作,新建应用。

 

最后把TF推理镜像(docker pull braveyuyong/tf_on_atlas:0.1.2)进行同样操作,下发应用的时候我选择使用cpu 3core,内存2048M。

 

 

最终的三个应用状态如下:

 

 

通过浏览器IE11打开URL: http://192.168.1.111:3001,如果能看到摄像头视频流和推理结果,表明大功告成!

 

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注