上篇文章记录了基于yolov5进行模型训练,本篇文章记录调用zed2基于yolov5模型进行图像实时推理。
开发板:Jetson Xviewer NX
摄像头: zed2
yolo版本:yolov5-5.0
系统:Ubuntu18.04
此篇文章主要基于yolov5-5.0版本上改写,源码地址:
yolov5 GitHub 地址: GitHub: https://github.com/ultralytics/yolov5/tree/v5.0
首先我们对检测代码封装成一个类,代码如下:
# -*- coding: utf-8 -*
import time
import numpy as np
import torch
from models.experimental import attempt_load
from utils.datasets import letterbox
from utils.general import non_max_suppression,scale_coords, plot_one_box
from utils.torch_utils import select_device,time_synchronized
from numpy import random
class Detector:
def __init__(self):
self.img_size = 640 #确保输入图片的尺寸能整除stride=32
# self.stride =int(model.stride.max()) #检测模型时yolov5也用了FPN里面的一个思路,将卷积神经网络中最后三层通过上采样的方式进行了一个堆叠的,要求图片的分辨率为32的一个整数倍
# self.img_size = check_img_size(self.img_size, s=self.stride) #检测图片尺寸img_size是否可以被32整除,如果不能,则改变你输入的img_size为向上取32的倍数的分辨率
self.threshold = 0.6 #置信度
self.hide_labels = False #是否隐藏标签,False:不隐藏,显示标签
self.hide_conf = False #是否隐藏置信度
self.weights = 'weights/yolov5s.pt' #加载权重文件
# self.other_weights = other_weights #增加别的权重文件进行检测
#self.device = '0' if torch.cuda.is_available() else 'cpu'
self.device = '' #使用的设备类型cpu or cuda,默认为空
self.device = select_device(self.device) #获取CPU 或 CUDA
#yolov5s
model = attempt_load(self.weights, map_location=self.device) #载入权重文件
model.to(self.device).eval() #模型转移到指定的设备上,推理阶段使用model.eval() 训练阶段使用model.train()
model.half() # GPU支持半精度, 如果使用cpu,不支持.half,改为.float()
self.m = model
self.names = model.module.names if hasattr(model, 'module') else model.names #模型能够检测的所有类别标签
self.colors = [[random.randint(0, 255) for _ in range(3)] for _ in self.names] #检测框颜色值,从0-225随机选择3个数
# #other_weights
# other_model = attempt_load(self.other_weights,map_location=self.device)
# other_model.to(self.device).eval()
# other_model.half()
# self.om = other_model
# self.other_names = other_model.module.names if hasattr(other_model, 'module') else other_model.names
# self.other_colors = [[random.randint(0, 255) for _ in range(3)] for _ in self.other_names]
def detect(self,im):
#如果图像是None,退出程序
if im is None:
exit(1)
else:
im0 = im.copy() #拷贝原图
# t0时刻开始推理
t0 = time.time() #图像预处理,[1080,1920,3]->[384,640,3]
img = letterbox(im, new_shape=self.img_size)[0]
img = img[:, :, ::-1].transpose(2, 0, 1) # [384,640,3] -> [3,384,640]
img = np.ascontiguousarray(img) #在内存上使用连续的内存存储图像
img = torch.from_numpy(img).to(self.device) #由numpy array创建torch Tensor; transfer to device
img = img.half() ## 半精度,如果使用cpu,则改成img.float()
img /= 255.0 # 图像归一化
if img.ndimension() == 3:
img = img.unsqueeze(0) ## [3,384,640] -> [1,3,384,640]
t1 = time.time()
pred = self.m(img, augment=False)[0] #模型推理出的结果
pred = pred.float()
pred = non_max_suppression(pred, self.threshold, 0.4) #非极大抑制值,返回值为过滤后的预测框
##other_weights
# other_pred = self.om(img, augment=False)[0]
# other_pred = comm_pred.float()
# other_pred = non_max_suppression(other_pred, self.threshold, 0.4)
t2 = time_synchronized()
boxes = [] #初始化返回结果
#yolo5s
for det in pred:
if det is not None and len(det): #如果有框
# Rescale boxes from img_size to im0 size,将预测信息映射到原图,即将标注的bounding_box大小调整为和原图一致,