从零开始带你用爱克斯板+OpenVINO做视频流检测

openlab_4276841a 更新于 8月前

完成人:卢雨畋 - 英特尔边缘计算创新大使

官方手册:https://www.xzsteam.com/docs/index.html

在开箱后,我们能看到如图所示的板子和铜柱螺丝,我们首先要做的是是把他旋到爱克斯板的四个角上,螺丝从风扇的那面向下插入四个最边角的孔,然后在底部(如图面)把铜柱与螺丝旋在一起即可,如图所示:

接下来,我们就可以通电开机了;你只需要把电插上,观察到风扇转动后过一会儿就可以在显示屏上看到windows系统启动了!如果没有启动,你可以找到电源插口处同一侧的另一头的黑色小圆点,按下后就可以正常启动。

接下来,你就可以进行windows下的正常操作,和你使用自己的电脑一样即可(你可以直接连接wifi,如果连接失败可以尝试重启或者是轻轻的摆弄一下天线);但我比较爱折腾,接下来我会为你演示如何将他重新安装成ubuntu系统,并开始ubuntu系统下的深度学习程序推理。

遇事不决看文档,我们注意到https://www.xzsteam.com/docs/osinstallation.html#toc-1,决定使用Canonical为Intel优化的版本。

这里我根据CPU选择的是:

选择镜像下载后,你可以选择制作成启动盘,或者使用一个开源软件ventory将他放置到U盘中,随后重启电脑不断单击F2键即可进入BIOS,然后按照文档步骤操作进入安装界面即可。

安装完毕后重启即可成功进入系统:

当然,在最后别忘了安装GPU驱动支持,安装后才可以在openvino上使用GPU。

mkdir neo && cd neo

wget https://ghproxy.com/https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.11702.1/intel-igc-core_1.0.11702.1_amd64.1.deb

wget https://ghproxy.com/https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.11702.1/intel-igc-opencl_1.0.11702.1_amd64.deb

wget https://ghproxy.com/https://github.com/intel/compute-runtime/releases/download/22.35.24055/intel-level-zero-gpu-dbgsym_1.3.24055_amd64.ddeb

wget https://ghproxy.com/https://github.com/intel/compute-runtime/releases/download/22.35.24055/intel-level-zero-gpu_1.3.24055_amd64.deb

wget https://ghproxy.com/https://github.com/intel/compute-runtime/releases/download/22.35.24055/intel-opencl-icd_22.35.24055_amd64.deb

wget https://ghproxy.com/https://github.com/intel/compute-runtime/releases/download/22.35.24055/libigdgmm12_22.1.3_amd64.deb

sudo dpkg -i *.deb

安装完毕后重启即可。

为了方便操作,你可以在此时安装远程控制工具进行操作或者查看对应的ip直接SSH(记得安装openssh),但这里还有一个很棒的方法推荐;你可以安装 Vscode,然后使用它的Tunnel插件进行远程隧道连接(模拟内网穿透),你只需要安装所需插件,然后在爱克斯板中打开 Vscode ,点击左下角的小人,选择“打开远程隧道访问”,然后在你的电脑上同时打开 Vscode,安装 remote ssh插件后找到远程中的Tunnnels 访问对应的电脑就可以成功进入爱克斯板的环境当中。

如果你想要用远程工具访问ubuntu版本的爱克斯板,请记得按照如下方式安装工具:

sudo apt-get install lightdm 选择lightdm

随后sudo dpkg-reconfigure gdm3选择lightdm,紧接着重启即可。

接下来让我们进入正式的开发环节,首先我们可以先通过 openvino 的 benchmark_app 查看爱克斯板的性能,首先安装 openvino,

pip install openvino-dev -i https://pypi.tuna.tsinghua.edu.cn/simple

pip install openvino -i https://pypi.tuna.tsinghua.edu.cn/simple

安装完毕后,我们可以在命令行输入 benchmark_app -h ,若出现下列输出则代表openvino安装成功。

接下来我们将以 Paddle PicoDet 来简单展示在爱克斯板上使用 OpenVINO的过程,首先我们先来看一下Paddle PicoDet,作为适合部署在边缘开发板上的模型,PicoDet能保证在一定的mAP精度上最大化运行速度:

我们可以结合 benchmark app 工具来简单估计模型的大致最后运行速度,首先需要下载对应的模型:https://github.com/PaddlePaddle/PaddleDetection/tree/release/2.6/configs/picodet

值得提醒的是,很多后处理过程涉及到的算子都不被推理框架天然支持,所以我们需要

在modelzoo中找到导出后不带后处理的模型,你可以点击下列地址直接下载:https://paddledet.bj.bcebos.com/deploy/Inference/picodet_xs_320_coco_lcnet_non_postprocess.tar

打开后可以看到如下文件,这是picodet导出后的静态图模型,得益于Paddle和OpenVINO的良好兼容,我们可以直接对Paddle静态图模型进行加载使用,并不需要转换成OpenVINO模型(OpenVINO IR)。

我们可以输入如下测试代码,即得到在GPU上的实际FPS测试结果,这将为我们提供良好的性能初始信息,具体的参数信息你可以在 benchmark_app -h中找到,或者前往官网获取相关信息。

benchmark_app -m picodet_xs_320_coco_lcnet_non_postproces***odel.pdmodel -d GPU -api async -t 15

若成功运行,你将看到下列结果:(如果运行失败出现找不到显卡等错误,你需要重新安装文中开头提到的GPU驱动并重新启动爱克斯板,由于网络波动,你需要确认驱动都完全下载好并安装完毕)

可以看到,在完全异步利用GPU推理的情况下,我们理论上可以至少支持两个视频或摄像头的实时推理(320x320)。有的朋友可能觉得 PicoDet-XS模型的 mAP只有23.5显得太小,那我们可以使用PicoDet-S模型,29.1mAP可以满足基本需求,且速度也相对可接受:

在性能测试通过后,我们可以直接来运行对应检测程序了,在https://github.com/PaddlePaddle/PaddleDetection/tree/release/2.6/deploy/third_engine/demo_openvino/python 中你可以获取所有需要的运行代码。我们可以直接把这个三个文件下载或者**粘贴到爱克斯板上的工作文件夹即可。

值得注意的是,在上面我们使用的picodet_xs_320_coco_lcnet_non_postproces***odel.pdmodel 模型属于不包含任何后处理的网络,需要使用 openvino_benchmark.py 文件方可运行。而对于网络包含后处理,但不包含NMS的模型,则需要使用openvino_infer.py 文件运行,且还需下载对应的 onnx 模型(w/ 后处理;w/o NMS),如:https://paddledet.bj.bcebos.com/deploy/third_engine/picodet_xs_320_lcnet_postproccesed_woNMS.onnx 

我们可以随便把一个待检测图片放在目录下,按照下列方式修改配置即可一键运行:

openvino_benchmark.py需要修改的部分:

openvino_infer.py 需要修改的部分:

修改后直接运行对应python文件即可看到检测结果,且结果保存在目录下的res.jpg文件。

最后,为了展示视频流实时检测的效果,我们可以随便下载一个视频,然后运行下列代码启动视频流检测(你也可以将视频流读取改为0,即读取本地摄像头进行检测):

import cv2

import numpy as np

import time

import argparse

from scipy.special import softmax

from openvino.runtime import Core

from openvino_benchmark import PicoDetPostProcess,draw_box

def image_preprocess(image, re_shape):

    img = cv2.resize(

        image, (re_shape, re_shape), interpolation=cv2.INTER_LANCZOS4)

    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

    img = np.transpose(img, [2, 0, 1]) / 255

    img = np.expand_dims(img, 0)

    img_mean = np.array([0.485, 0.456, 0.406]).reshape((3, 1, 1))

    img_std = np.array([0.229, 0.224, 0.225]).reshape((3, 1, 1))

    img -= img_mean

    img /= img_std

    return img.astype(np.float32)

def infer(src_img,input_img):

    output = compiled_model.infer_new_request({0: input_img})

    result_ie = list(output.values())

    test_im_shape = np.array([[320, 320]]).astype('float32')

    test_scale_factor = np.array([[1, 1]]).astype('float32')

    np_score_list = []

    np_boxes_list = []

    num_outs = int(len(result_ie) / 2)

    for out_idx in range(num_outs):

        np_score_list.append(result_ie[out_idx])

        np_boxes_list.append(result_ie[out_idx + num_outs])

    postprocess = PicoDetPostProcess(input_img.shape[2:], test_im_shape,

                                        test_scale_factor)

    np_boxes, _ = postprocess(np_score_list, np_boxes_list)

    scale_x = src_img.shape[1] / input_img.shape[3]

    scale_y = src_img.shape[0] / input_img.shape[2]

    res_image = draw_box(src_img, np_boxes, class_label, scale_x, scale_y)

    res_image = src_img

    return res_image

MODEL_PATH = "picodet_xs_320_coco_lcnet_non_postproces***odel.pdmodel"

class_label= "coco_label.txt"

if __name__ == "__main__":

    # openvino init

    ie = Core()

    net = ie.read_model(MODEL_PATJ)

    compiled_model = ie.compile_model(net, 'CPU')

   

    cap = cv2.VideoCapture("行人.mp4")  

    if not cap.isOpened():

        print("无法打开视频流")

        exit()

    frame_count = 0

    start_time = time.time()

    while True:

        ret, frame = cap.read()

        input_img = image_preprocess(frame, 320)

        res_img = infer(frame,input_img)

        frame_count += 1

        elapsed_time = time.time() - start_time

        if elapsed_time > 1:

            fps = frame_count / elapsed_time

            print("实时帧速率 (FPS): {:.2f}".format(fps))

            start_time = time.time()

            frame_count = 0

        if not ret:

            break

        cv2.imshow("Video Stream", res_img)

        if cv2.waitKey(1) & 0xFF == ord('q'):

            break

    cap.release()

    cv2.destroyAllWindows()

从中我们可以观察到帧率可以基本保持在15~20FPS间,但这时候有朋友可能想问,之前在性能测试中我们不是测得结果比这高得多吗?是的,其实真正意义上的检测性能远比此高得多,因为此时瓶颈并不在检测本身,很有可能后处理和视频解码花费了更多时间。你可以采取更深入的技术来解决这些技术瓶颈(比如更换硬解码或者用c++ api实现推理过程,换用OpenVINO异步推理等等),相信在使用这些操作后,你的检测性能表现一定会更上一层楼。

至此,一个简单的爱克斯板从刷机到OpenVINO使用全流程就这样走通了,希望你能够跟随这篇教程完美解锁自己的OpenVINO体验,祝你在OpenVINO和爱克斯板的世界中探索愉快!

0个评论