0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何在KV260上快速体验Vitsi AI图像分类示例程序

电子发烧友论坛 来源:电子发烧友论坛 2023-09-12 10:02 次阅读

本文首先将会对Vitis统一软件平台和Vitsi AI进行简单介绍,然后介绍如何在KV260上部署DPU镜像,最后在KV260 DPU镜像上运行Vitis AI自带的图像分类示例。通过本文,你将会对Vitis软件平台、Vitsi AI架构有初步认识,并知道如何在KV260上快速体验Vitsi AI图像分类示例程序。

01一、背景简介

开始本文的实操环节之前,这里我先介绍一些背景知识,分别是Vitis统一软件平台和Vitis AI。

1.1 Vitis 统一软件平台简介

来自Xilinx官网的简介,Vitis 统一软件平台包括:

全面的内核开发套件,可无缝构建加速应用

完整的硬件加速开源库,针对 AMD FPGA 和 Versal 自适应 SoC 硬件平台进行了优化

插入特定领域的开发环境,可直接在熟悉的更高层次框架中进行开发

不断发展的硬件加速合作伙伴库和预建应用生态系统

Vitis Model Composer 是一款基于模型的设计工具,不仅可在 MathWorks MATLABSimulink 环境中实现快速设计探索与验证 ,而且还可加速 AMD 器件的生产进程。

Vitis Networking P4 允许创建软定义网络。VitisNetP4 数据平面构建器生成的系统可以针对从简单的数据包分类到复杂的数据包编辑的各种数据包处理功能进行编程

来自官网的Vitis统一软件平台架构图:

fe278d48-50ff-11ee-a25d-92fbcf53809c.jpg

从官网的介绍页面我们也可以看到,Vitis 统一软件平台包括如下组件:

Vitis AI

Vitis 视频分析SDK

Vitis 库

Vitis HLS

Vitis Model Composer

今天我们将会重点介绍Vitis AI。

1.2 Vitsi AI简介

本节内容主要参考了自官方github.io文档。

AMD Vitis AI 是一个集成开发环境,可用于加速 AMD 平台上的 AI 推理。该工具链提供优化的IP、工具、库、模型以及资源,例如示例设计和教程,可在整个开发过程中为用户提供帮助。它在设计时充分考虑了高效率和易用性,在 AMD 自适应 SoC 和 Alveo 数据中心加速卡上释放了 AI 加速的全部潜力。

Vitis AI 解决方案由三个主要组件组成:

深度学习处理器单元 (DPU),用于优化 ML 模型推理的硬件引擎。

模型开发工具,用于为 DPU 编译和优化 ML 模型。

模型部署库和 API,用于从软件应用程序在 DPU 引擎上集成和执行 ML 模型。

Vitis AI 解决方案的打包和交付方式如下:

AMD 开放下载:集成 DPU 的预构建目标映像(以下简称“DPU镜像”)

Vitis AI Docker容器:模型开发工具

Vitis AI github 存储库:模型部署库、设置脚本、示例和参考设计

02二、部署DPU镜像到KV260

2.1 下载DPU镜像

在KV260开发板上正式体验Vitis AI之前,需要将上一节中提到的DPU镜像下载下来并烧录到SD上。

支持KV260的最新DPU镜像下载链接:https://china.xilinx.com/member/forms/download/design-license-xef.html?filename=xilinx-kv260-dpu-v2022.2-v3.0.0.img.gz

2.2 写入DPU镜像到SD卡

下载完成后,解压压缩包,通过Rufus将解压的wic文件写入SD卡。使用Rufus选择文件时,需要注意将右侧的默认文件类型修改为全部文件,否则默认不支持wic文件:

fe35e672-50ff-11ee-a25d-92fbcf53809c.png

写入过程显示进度:

fe4d145a-50ff-11ee-a25d-92fbcf53809c.png

2.3 启动DPU镜像系统

完成DPU镜像写入SD卡后,将SD卡读卡器从PC移除后,将SD卡插入到开发板,插好串口线,打开串口终端,波特率设置为115200,就可以准备上电开机了。

启动之后会自动登录root账号(默认密码为root):

fe5ae396-50ff-11ee-a25d-92fbcf53809c.png

插上网线的话,启动后还可以看到输出了dashborad访问链接:

fe8685d2-50ff-11ee-a25d-92fbcf53809c.png

根据ifconfig查看的IP地址,浏览器访问dashboard链接,可以看到实时状态监控:

fea2b068-50ff-11ee-a25d-92fbcf53809c.png

03三、运行Vitsi AI图像分类示例

3.1 DPU镜像自带的一些文件介绍

DPU镜像默认带有SSH服务,并且是开机启动的,因此可以使用MobaXterm的SSH客户端通过网络登录KV260,如下图所示:

fecb22be-50ff-11ee-a25d-92fbcf53809c.png

MobaXterm的SSH客户端时带有X11-forwarding功能的,支持将远程程序界面通过SSH协议显示在本地。

登录系统后,可以看到,/home/root目录下已经有了两个目录。

使用tree命令,可以看到Vitis-AI目录结构:

fef4319a-50ff-11ee-a25d-92fbcf53809c.png

接下来我们将会尝试运行vai_runtime下的resnet50示例程序,我们先看看这个目录下的文件结构:

ff018192-50ff-11ee-a25d-92fbcf53809c.png

里面有文件的作用分别为:

build.sh,编译脚本,里面包含编译src/main.cc的命令

resnet50,已经编译好的可执行程序,由src/main.cc编译生成

readme,说明文件

words.txt,分类标签

src/main.cc,示例程序源码

DPU镜像默认已经安装了gcc,直接运行build.sh就可以编译src/main.cc,并生成resnet50可执行文件。可以尝试将resnet50可执行文件删除掉,再运行build.sh脚本,观察是否重新生成了resnet50。

ff1950ce-50ff-11ee-a25d-92fbcf53809c.png

3.2 下载resnet50测试图片

通过以下命令,下载并解压resnet50测试图片:

cd ~
wget https://china.xilinx.com/bin/public/openDownload?filename=vitis_ai_runtime_r3.0.0_image_video.tar.gz -O vitis_ai_runtime_r3.0.0_image_video.tar.gz
mkdir vitis_ai_runtime_r3.0.0_image_video
tar -C vitis_ai_runtime_r3.0.0_image_video -xzvf vitis_ai_runtime_r3.0.0_image_video.tar.gz

(左右移动查看全部内容)

3.3 运行resnet50示例程序

接下来,通过如下命令,运行resnet50示例程序:

cd ~/Vitis-AI/examples/vai_runtime/resnet50
./resnet50 /usr/share/vitis_ai_library/models/resnet50/resnet50.xmodel

(左右移动查看全部内容)

运行结果如下:

ff22e12a-50ff-11ee-a25d-92fbcf53809c.png

报错说../images目录找不到。

创建../images目录,并将刚刚下载的resnet50测试图片拷贝到该目录中:

mkdir -v ../images
cp -vr ~/vitis_ai_runtime_r3.0.0_image_video/images/* ../images/

(左右移动查看全部内容)

运行输出如下:

ff4dfd06-50ff-11ee-a25d-92fbcf53809c.png

再次运行resnet50示例程序:

ff6a080c-50ff-11ee-a25d-92fbcf53809c.png

成功识别了。

命令行第二个参数 /usr/share/vitis_ai_library/models/resnet50/resnet50.xmodel 是resnet50的DPU模型文件,该文件在DPU镜像中已经有了,因此不需要手动下载。

3.4 使用金鱼图片进行测试

words.txt 文件中是resnet50识别结果的分类标签,可以看到前面几行中包含金鱼(goldfish)分类:

ff84b134-50ff-11ee-a25d-92fbcf53809c.png

因此,可以找一个金鱼图片进行测试。

随便找了一张:

通过MobaXterm左侧边栏的上传功能传到开发板上:

ffbca742-50ff-11ee-a25d-92fbcf53809c.png

默认上传位置为HOME目录(~)。

接下来,将金鱼图片拷贝到../images目录,并将原来的测试图片删除掉,重新运行resnet50示例程序,可以看到成功识别了金鱼:

ffd5b354-50ff-11ee-a25d-92fbcf53809c.png

04四、示例程序源码解读

接下来我们看看resnet50目录下的src/main.cc文件内容。

4.2 main函数

首先是main函数:

/**
 * [url=home.php?mod=space&uid=2666770]@Brief[/url] Entry for runing ResNet50 neural network
 *
 * [url=home.php?mod=space&uid=1902110]@NOTE[/url] Runner APIs prefixed with "dpu" are used to easily program &
 *    deploy ResNet50 on DPU platform.
 *
 */
int main(int argc, char* argv[]) {
 // Check args
 if (argc != 2) {
  cout << "Usage of resnet50 demo: ./resnet50 [model_file]" << endl;
    return -1;
  }
  auto graph = xir::deserialize(argv[1]);
  auto subgraph = get_dpu_subgraph(graph.get());
  CHECK_EQ(subgraph.size(), 1u)
      << "resnet50 should have one and only one dpu subgraph.";
  LOG(INFO) << "create running for subgraph: " << subgraph[0]->get_name();
 /*create runner*/
 auto runner = vart::create_runner(subgraph[0], "run");
 // ai::XdpuRunner* runner = new ai::XdpuRunner("./");
 /*get in/out tensor*/
 auto inputTensors = runner->get_input_tensors();
 auto outputTensors = runner->get_output_tensors();


 /*get in/out tensor shape*/
 int inputCnt = inputTensors.size();
 int outputCnt = outputTensors.size();
 TensorShape inshapes[inputCnt];
 TensorShape outshapes[outputCnt];
 shapes.inTensorList = inshapes;
 shapes.outTensorList = outshapes;
 getTensorShape(runner.get(), &shapes, inputCnt, outputCnt);


 /*run with batch*/
 runResnet50(runner.get());
 return 0;
}

(左右移动查看全部内容)

其中:

auto graph = xir::deserialize(argv[1]); 用于加载模型

auto runner = vart::create_runner(subgraph[0], "run"); 用于创建Runner对象

auto inputTensors = runner->get_input_tensors(); 用于获取输入Tensor对象

auto outputTensors = runner->get_output_tensors(); 用于获取输出Tensor对象

最后的 runResnet50(runner.get()); 运行模型

4.2 runRestnet50函数

接下来我们看看runReset50函数:

/**
 * @brief Run DPU Task for ResNet50
 *
 * [url=home.php?mod=space&uid=3142012]@param[/url] taskResnet50 - pointer to ResNet50 Task
 *
 * [url=home.php?mod=space&uid=1141835]@Return[/url] none
 */
void runResnet50(vart::Runner* runner) {
 /* Mean value for ResNet50 specified in Caffe prototxt */
 vector kinds, images;


 /* Load all image names.*/
 ListImages(baseImagePath, images);
 if (images.size() == 0) {
  cerr << "
Error: No images existing under " << baseImagePath << endl;
    return;
  }


  /* Load all kinds words.*/
  LoadWords(wordsPath + "words.txt", kinds);
  if (kinds.size() == 0) {
    cerr << "
Error: No words exist in file words.txt." << endl;
    return;
  }
  float mean[3] = {104, 107, 123};


  /* get in/out tensors and dims*/
  auto outputTensors = runner->get_output_tensors();
 auto inputTensors = runner->get_input_tensors();
 auto out_dims = outputTensors[0]->get_shape();
 auto in_dims = inputTensors[0]->get_shape();


 auto input_scale = get_input_scale(inputTensors[0]);
 auto output_scale = get_output_scale(outputTensors[0]);


 /*get shape info*/
 int outSize = shapes.outTensorList[0].size;
 int inSize = shapes.inTensorList[0].size;
 int inHeight = shapes.inTensorList[0].height;
 int inWidth = shapes.inTensorList[0].width;


 int batchSize = in_dims[0];


 std::vector> inputs, outputs;


 vector imageList;
 int8_t* imageInputs = new int8_t[inSize * batchSize];


 float* softmax = new float[outSize];
 int8_t* FCResult = new int8_t[batchSize * outSize];
 std::vector inputsPtr, outputsPtr;
 std::vector> batchTensors;
 /*run with batch*/
 for (unsigned int n = 0; n < images.size(); n += batchSize) {
    unsigned int runSize =
        (images.size() < (n + batchSize)) ? (images.size() - n) : batchSize;
    in_dims[0] = runSize;
    out_dims[0] = batchSize;
    for (unsigned int i = 0; i < runSize; i++) {
      Mat image = imread(baseImagePath + images[n + i]);


      /*image pre-process*/
      Mat image2;  //= cv::Mat(inHeight, inWidth, CV_8SC3);
      resize(image, image2, Size(inHeight, inWidth), 0, 0);
      for (int h = 0; h < inHeight; h++) {
        for (int w = 0; w < inWidth; w++) {
          for (int c = 0; c < 3; c++) {
            imageInputs[i * inSize + h * inWidth * 3 + w * 3 + c] =
                (int8_t)((image2.at(h, w)[c] - mean[c]) * input_scale);
     }
    }
   }
   imageList.push_back(image);
  }


  /* in/out tensor refactory for batch inout/output */
  batchTensors.push_back(std::shared_ptr(
    xir::create(inputTensors[0]->get_name(), in_dims,
              xir::DataType{xir::XINT, 8u})));
  inputs.push_back(std::make_unique(
    imageInputs, batchTensors.back().get()));
  batchTensors.push_back(std::shared_ptr(
    xir::create(outputTensors[0]->get_name(), out_dims,
              xir::DataType{xir::XINT, 8u})));
  outputs.push_back(std::make_unique(
    FCResult, batchTensors.back().get()));


  /*tensor buffer input/output */
  inputsPtr.clear();
  outputsPtr.clear();
  inputsPtr.push_back(inputs[0].get());
  outputsPtr.push_back(outputs[0].get());


  /*run*/
  auto job_id = runner->execute_async(inputsPtr, outputsPtr);
  runner->wait(job_id.first, -1);
  for (unsigned int i = 0; i < runSize; i++) {
      cout << "
Image : " << images[n + i] << endl;
      /* Calculate softmax on CPU and display TOP-5 classification results */
      CPUCalcSoftmax(&FCResult[i * outSize], outSize, softmax, output_scale);
      TopK(softmax, outSize, 5, kinds);
      /* Display the impage */
      bool quiet = (getenv("QUIET_RUN") != nullptr);
      if (!quiet) {
        cv::imshow("Classification of ResNet50", imageList[i]);
        cv::waitKey(10000);
      }
    }
    imageList.clear();
    inputs.clear();
    outputs.clear();
  }
  delete[] FCResult;
  delete[] imageInputs;
  delete[] softmax;
}

(左右移动查看全部内容)

其中,关键代码行如下:

ListImages(baseImagePath, images); 用于列出../images目录中的图片文件

LoadWords(wordsPath + "words.txt", kinds); 用于读取words.txt中的分类标签

Mat image = imread(baseImagePath + images[n + i]); 用于读取图片

resize(image, image2, Size(inHeight, inWidth), 0, 0); 用于将图片缩放为模型需要的尺寸

auto job_id = runner->execute_async(inputsPtr, outputsPtr); 开始异步执行模型推理

runner->wait(job_id.first, -1); 等待异步执行完成

cv::imshow("Classification of ResNet50", imageList[i]); 显示图片

cv::waitKey(10000); 等待键盘按键10秒

好了本篇内容就到这里了,感谢阅读,下次再会。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Xilinx
    +关注

    关注

    70

    文章

    2121

    浏览量

    119373
  • AI
    AI
    +关注

    关注

    87

    文章

    26443

    浏览量

    264062
  • 程序
    +关注

    关注

    114

    文章

    3631

    浏览量

    79543
  • 图像分类
    +关注

    关注

    0

    文章

    87

    浏览量

    11838

原文标题:【试用报告】如何在KV260上快速体验Vitsi AI图像分类示例程序

文章出处:【微信号:gh_9b9470648b3c,微信公众号:电子发烧友论坛】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    KV260视觉入门套件smartcamera体验

    KV260视觉入门套件smartcamera体验
    的头像 发表于 09-11 13:04 2049次阅读
    <b class='flag-5'>KV260</b>视觉入门套件smartcamera体验

    [KV260视觉入门套件试用体验]+KV260 开发套件使用初体验

    KV260开发板,我们可以接摄像头,在显示器显示摄像头图像,以及对摄像头视频数据做AI应用。 KV2
    发表于 07-31 01:26

    KV260视觉入门套件试用体验】运行SmartCamera示例程序

    将会了解如何在KV260安装最新版本Docker,以及如何在KV260运行Xilinx官方的
    发表于 08-20 23:38

    KV260视觉入门套件试用体验】KV260 开发套件使用体验(二、接通摄像头)

    ) 在KV260开发板,我们可以接摄像头,在显示器显示摄像头图像,以及对摄像头视频数据做AI应用。 2、
    发表于 09-03 11:41

    KV260视觉入门套件试用体验】部署DPU镜像并运行Vitis AI图像分类示例程序

    对Vitis软件平台、Vitsi AI架构有初步认识,并知道如何在KV260快速体验
    发表于 09-10 23:01

    KV260视觉入门套件试用体验】老刘记事儿KV260初体验之跑通Smart-Camera例程(四)

    【摘要】通过本帖你将了解到: (1)KV260运行Smart-Camera例程智能相机四种工作模式的详尽配置与指令操作步骤; (2)KV260运行Smart-Camera例程时常见的E
    发表于 09-15 22:43

    KV260视觉入门套件试用体验】KV260开发板初使用

    的硅器件、存储器、引导和安全模块。 Kria KV260 Vision AI是Xilinx公司推出的一款视觉AI入门套件,旨在为客户提供一个平台来评估他们的目标应用程序并最终设计他们
    发表于 09-18 14:56

    KV260视觉入门套件试用体验】五、VITis AI (人脸检测和人体检测)

    root@xilinx-kv260-starterkit-20222:~/Vitis-AI/board_setup/vek280# ./host_cross_compiler_setup.sh -sh
    发表于 09-26 16:22

    KV260视觉入门套件试用体验】Vitis-AI加速的YOLOX视频目标检测示例体验和原理解析

    示例体验 参考此前的帖子:【KV260视觉入门套件试用体验】部署DPU镜像并运行Vitis AI图像分类
    发表于 10-06 23:32

    KV260视觉入门套件试用体验】+03.SmartCamera人脸识别示例程序(zmj)

    **【KV260视觉入门套件试用体验】+03.SmartCamera人脸识别示例程序(zmj) ** 本篇主要介绍在KV260视觉入门套件使用Ubuntu-22.04-LTS系统镜像实现
    发表于 10-15 23:47

    KV260视觉入门套件试用体验】KV260开箱及镜像烧写

    是所有部件的照片 简单介绍一下kv260吧,Kria™ KV260 视觉 AI 入门套件是评估基于视觉 AI 的应用程序的开发平台。 系统镜
    发表于 10-16 03:31

    KV260视觉入门套件试用体验】四、KV260 视觉入门套件和固件更新

    设备 Kria™ KV260 Vision AI 入门套件具有主启动设备和辅助启动设备,可将特定于平台的启动固件,与运行时的操作系统和应用程序隔离。这使你能够专注于开发和更新应用程序
    发表于 10-17 08:28

    KV260视觉入门套件试用体验】三、开发板性能评估

    Wiki - Confluence (atlassian.net) Xilinx官方的快速入门指南: Kria KV260视觉 AI 入门套件 (xilinx.com) KV260
    发表于 10-17 08:39

    使用Xilinx Kria KV260进行AI火灾探测

    电子发烧友网站提供《使用Xilinx Kria KV260进行AI火灾探测.zip》资料免费下载
    发表于 10-27 10:12 5次下载
    使用Xilinx Kria <b class='flag-5'>KV260</b>进行<b class='flag-5'>AI</b>火灾探测

    kv260用的什么芯片?

    kv260用的什么芯片? KV260是一款电子产品,它使用的是微处理器芯片。微处理器芯片是一种将计算机的功能集成到一个小型芯片中的半导体设备。微处理器芯片除了拥有计算能力之外,还能控制其他电子设备
    的头像 发表于 08-16 11:15 750次阅读