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

发表评论

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