yolo-inference多后端+多任务+多算法+多精度模型 框架开发记录(python版)

先贴出github地址,欢迎大家批评指正:https://github.com/taifyang/yolo-inference
不知不觉LZ已经快工作两年了,由于之前的工作内容主要和模型部署相关,想着利用闲暇时间写一些推理方面的经验总结,于是有了这个工程。其实本来也是自己写了玩的,不过已经陆续迭代半年多了,期间也通过借签优秀代码吸收了经验,索性总结一下心得~

1.0 初始版本
1.1 支持多精度模型
1.2 支持tensorrt的cuda前后处理
1.3 支持onnxruntime的int8推理
1.4 onnxruntime推理代码采用cpp风格接口
1.5 采用抽象工厂和单例模式重构代码
1.6 增加cmake编译支持和重构python代码
1.7 增加Linux系统编译支持
2.0 增加yolov8检测器支持
2.1 增加cmake条件编译选项和自动化测试脚本
3.0 增加分类和分割算法支持
3.1 重构代码结构和缺陷修复

初始版本的接口类定义如下:

import cv2
import numpy as np
from enum import Enum
from abc import ABC, abstractclassmethod...class Device_Type(Enum):CPU = 0GPU = 1class YOLOv5(ABC):def infer(self, image_path:str) -> None:self.image = cv2.imread(image_path)self.result = self.image.copy()self.pre_process()self.process()self.post_process()cv2.imwrite("result.jpg", self.result)cv2.imshow("result", self.result)cv2.waitKey(0)@abstractclassmethoddef pre_process(self) -> None:pass@abstractclassmethoddef process(self) -> None:pass    @abstractclassmethoddef post_process(self) -> None:pass

子类如YOLOv5_ONNXRuntime继承上述类:

import onnxruntime
from yolov5 import *
from utils import *class YOLOv5_ONNXRuntime(YOLOv5):def __init__(self, model_path:str, device_type:Device_Type) -> None:super().__init__()if device_type == Device_Type.CPU:self.onnx_session = onnxruntime.InferenceSession(model_path, providers=['CPUExecutionProvider'])if device_type == Device_Type.GPU:self.onnx_session = onnxruntime.InferenceSession(model_path, providers=['CUDAExecutionProvider'])self.input_name = []for node in self.onnx_session.get_inputs():self.input_name.append(node.name)self.output_name = []for node in self.onnx_session.get_outputs():self.output_name.append(node.name)self.inputs = {}def pre_process(self) -> None:input = letterbox(self.image, input_shape)input = input[:, :, ::-1].transpose(2, 0, 1).astype(dtype=np.float32)  #BGR2RGB和HWC2CHWinput = input / 255.0input = np.expand_dims(input, axis=0)for name in self.input_name:self.inputs[name] = inputdef process(self) -> None:self.outputs = self.onnx_session.run(None, self.inputs)def post_process(self) -> None:self.outputs = np.squeeze(self.outputs)self.outputs = self.outputs[self.outputs[..., 4] > confidence_threshold]classes_scores = self.outputs[..., 5:]     boxes = []scores = []class_ids = []for i in range(len(classes_scores)):class_id = np.argmax(classes_scores[i])self.outputs[i][4] *= classes_scores[i][class_id]self.outputs[i][5] = class_idif self.outputs[i][4] > score_threshold:boxes.append(self.outputs[i][:6])scores.append(self.outputs[i][4])class_ids.append(self.outputs[i][5])               boxes = np.array(boxes)boxes = xywh2xyxy(boxes)scores = np.array(scores)indices = nms(boxes, scores, score_threshold, nms_threshold) boxes = boxes[indices]draw(self.result, boxes)

调用demo如下:

from yolov5_onnxruntime import *yolov5 = YOLOv5_ONNXRuntime(model_path="yolov5n.onnx", device_type=Device_Type.CPU)
yolov5.infer("bus.jpg")

后续支持其他功能后调用demo增加了parse_args解析命令参数,通过importlib导入相应模块,并通过getattr通过类名获取类(反射机制),具体内容如下:

import argparse
import importlib
from yolov5 import *def parse_args():parser = argparse.ArgumentParser('yolov5')parser.add_argument('--algo_type', default='ONNXRuntime', type=str, help='ONNXRuntime, OpenCV, OpenVINO, TensorRT')parser.add_argument('--model_path', default='yolov5n_fp32.onnx', type=str, help='the path of model')parser.add_argument('--device_type',  default='cpu', type=str, help='cpu, gpu')parser.add_argument('--model_type',  default='fp32', type=str, help='fp32, fp16, int8')return parser.parse_args()if __name__ == '__main__':args = parse_args()algo_type = args.algo_typealgo = importlib.import_module('yolov5_' + algo_type.lower()) YOLOv5 = getattr(algo, 'YOLOv5_' + algo_type)model_path = args.model_pathif args.device_type == 'cpu':device_type = Device_Type.CPUelif args.device_type == 'gpu':device_type = Device_Type.GPUif args.model_type == 'fp32':model_type = Model_Type.FP32elif args.model_type == 'fp16':model_type = Model_Type.FP16elif args.model_type == 'int8':model_type = Model_Type.INT8yolov5 = YOLOv5(model_path, device_type, model_type)yolov5.infer("test.mp4")

在3.0版本中由于增加了对分类和分割算法的支持,以onnxruntime框架为例具体实现类如下:

import onnxruntime
from yolo import *
from utils import *class YOLO_ONNXRuntime(YOLO):def __init__(self, algo_type:Algo_Type, device_type:Device_Type, model_type:Model_Type, model_path:str) -> None:super().__init__()assert os.path.exists(model_path), "model not exists!"if device_type == Device_Type.CPU:self.onnx_session = onnxruntime.InferenceSession(model_path, providers=['CPUExecutionProvider'])elif device_type == Device_Type.GPU:self.onnx_session = onnxruntime.InferenceSession(model_path, providers=['CUDAExecutionProvider'])self.algo_type = algo_typeself.model_type = model_typeself.input_name = []for node in self.onnx_session.get_inputs(): self.input_name.append(node.name)self.output_name = []for node in self.onnx_session.get_outputs():self.output_name.append(node.name)self.input = {}@abstractclassmethod       def pre_process(self) -> None:passdef process(self) -> None:self.output = self.onnx_session.run(None, self.input)@abstractclassmethod         def post_process(self) -> None:passclass YOLO_ONNXRuntime_Classification(YOLO_ONNXRuntime):           def pre_process(self) -> None:if self.algo_type == Algo_Type.YOLOv5:crop_size = min(self.image.shape[0], self.image.shape[1])left = (self.image.shape[1] - crop_size) // 2top = (self.image.shape[0] - crop_size) // 2crop_image = self.image[top:(top+crop_size), left:(left+crop_size), ...]input = cv2.resize(crop_image, self.input_shape)input = input / 255.0input = input - np.array([0.406, 0.456, 0.485])input = input / np.array([0.225, 0.224, 0.229])if self.algo_type == Algo_Type.YOLOv8:self.input_shape = (224, 224)if self.image.shape[1] > self.image.shape[0]:self.image = cv2.resize(self.image, (self.input_shape[0]*self.image.shape[1]//self.image.shape[0], self.input_shape[0]))else:self.image = cv2.resize(self.image, (self.input_shape[1], self.input_shape[1]*self.image.shape[0]//self.image.shape[1]))crop_size = min(self.image.shape[0], self.image.shape[1])left = (self.image.shape[1] - crop_size) // 2top = (self.image.shape[0] - crop_size) // 2crop_image = self.image[top:(top+crop_size), left:(left+crop_size), ...]input = cv2.resize(crop_image, self.input_shape)input = input / 255.0input = input[:, :, ::-1].transpose(2, 0, 1)  #BGR2RGB和HWC2CHWif self.model_type == Model_Type.FP32 or self.model_type == Model_Type.INT8:input = np.expand_dims(input, axis=0).astype(dtype=np.float32)elif self.model_type == Model_Type.FP16:input = np.expand_dims(input, axis=0).astype(dtype=np.float16)for name in self.input_name:self.input[name] = inputdef post_process(self) -> None:output = np.squeeze(self.output).astype(dtype=np.float32)if self.algo_type == Algo_Type.YOLOv5:print("class:", np.argmax(output), " scores:", np.exp(np.max(output))/np.sum(np.exp(output)))if self.algo_type == Algo_Type.YOLOv8:print("class:", np.argmax(output), " scores:", np.max(output))class YOLO_ONNXRuntime_Detection(YOLO_ONNXRuntime):def pre_process(self) -> None:input = letterbox(self.image, self.input_shape)input = input[:, :, ::-1].transpose(2, 0, 1)  #BGR2RGB和HWC2CHWinput = input / 255.0if self.model_type == Model_Type.FP32 or self.model_type == Model_Type.INT8:input = np.expand_dims(input, axis=0).astype(dtype=np.float32)elif self.model_type == Model_Type.FP16:input = np.expand_dims(input, axis=0).astype(dtype=np.float16)for name in self.input_name:self.input[name] = inputdef post_process(self) -> None:output = np.squeeze(self.output[0]).astype(dtype=np.float32)boxes = []scores = []class_ids = []if self.algo_type == Algo_Type.YOLOv5:output = output[output[..., 4] > self.confidence_threshold]classes_scores = output[..., 5:85]     for i in range(output.shape[0]):class_id = np.argmax(classes_scores[i])obj_score = output[i][4]cls_score = classes_scores[i][class_id]output[i][4] = obj_score * cls_scoreoutput[i][5] = class_idif output[i][4] > self.score_threshold:boxes.append(output[i][:6])scores.append(output[i][4])class_ids.append(output[i][5])   output[i][5:] *= obj_scoreif self.algo_type == Algo_Type.YOLOv8: for i in range(output.shape[0]):classes_scores = output[..., 4:]     class_id = np.argmax(classes_scores[i])output[i][4] = classes_scores[i][class_id]output[i][5] = class_idif output[i][4] > self.score_threshold:boxes.append(output[i, :6])scores.append(output[i][4])class_ids.append(output[i][5])                  boxes = np.array(boxes)boxes = xywh2xyxy(boxes)scores = np.array(scores)indices = nms(boxes, scores, self.score_threshold, self.nms_threshold) boxes = boxes[indices]self.result = draw(self.image, boxes)class YOLO_ONNXRuntime_Segmentation(YOLO_ONNXRuntime):def pre_process(self) -> None:input = letterbox(self.image, self.input_shape)input = input[:, :, ::-1].transpose(2, 0, 1)  #BGR2RGB和HWC2CHWinput = input / 255.0if self.model_type == Model_Type.FP32 or self.model_type == Model_Type.INT8:input = np.expand_dims(input, axis=0).astype(dtype=np.float32)elif self.model_type == Model_Type.FP16:input = np.expand_dims(input, axis=0).astype(dtype=np.float16)for name in self.input_name:self.input[name] = inputdef post_process(self) -> None:output = np.squeeze(self.output[0]).astype(dtype=np.float32)boxes = []scores = []class_ids = []preds = []if self.algo_type == Algo_Type.YOLOv5:output = output[output[..., 4] > self.confidence_threshold]classes_scores = output[..., 5:85]     for i in range(output.shape[0]):class_id = np.argmax(classes_scores[i])obj_score = output[i][4]cls_score = classes_scores[i][class_id]output[i][4] = obj_score * cls_scoreoutput[i][5] = class_idif output[i][4] > self.score_threshold:boxes.append(output[i][:6])scores.append(output[i][4])class_ids.append(output[i][5])   output[i][5:] *= obj_scorepreds.append(output[i])if self.algo_type == Algo_Type.YOLOv8: for i in range(output.shape[0]):classes_scores = output[..., 4:84]     class_id = np.argmax(classes_scores[i])output[i][4] = classes_scores[i][class_id]output[i][5] = class_idif output[i][4] > self.score_threshold:boxes.append(output[i, :6])scores.append(output[i][4])class_ids.append(output[i][5])    preds.append(output[i])           boxes = np.array(boxes)boxes = xywh2xyxy(boxes)scores = np.array(scores)indices = nms(boxes, scores, self.score_threshold, self.nms_threshold) boxes = boxes[indices]masks_in = np.array(preds)[indices][..., -32:]proto= np.squeeze(self.output[1]).astype(dtype=np.float32)c, mh, mw = proto.shape masks = (1/ (1 + np.exp(-masks_in @ proto.reshape(c, -1)))).reshape(-1, mh, mw)downsampled_bboxes = boxes.copy()downsampled_bboxes[:, 0] *= mw / self.input_shape[0]downsampled_bboxes[:, 2] *= mw / self.input_shape[0]downsampled_bboxes[:, 3] *= mh / self.input_shape[1]downsampled_bboxes[:, 1] *= mh / self.input_shape[1]masks = crop_mask(masks, downsampled_bboxes)self.result = draw(self.image, boxes, masks)

即YOLO基类派生出YOLO_ONNXRuntime等类,再由YOLO_ONNXRuntime类派生一系列具体算法实现子类。由于功能的扩充,此时调用方法变得比较臃肿:

import argparse
import importlib
from yolo import *def parse_args():parser = argparse.ArgumentParser('yolo_inference')parser.add_argument('--algo_type', default='YOLOv8', type=str, help='YOLOv5, YOLOv8')parser.add_argument('--backend_type', default='TensorRT', type=str, help='ONNXRuntime, OpenCV, OpenVINO, TensorRT')parser.add_argument('--task_type', default='Segmentation', type=str, help='Classification, Detection, Segmentation')parser.add_argument('--device_type',  default='GPU', type=str, help='CPU, GPU')parser.add_argument('--model_type',  default='FP32', type=str, help='FP32, FP16, INT8')parser.add_argument('--model_path', default='yolov8n_seg_fp32.engine', type=str, help='the path of model')parser.add_argument('--input_path', default="bus.jpg", type=str, help='save result')parser.add_argument('--output_path', default="", type=str, help='save result')parser.add_argument('--show_result', default=False, type=bool, help='show result')parser.add_argument('--save_result', default=True, type=bool, help='save result')return parser.parse_args()if __name__ == '__main__':args = parse_args()backend_type = args.backend_typebackend = importlib.import_module('yolo_' + backend_type.lower()) yolo = getattr(backend, 'YOLO_' + backend_type + '_' + args.task_type)model_path = args.model_pathif args.algo_type == 'YOLOv5':algo_type = Algo_Type.YOLOv5if args.algo_type == 'YOLOv8':algo_type = Algo_Type.YOLOv8if args.task_type == 'Classification':task_type = Task_Type.Classificationif args.task_type == 'Detection':task_type = Task_Type.Detectionif args.task_type == 'Segmentation':task_type = Task_Type.Segmentation  if args.device_type == 'CPU':device_type = Device_Type.CPUif args.device_type == 'GPU':device_type = Device_Type.GPUif args.model_type == 'FP32':model_type = Model_Type.FP32if args.model_type == 'FP16':model_type = Model_Type.FP16if args.model_type == 'INT8':model_type = Model_Type.INT8show_result = args.show_result and (task_type == Task_Type.Detection or task_type == Task_Type.Segmentation)save_result = args.save_result and (task_type == Task_Type.Detection or task_type == Task_Type.Segmentation)args.output_path = "./result/"+str(args.algo_type)+"_"+str(args.backend_type)+"_"+str(args.task_type)+"_"+str(args.device_type)+"_"+str(args.model_type)+".jpg"yolo = yolo(algo_type, device_type, model_type, model_path)yolo.infer(args.input_path, args.output_path, show_result, save_result)

3.1版本中,借签了https://github.com/ultralytics/ultralytics的做法,项目层级划分如下:
在这里插入图片描述
即将不同推理后端封装入算法包,此时yolo.py内容如下:

import os
import cv2
import time
from enum import Enum
import backendsclass YOLO:  def __init__(self) -> None:super().__init__()self.score_threshold = 0.2self.nms_threshold = 0.5self.confidence_threshold = 0.2  self.input_shape = (640, 640) def task_map(self):return {'ONNXRuntime':{'Classify':backends.ONNXRuntime.YOLO_ONNXRuntime_Classify,'Detect':backends.ONNXRuntime.YOLO_ONNXRuntime_Detect,'Segment':backends.ONNXRuntime.YOLO_ONNXRuntime_Segment,},'OpenCV':{'Classify':backends.OpenCV.YOLO_OpenCV_Classify,'Detect':backends.OpenCV.YOLO_OpenCV_Detect,#'Segment':tasks.OpenCV.YOLO_OpenCV_Segment,},'OpenVINO':{'Classify':backends.OpenVINO.YOLO_OpenVINO_Classify,'Detect':backends.OpenVINO.YOLO_OpenVINO_Detect,'Segment':backends.OpenVINO.YOLO_OpenVINO_Segment,},'TensorRT':{'Classify':backends.TensorRT.YOLO_TensorRT_Classify,'Detect':backends.TensorRT.YOLO_TensorRT_Detect,'Segment':backends.TensorRT.YOLO_TensorRT_Segment,},}def infer(self, input_path:str, output_path:str, show_result:bool, save_result:bool) -> None:assert os.path.exists(input_path), 'input not exists!'if input_path.endswith('.bmp') or input_path.endswith('.jpg') or input_path.endswith('.png'):self.image = cv2.imread(input_path)self.pre_process()self.process()self.post_process()if save_result and output_path!='':cv2.imwrite(output_path, self.result)if show_result:cv2.imshow('result', self.result)cv2.waitKey(0)elif input_path.endswith('.mp4'):cap = cv2.VideoCapture(input_path)start = time.time()if save_result and output_path!='':fourcc = cv2.VideoWriter_fourcc(*'XVID')wri = cv2.VideoWriter(output_path, fourcc, 30.0, (1280,720))while True:ret, self.image  = cap.read()if not ret:breakself.result = self.image.copy()self.pre_process()self.process()self.post_process()if show_result:cv2.imshow('result', self.result)cv2.waitKey(1)if save_result and output_path!='':wri.write(self.result)end = time.time()print((end-start)*1000, 'ms')                  

即通过task_map接口返回具体算法类的实现。其同级的__init__.py文件内容如下:

from backends import ONNXRuntime, OpenCV, OpenVINO, TensorRT__all__ = 'ONNXRuntime', 'OpenCV', 'OpenVINO', 'TensorRT'

用来初始化ONNXRuntime,OpenCV,OpenVINO,TensorRT四个package。ONNXRuntime文件夹下的yolo_onnxruntime.py内容为:

import onnxruntime
from backends.yolo import *
from backends.utils import *class YOLO_ONNXRuntime(YOLO):def __init__(self, algo_type:str, device_type:str, model_type:str, model_path:str) -> None:super().__init__()assert os.path.exists(model_path), "model not exists!"if device_type == 'CPU':self.onnx_session = onnxruntime.InferenceSession(model_path, providers=['CPUExecutionProvider'])elif device_type == 'GPU':self.onnx_session = onnxruntime.InferenceSession(model_path, providers=['CUDAExecutionProvider'])self.algo_type = algo_typeself.model_type = model_typeself.input_name = []for node in self.onnx_session.get_inputs(): self.input_name.append(node.name)self.output_name = []for node in self.onnx_session.get_outputs():self.output_name.append(node.name)self.input = {}def process(self) -> None:self.output = self.onnx_session.run(None, self.input)class YOLO_ONNXRuntime_Classify(YOLO_ONNXRuntime):           def pre_process(self) -> None:if self.algo_type == 'YOLOv5':crop_size = min(self.image.shape[0], self.image.shape[1])left = (self.image.shape[1] - crop_size) // 2top = (self.image.shape[0] - crop_size) // 2crop_image = self.image[top:(top+crop_size), left:(left+crop_size), ...]input = cv2.resize(crop_image, self.input_shape)input = input / 255.0input = input - np.array([0.406, 0.456, 0.485])input = input / np.array([0.225, 0.224, 0.229])if self.algo_type == 'YOLOv8':self.input_shape = (224, 224)if self.image.shape[1] > self.image.shape[0]:self.image = cv2.resize(self.image, (self.input_shape[0]*self.image.shape[1]//self.image.shape[0], self.input_shape[0]))else:self.image = cv2.resize(self.image, (self.input_shape[1], self.input_shape[1]*self.image.shape[0]//self.image.shape[1]))crop_size = min(self.image.shape[0], self.image.shape[1])left = (self.image.shape[1] - crop_size) // 2top = (self.image.shape[0] - crop_size) // 2crop_image = self.image[top:(top+crop_size), left:(left+crop_size), ...]input = cv2.resize(crop_image, self.input_shape)input = input / 255.0input = input[:, :, ::-1].transpose(2, 0, 1)  #BGR2RGB和HWC2CHWif self.model_type == 'FP32' or self.model_type == 'INT8':input = np.expand_dims(input, axis=0).astype(dtype=np.float32)elif self.model_type == 'FP16':input = np.expand_dims(input, axis=0).astype(dtype=np.float16)for name in self.input_name:self.input[name] = inputdef post_process(self) -> None:output = np.squeeze(self.output).astype(dtype=np.float32)if self.algo_type == 'YOLOv5':print("class:", np.argmax(output), " scores:", np.exp(np.max(output))/np.sum(np.exp(output)))if self.algo_type == 'YOLOv8':print("class:", np.argmax(output), " scores:", np.max(output))class YOLO_ONNXRuntime_Detect(YOLO_ONNXRuntime):def pre_process(self) -> None:input = letterbox(self.image, self.input_shape)input = input[:, :, ::-1].transpose(2, 0, 1)  #BGR2RGB和HWC2CHWinput = input / 255.0if self.model_type == 'FP32' or self.model_type == 'INT8':input = np.expand_dims(input, axis=0).astype(dtype=np.float32)elif self.model_type == 'FP16':input = np.expand_dims(input, axis=0).astype(dtype=np.float16)for name in self.input_name:self.input[name] = inputdef post_process(self) -> None:output = np.squeeze(self.output[0]).astype(dtype=np.float32)boxes = []scores = []class_ids = []if self.algo_type == 'YOLOv5':output = output[output[..., 4] > self.confidence_threshold]classes_scores = output[..., 5:85]     for i in range(output.shape[0]):class_id = np.argmax(classes_scores[i])obj_score = output[i][4]cls_score = classes_scores[i][class_id]output[i][4] = obj_score * cls_scoreoutput[i][5] = class_idif output[i][4] > self.score_threshold:boxes.append(output[i][:6])scores.append(output[i][4])class_ids.append(output[i][5])   output[i][5:] *= obj_scoreif self.algo_type == 'YOLOv8': for i in range(output.shape[0]):classes_scores = output[..., 4:]     class_id = np.argmax(classes_scores[i])output[i][4] = classes_scores[i][class_id]output[i][5] = class_idif output[i][4] > self.score_threshold:boxes.append(output[i, :6])scores.append(output[i][4])class_ids.append(output[i][5])                  boxes = np.array(boxes)boxes = xywh2xyxy(boxes)scores = np.array(scores)indices = nms(boxes, scores, self.score_threshold, self.nms_threshold) boxes = boxes[indices]self.result = draw(self.image, boxes)class YOLO_ONNXRuntime_Segment(YOLO_ONNXRuntime):def pre_process(self) -> None:input = letterbox(self.image, self.input_shape)input = input[:, :, ::-1].transpose(2, 0, 1)  #BGR2RGB和HWC2CHWinput = input / 255.0if self.model_type == 'FP32' or self.model_type == 'INT8':input = np.expand_dims(input, axis=0).astype(dtype=np.float32)elif self.model_type == 'FP16':input = np.expand_dims(input, axis=0).astype(dtype=np.float16)for name in self.input_name:self.input[name] = inputdef post_process(self) -> None:output = np.squeeze(self.output[0]).astype(dtype=np.float32)boxes = []scores = []class_ids = []preds = []if self.algo_type == 'YOLOv5':output = output[output[..., 4] > self.confidence_threshold]classes_scores = output[..., 5:85]     for i in range(output.shape[0]):class_id = np.argmax(classes_scores[i])obj_score = output[i][4]cls_score = classes_scores[i][class_id]output[i][4] = obj_score * cls_scoreoutput[i][5] = class_idif output[i][4] > self.score_threshold:boxes.append(output[i][:6])scores.append(output[i][4])class_ids.append(output[i][5])   output[i][5:] *= obj_scorepreds.append(output[i])if self.algo_type == 'YOLOv8': for i in range(output.shape[0]):classes_scores = output[..., 4:84]     class_id = np.argmax(classes_scores[i])output[i][4] = classes_scores[i][class_id]output[i][5] = class_idif output[i][4] > self.score_threshold:boxes.append(output[i, :6])scores.append(output[i][4])class_ids.append(output[i][5])    preds.append(output[i])           boxes = np.array(boxes)boxes = xywh2xyxy(boxes)scores = np.array(scores)indices = nms(boxes, scores, self.score_threshold, self.nms_threshold) boxes = boxes[indices]masks_in = np.array(preds)[indices][..., -32:]proto= np.squeeze(self.output[1]).astype(dtype=np.float32)c, mh, mw = proto.shape masks = (1/ (1 + np.exp(-masks_in @ proto.reshape(c, -1)))).reshape(-1, mh, mw)downsampled_bboxes = boxes.copy()downsampled_bboxes[:, 0] *= mw / self.input_shape[0]downsampled_bboxes[:, 2] *= mw / self.input_shape[0]downsampled_bboxes[:, 3] *= mh / self.input_shape[1]downsampled_bboxes[:, 1] *= mh / self.input_shape[1]masks = crop_mask(masks, downsampled_bboxes)self.result = draw(self.image, boxes, masks)

init.py文件内容为:

from backends.ONNXRuntime.yolo_onnxruntime import YOLO_ONNXRuntime_Classify, YOLO_ONNXRuntime_Detect, YOLO_ONNXRuntime_Segment__all__ = "YOLO_ONNXRuntime_Classify", "YOLO_ONNXRuntime_Detect", "YOLO_ONNXRuntime_Segment",

来初始化具体算法实现子类。

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

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

相关文章

边缘计算网关在智慧厕所远程监测与管理的应用

随着智慧城市建设的不断深入,城市公共设施的智慧化管理成为了提升城市品质和居民生活质量的关键建设。公厕作为城市基础设施的重要组成部分,其管理效率和卫生状况直接影响着市民的日常生活体验。在公厕设施建设背景下,边缘计算网关技术的应用…

【JS重点09】JS闭包(面试重点)

本文核心目标:阅读完本文能说出什么是闭包,闭包作用以及如何利用闭包 一:闭包概览 1 闭包是什么 闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境&#xff09…

如何将接口返回/n替换为react.js中的换行符

将每个/n替换为ReactJS中的一个<br>标记。cpa_ability为后端返回的字段名

时间类:Calendar

一.Calendar概述 1.Calendar代表了系统当前时间的日历对象,可以单独修改,获取时间中的年&#xff0c;月&#xff0c;日 2.细节:Calendar是一个抽象类,不能直接创建对象。 二.获取Calendar日历类对象的方法 // 会根据系统的不同时区来获取不同的日历对象 // 会根据系统的不同…

6.每日LeetCode-数组类,找到所有数组中消失的数字(Go)

题目 448找到所有数组中消失的数字.go 给你一个含 n 个整数的数组 nums &#xff0c;其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字&#xff0c;并以数组的形式返回结果。 示例 1&#xff1a; 输入&#xff1a;nums [4,3,2,7,8,2,…

双喜临门 | 两大权威报告发布,开源网安实力登榜

近日&#xff0c;开源网安凭借出色表现和实力&#xff0c;荣获两大荣誉&#xff1a;入选《中国信息安全》杂志社联合数说安全发布的《2024 年中国金融行业网络安全市场全景图》&#xff0c;并登榜安在发布的《2024安在新榜网络安全产品“大众点评”百强榜》。 2024年中国金融行…

Java开发规范

1.接口命名规范–Restful API 原本格式是动词资源by传参&#xff0c;后来进化为Restful API&#xff0c;思想是以资源为中心。 动词用get,post,put,delete请求方法代替&#xff0c;by后面的名词用传参代替。 并且GET方法传参资源ID采用路径传参&#xff0c;除了资源ID外的GET…

【智能算法应用】基于A星算法求解六边形栅格地图路径规划

目录 1.算法原理2.结果展示3.参考文献4.代码获取 1.算法原理 精准导航&#xff1a;用A*算法优化栅格地图的路径规划【附Matlab代码】 六边形栅格地图 分析一下地图&#xff1a; 六边形栅格地图上移动可以看做6领域运动&#xff0c;偶数列与奇数列移动方式有所差异&#xff0…

使用 Elasticsearch 调用 OpenAI 函数

作者&#xff1a;来自 Elastic Ashish Tiwari 介绍 OpenAI 中的函数调用是指 AI 模型与外部函数或 API 交互的能力&#xff0c;使它们能够执行文本生成之外的任务。此功能使模型能够通过调用预定义函数来执行代码、从数据库检索信息、与外部服务交互等。 该模型根据用户提示智…

连接·共享·成长:15大顶尖峰会热议AI,逾万商家聚焦实在Agent

在数字化浪潮的推动下&#xff0c;人工智能&#xff08;AI&#xff09;和机器人流程自动化&#xff08;RPA&#xff09;正成为行业创新和效率提升的强大引擎。作为自动化领域的领航者&#xff0c;实在智能不仅在AI技术革新上保持领先地位&#xff0c;更通过一系列行业活动&…

[13] CUDA_Opencv联合编译过程

CUDA_Opencv联合编译过程 详细编译过程可见我之前的文章&#xff1a;Win10下OpencvCUDA联合编译详细教程&#xff08;版本455、460、470,亲测可用&#xff01;&#xff01;&#xff01;&#xff09;本文给出Windows\linux下的opencvcuda的编译总结&#xff0c;摘自 <基于GP…

[面试题]Java【虚拟机】

[面试题]Java【基础】[面试题]Java【虚拟机】 因为 Java 并发涉及到的内容会非常多&#xff0c;本面试题可能很难覆盖到所有的知识点&#xff0c;所以推荐 《深入拆解 Java 虚拟机》 。 走近 Java 什么是虚拟机&#xff1f; Java 虚拟机&#xff0c;是一个可以执行 Java 字…

Pygame的基本应用

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 Pygame有很多模块&#xff0c;每个模块又有很多方法&#xff0c;在此不能够逐一讲解&#xff0c;所以&#xff0c;我们通过一个实例来学习Pygame&…

SpringBoot接入RS-232串口通讯实现数据交互

目录 一、什么是RS-232&#xff1f; 先看看硬件通讯接口长啥样 RS-232 二、方案一 1.前期准备 a.配置 RXTX 1&#xff09;下载 RXTX 包并解压 2&#xff09;拷贝动态库到对应的jdk目录下 Windows平台 Linux平台 3&#xff09;在工程根目录下创建 lib 文件夹&#x…

Whisper语音识别 -- 自回归解码分析

前言 Whisper 是由 OpenAI 开发的一种先进语音识别系统。它采用深度学习技术&#xff0c;能够高效、准确地将语音转换为文本。Whisper 支持多种语言和口音&#xff0c;并且在处理背景噪音和语音变异方面表现出色。其广泛应用于语音助手、翻译服务、字幕生成等领域&#xff0c;为…

unidbg讲解V1

前言 unidbg是什么? unidbg是一个Java项目,可以帮助我们去模拟一个安卓或IOS设备,用于去执行so文件中的算法,从而不需要再去逆向他内部的算法。最终会产出一个jar包,可以被python进行调用。 如何使用unidbg? 下载github上开源的项目:https://github.com/zhkl0228/un…

【因果推断python】32_合成控制2

目录 合成控制作为线性回归的一种实现​编辑 合成控制作为线性回归的一种实现 为了估计综合控制的治疗效果&#xff0c;我们将尝试构建一个类似于干预期之前的治疗单元的“假单元”。然后&#xff0c;我们将看到这个“假单位”在干预后的表现。合成控制和它所模仿的单位之间的…

OpenGauss常操作

OpenGauss官网已经有很详细的说明了,但是对于新手而言还有一些需要注意的地方; 安装 yum一键安装; yum -y install libaio-devel yum -y install readline-devel yum -y install libnsl 单独创建用户和组; groupadd dbgroup useradd -g dbgroup omm passwd omm 取消打开文…

关于学习Token、JWT、Cookie等验证授权方式的总结

目录 一、为什么Cookie无法防止CSRF攻击&#xff0c;而Token可以&#xff1f; 二、为什么无论采用Cookie-session的方式&#xff0c;还是Token&#xff08;JWT&#xff09;的方式&#xff0c;在一个浏览器里&#xff0c;同一个网站只能保证一个用户处于登录状态&#xff1f; …

韩顺平0基础学java——第22天

p441-459 异常exception 选中代码块&#xff0c;快捷键ctraltt6&#xff0c;即trt-catch 如果进行了异常处理&#xff0c;那么即使出现了异常&#xff0c;但是会继续执行 程序过程中发生的异常事件分为两大类&#xff1a; 异常体系图※ 常见的运行异常&#xff1a;类型转换…