KV260视觉AI套件--PYNQ-DPU-Resnet50

news2024/10/7 10:13:50

目录

1. 简介

2. 代码解析

3. 全部代码展示

4. 总结


1. 简介

本文以 Resnet50 为例,展示使用 PYNQ 调用 DPU 运行 Resnet50 网络的详细过程,并对其中关键代码做出解释。

PYNQ是一个针对Xilinx Zynq平台的Python开发框架,它允许开发者使用Python语言和库来利用Zynq的高效计算资源,使用 PYNQ 可以非常方便地处理各种与 Zynq 相关的计算任务,包括调用 DPU 进行推理。

Resnet50

一种深度卷积神经网络(CNN),它由50层构成。这种网络特别设计用于图像识别任务,并且在2015年的ImageNet大规模视觉识别挑战赛(ILSVRC)中取得了胜利。Resnet50的“残差学习”能力使得它可以通过添加更多的层来提高准确性,而不会导致训练难度增加或准确性下降。

这个网络的核心是“残差块”,它允许数据在网络的多个层之间直接传递,从而解决了深度网络训练中的“退化问题”。这种设计使得即使是非常深的网络也能有效地训练,并且随着网络深度的增加,性能也能得到提升。

2. 代码解析

  • 硬件和模型加载
overlay = DpuOverlay("dpu.bit")
overlay.load_model("dpu_resnet50.xmodel")

首先,加载一个名为 dpu.bit 的 FPGA 比特流到 Zynq 设备上。DpuOverlay 是 PYNQ 库中用于管理 FPGA 上的叠加层(overlay)的一个类。 

然后加载一个名为 dpu_resnet50.xmodel 的深度学习模型到已经配置好的 DPU 上。load_model 是 DpuOverlay 类的一个方法,它用于加载编译后的深度学习模型文件。这里的 dpu_resnet50.xmodel 是一个已经被转换和优化以适应 DPU执行的深度学习模型文件。

  • runner类,来自VART的方法
dpu = overlay.runner # runner类,来自VART的方法
inputTensors = dpu.get_input_tensors() # 返回是单个元素的列表
outputTensors = dpu.get_output_tensors() # 即[xir.Tensor]

VART(Vitis AI Runtime)是Xilinx提供的一套运行时库,用于在Xilinx平台上执行深度学习模型推理。

dpu = overlay.runner,这行代码通过访问overlay对象的runner属性,获取了一个VART运行时的实例。

  • 获取dimensions 
# 元组tuple,类似于列表list,但不可更改;dims -> dimensions
shapeIn = tuple(inputTensors[0].dims) # 元组(1, 224, 224, 3)
shapeOut = tuple(outputTensors[0].dims) # (1, 1, 1, 1000)
  • 计算输出数据大小
# get_data_size()方法返回输出张量的总大小,除以输入张量的第一维大小(即batch size),可以得到单个输出张量的大小。outputSize为1000
outputSize = int(outputTensors[0].get_data_size() / shapeIn[0])
  •  构建一维阵列,dtype=f64
softmax = np.empty(outputSize)
  • 形状shape创建内存数据阵列;order="C"行优先存储,"F"列优先存储 
output_data = [np.empty(shapeOut, dtype=np.float32, order="C")]
input_data  = [np.empty(shapeIn,  dtype=np.float32, order="C")]
  • 为 input_data 中第一个元素设置别名 image
image = input_data[0]
  • 图像预处理 
preprocessed = preprocess_fn(cv2.imread(os.path.join(image_folder, original_images[image_index])))
  • 格式转换,切片操作
image[0,...] = preprocessed.reshape(shapeIn[1:])
  • 执行异步推理作业,并等待结果返回
job_id = dpu.execute_async(input_data, output_data)
dpu.wait(job_id)

job_id = dpu.execute_async(input_data, output_data),这行代码调用execute_async方法来异步启动一个深度学习模型的推理任务。这个方法接收两个参数:input_data和output_data,分别代表模型的输入数据和用于接收模型输出结果的容器。input_data应该与模型的输入张量格式匹配,而output_data则应该是足够大以容纳预期的输出结果的容器。

execute_async方法立即返回一个job_id,这是一个标识符,用于追踪异步执行的推理任务。此时,推理任务已经在DPU上启动,但该方法不会阻塞调用线程等待任务完成。这允许CPU继续执行其他任务,而不必等待DPU完成推理。

dpu.wait(job_id),这行代码调用wait方法,并传入之前execute_async方法返回的job_id,以等待对应的推理任务完成。如果推理任务已经完成,wait方法将立即返回;如果推理任务尚未完成,wait方法将阻塞调用线程,直到任务完成。这确保了在继续进行任何依赖于推理结果的操作之前,推理任务已经成功完成。

  •  转化为一维向量
# 转化为一维向量,放入temp列表中,此时temp形状为(1,1,1000)
temp = [j.reshape(1, outputSize) for j in output_data]
  • 计算每个元素的指数
softmax = calculate_softmax(temp[0][0])
  • 计算最大值所在的index标签 
print("Classification: {}".format(predict_label(softmax)))
  • 显示图像 
if display:
  display_image = cv2.imread(os.path.join(image_folder, original_images[image_index]))
  _, ax = plt.subplots(1)
  _ = ax.imshow(cv2.cvtColor(display_image, cv2.COLOR_BGR2RGB))

_ = ax.imshow(cv2.cvtColor(display_image, cv2.COLOR_BGR2RGB))

# 短横线"_"用作一个变量名,临时变量,一种书写习惯

3. 全部代码展示

以下代码演示了使用PYNQ和DPU进行深度学习推理的全部过程,从图像预处理、数据加载、模型推理到结果展示,为图像分类任务提供了一个完整的流程:

import os
import time
import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline

from pynq_dpu import DpuOverlay
overlay = DpuOverlay("dpu.bit")

overlay.load_model("dpu_resnet50.xmodel")

_R_MEAN = 123.68
_G_MEAN = 116.78
_B_MEAN = 103.94

MEANS = [_B_MEAN,_G_MEAN,_R_MEAN]

def resize_shortest_edge(image, size):
    H, W = image.shape[:2]
    if H >= W:
        nW = size
        nH = int(float(H)/W * size)
    else:
        nH = size
        nW = int(float(W)/H * size)
    return cv2.resize(image,(nW,nH))

def mean_image_subtraction(image, means):
    B, G, R = cv2.split(image)
    B = B - means[0]
    G = G - means[1]
    R = R - means[2]
    image = cv2.merge([R, G, B])
    return image

def BGR2RGB(image):
    B, G, R = cv2.split(image)
    image = cv2.merge([R, G, B])
    return image

def central_crop(image, crop_height, crop_width):
    image_height = image.shape[0]
    image_width = image.shape[1]
    offset_height = (image_height - crop_height) // 2
    offset_width = (image_width - crop_width) // 2
    return image[offset_height:offset_height + crop_height, offset_width:
                 offset_width + crop_width, :]

def normalize(image):
    image=image/256.0
    image=image-0.5
    image=image*2
    return image

def preprocess_fn(image, crop_height = 224, crop_width = 224):
    image = resize_shortest_edge(image, 256)
    image = mean_image_subtraction(image, MEANS)
    image = central_crop(image, crop_height, crop_width)
    return image

def calculate_softmax(data):
    result = np.exp(data)
    return result

def predict_label(softmax):
    with open("img/words.txt", "r") as f:
        lines = f.readlines()
    return lines[np.argmax(softmax)-1]

image_folder = 'img'
original_images = [i for i in os.listdir(image_folder) if i.endswith("JPEG")]
total_images = len(original_images)

dpu = overlay.runner

inputTensors = dpu.get_input_tensors()
outputTensors = dpu.get_output_tensors()

shapeIn = tuple(inputTensors[0].dims)
shapeOut = tuple(outputTensors[0].dims)
outputSize = int(outputTensors[0].get_data_size() / shapeIn[0])

softmax = np.empty(outputSize)

output_data = [np.empty(shapeOut, dtype=np.float32, order="C")]
input_data = [np.empty(shapeIn, dtype=np.float32, order="C")]
image = input_data[0]

def run(image_index, display=False):
    preprocessed = preprocess_fn(cv2.imread(
        os.path.join(image_folder, original_images[image_index])))
    image[0,...] = preprocessed.reshape(shapeIn[1:])
    job_id = dpu.execute_async(input_data, output_data)
    dpu.wait(job_id)
    temp = [j.reshape(1, outputSize) for j in output_data]
    softmax = calculate_softmax(temp[0][0])
    if display:
        display_image = cv2.imread(os.path.join(
            image_folder, original_images[image_index]))
        _, ax = plt.subplots(1)
        _ = ax.imshow(cv2.cvtColor(display_image, cv2.COLOR_BGR2RGB))
        print("Classification: {}".format(predict_label(softmax)))

run(1, display=True)

代码的主要步骤如下:

  • 环境配置与模型加载:首先,导入所需的Python库,包括os、time、numpy、cv2(OpenCV库)、matplotlib(用于图像显示)等,并加载DPU叠加层和预训练的深度学习模型(dpu_resnet50.xmodel)。
  • 图像预处理:定义了几个预处理函数来准备图像数据以供模型使用。这些函数包括:
    1. resize_shortest_edge:调整图像大小,使得其最短边为指定的尺寸,同时保持原始的宽高比。
    2. mean_image_subtraction:执行均值减法,用于图像归一化,减去图像中每个通道的平均值。
    3. BGR2RGB:将图像从BGR格式转换为RGB格式,因为OpenCV默认读入图像为BGR格式,而大多数模型使用RGB。
    4. central_crop:从图像中心裁剪指定大小的区域。
    5. normalize:将图像数据归一化到[-1, 1]的范围内。
    6. preprocess_fn:将上述预处理步骤组合起来,为模型准备图像数据。
  • 模型预测:图像预处理后,使用DPU执行预测。首先,读取输入和输出张量的形状,准备好输入数据的容器。然后,对指定的图像进行预处理并将其加载到输入数据容器中。通过DPU执行异步推理,并等待结果。使用calculate_softmax函数计算输出数据的softmax,以获得每个类别的预测概率。
  • 结果展示:定义predict_label函数,它根据softmax预测结果,从一个包含类别标签的文件中选择并返回最可能的类别标签。如果display参数设为True,该函数还会显示原图像及其预测类别。
  • 执行预测:最后,选择一个图像文件并调用run函数来执行上述预测流程,并可选择是否显示图像及其分类标签。

4. 总结

在这个总结中,我们探讨了Resnet50,这是一个由50层构成的深度卷积神经网络,它在图像识别任务中表现出色。通过“残差学习”的创新设计,Resnet50解决了深度网络训练中的退化问题,使得网络能够通过增加更多的层来提高性能,而不会增加训练难度。我们还分析了如何在Xilinx Zynq平台上使用VART运行Resnet50模型的代码,包括模型加载、数据预处理、异步推理和结果分类。这个过程展示了如何利用Zynq芯片的强大功能,将深度学习应用于边缘计算,为各种行业,特别是高级驾驶辅助系统(ADAS)等应用,提供了新的可能性。这个例子不仅展示了深度学习在实际应用中的潜力,也突显了Zynq芯片在处理复杂计算任务时的高效性和灵活性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1889524.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学校教室NTP电子钟时间是如何同步北京时间的?-讯鹏时钟

在学校教室里,NTP 电子钟精准地显示着时间,与北京时间保持高度同步,为师生们提供了可靠的时间参考。那么,它是如何做到这一点的呢? NTP 电子钟能够与北京时间同步,主要依赖于网络时间协议(NTP&a…

准化 | 水系统碳中和标准体系初见成效

2024年5月31日,中华环保联合会发布《团体标准公告 2024年第10号(总第78号)》,批准发布了由中华环保联合会提出并归口的《废水处理温室气体监测技术规程》(T/ACEF 142-2024)、《工业水系统碳排放核算方法与报告指南》(T/ACEF143-20…

数据驱动:Facebook的广告策略与商业模式

在现代数字经济中,数据已经成为新的石油,驱动着企业的增长和创新。Facebook,作为全球最大的社交媒体平台之一,充分利用其庞大的用户数据和先进的算法技术,建立了一个高度精确和高效的广告生态系统。这不仅推动了平台自…

qtreewidget 美化,htmlcss和qss 不是一个概念!已解决

这种样式的美化, 能气死个人,css 一个单词搞定,非要 在qss中。多少个单词不知道了。 m_tree_widget->setStyleSheet("QTreeView{background:transparent; selection-background-color:transparent;}""QTreeView::branch{b…

PyTorch之nn.Module与nn.functional用法区别

文章目录 1. nn.Module2. nn.functional2.1 基本用法2.2 常用函数 3. nn.Module 与 nn.functional3.1 主要区别3.2 具体样例:nn.ReLU() 与 F.relu() 参考资料 1. nn.Module 在PyTorch中,nn.Module 类扮演着核心角色,它是构建任何自定义神经网…

这次发现的开源版本我愿意称之为最具学习价值的商城系统|商城源码点击进入

这是一款我发现的强大、灵活、易用的商城系统,成为我的的首选商城框架,让我的商城开发事半功倍!这款开源商城项目具有多元的商业模式满足了任何使用场景的需求。 有S2B2C供应链商城、B2B2C多商户商城、O2O外卖商城、B2C单商户商城、社区团购、…

全网最详细,零基础学会AI绘画Stable Diffusion,学不会来打我!

前言 什么是Stable Diffusion 自从去年10月份Stable Diffusion开源以来,仅过了半年的时间,如今它已经能够创作出精美细致的二次元插画,媲美真人的赛博Coser,以及具有独特风格的AI动画。 无论你只是感兴趣,还是想了解…

旅游管理系统-计算机毕业设计源码16021

摘 要 本文旨在设计和实现一个基于Spring Boot框架的旅游管理系统。该系统通过利用Spring Boot的快速开发特性和丰富的生态系统,提供了一个高效、可靠和灵活的解决方案。系统将实现旅游景点信息的管理、线路规划、跟团游玩、旅游攻略、酒店信息管理、订单管理和用户…

有哪些手持小风扇品牌推荐?五大手持小风扇诚意推荐!

在炎炎夏日,一款便携且高效的手持小风扇无疑是消暑的必备神器。为了帮助大家轻松应对酷暑,我们精心挑选了五大手持小风扇品牌进行诚意推荐。这些品牌不仅拥有出色的降温效果,更在外观设计、便携性、续航能力及操作便捷性上表现卓越。接下来&a…

第三方软件测试公司分享:软件渗透测试的测试内容和注意事项

软件渗透测试是一种通过模拟攻击的方式来评估软件系统的安全性和漏洞,以发现并修复系统中的安全弱点。保护用户的数据和信息不被恶意攻击者利用,也是软件产品开发流程中重要的环节,可以帮助开发团队完善产品质量,提高用户满意度。…

代码随想录-二叉搜索树①

目录 二叉搜索树的定义 700. 二叉搜索树中的搜索 题目描述: 输入输出示例: 思路和想法: 98. 验证二叉搜索树 题目描述: 输入输出示例: 思路和想法: 530. 二叉搜索树的最小绝对差 题目描述&#x…

03:Spring MVC

文章目录 一:Spring MVC简介1:说说自己对于Spring MVC的了解?1.1:流程说明: 一:Spring MVC简介 Spring MVC就是一个MVC框架,Spring MVC annotation式的开发比Struts2方便,可以直接代…

c/c++语言的一种日志的编写办法

今日分享一下,从某源码中看到这种日志编写方式,很强。可以借鉴。 这个函数调用的日志函数是不一样的,仔细观看: 这几种日志输出函数,背后都调用了相同的调用。 与之对应的区别就是,函数名称的差异取决于…

【云原生监控】Prometheus 普罗米修斯从搭建到使用详解

目录 一、前言 二、服务监控概述 2.1 什么是微服务监控 2.2 微服务监控指标 2.3 微服务监控工具 三、Prometheus概述 3.1 Prometheus是什么 3.2 Prometheus 特点 3.3 Prometheus 架构图 3.3.1 Prometheus核心组件 3.3.2 Prometheus 工作流程 3.4 Prometheus 应用场景…

【Python基础篇】一篇文章入门Python,进入Python的世界

文章目录 0.前言1.打印(Hello,World)2.创建变量3.打印升级3.1 打印一句话中间加变量3.2 sep设置分隔符3.3 end和换行 4. 注释 0.前言 大家好,我是小辰,前几天做了个重大的决定,学习python。 首先&#xff0…

wine烧录stm32教程

前言 使用环境 ubuntu22.04 因为stlnk的线太短了并且容易扯断开,想使用串口进行烧录,但是又不想每次烧录代码都拔下短接帽(暂时不知道stm32flash怎么支持ISP一键下载),故写下此教程步骤一:安装wine 首选我们要下载wine,由于国内下…

跨国企业与IP地址定位的商业策略

随着经济全球化的发展,许多企业都选择拓宽国际市场,而跨国企业需要在全球范围内进行高效的市场运营和管理,以应对不同市场的需求和竞争。IP地址定位技术能够通过识别用户的地理位置,为企业提供重要的数据支持,帮助他们…

记录搭建一台可域名访问的HTTPS服务器

一、背景 近期公司业务涉及到微信小程序,即将开发完成需要按照微信小程序平台的要求提供带证书的域名请求服务器。 资源背景介绍如下: 1、域名 公司已有一个二级域名,再次申请新的二级域名并且实现ICP备案不仅需要花重金重新购买,…

深入浅出:进程管理的艺术

目录 进程的定义 进程的特征 进程的状态 进程与程序的区别 进程的控制和管理 进程的特点 1. 虚拟内存空间的分配 2. 时间片轮转调度 图解: 进程段 数据段(Data Segment) 正文段(Text Segment) 堆栈段&…

十二、【源码】Spring整合AOP

源码地址:https://github.com/spring-projects/spring-framework 仓库地址:https://gitcode.net/qq_42665745/spring/-/tree/12-spring-aop Spring整合AOP 核心类: DefaultAdvisorAutoProxyCreator:用于在Spring框架中自动为符…