目录
1. 简介
2. 代码解析
3. 全部代码展示
4. 总结
1. 简介
Resnet50
一种深度卷积神经网络(CNN),它由50层构成。这种网络特别设计用于图像识别任务,并且在2015年的ImageNet大规模视觉识别挑战赛(ILSVRC)中取得了胜利。Resnet50的“残差学习”能力使得它可以通过添加更多的层来提高准确性,而不会导致训练难度增加或准确性下降。
这个网络的核心是“残差块”,它允许数据在网络的多个层之间直接传递,从而解决了深度网络训练中的“退化问题”。这种设计使得即使是非常深的网络也能有效地训练,并且随着网络深度的增加,性能也能得到提升。
2. 代码解析
- 硬件和模型加载
overlay = DpuOverlay("dpu.bit")
overlay.load_model("dpu_resnet50.xmodel")
- runner类,来自VART的方法
dpu = overlay.runner # runner类,来自VART的方法
inputTensors = dpu.get_input_tensors() # 返回是单个元素的列表
outputTensors = dpu.get_output_tensors() # 即[xir.Tensor]
- 获取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)
- 转化为一维向量
# 转化为一维向量,放入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. 全部代码展示
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)
4. 总结
在这个总结中,我们探讨了Resnet50,这是一个由50层构成的深度卷积神经网络,它在图像识别任务中表现出色。通过“残差学习”的创新设计,Resnet50解决了深度网络训练中的退化问题,使得网络能够通过增加更多的层来提高性能,而不会增加训练难度。我们还分析了如何在Xilinx Zynq平台上使用VART运行Resnet50模型的代码,包括模型加载、数据预处理、异步推理和结果分类。这个过程展示了如何利用Zynq芯片的强大功能,将深度学习应用于边缘计算,为各种行业,特别是高级驾驶辅助系统(ADAS)等应用,提供了新的可能性。这个例子不仅展示了深度学习在实际应用中的潜力,也突显了Zynq芯片在处理复杂计算任务时的高效性和灵活性。