10.9 双坐标轴绘制

在实际的应用中,常常需要把同一自变量的两个不同量纲、不同量级的函数量的变化同时绘制在同一个图窗中,例如在同一张图中同时展示空间一点上的电磁波的幅度和相位随时间的变化;不同时间内的降雨量和温湿度的变化,MATLAB中的plotyy函数可以实现上述功能,其具体的语法格式如下

plotyy(X1,Y1,X2,Y2):以左、右不同的纵轴分别绘制X1-Y1和X2-Y2两条曲线。

plotyy(X1,Y1,X2,Y2,Fun):以左、右不同的纵轴以Fun指定的形式分别绘制X1-Y1和X2-Y2两条曲线。

plotyy(X1,Y1,X2,Y2,Fun1,Fun2):以左、右不同的纵轴分别以Fun1、Fun2指定的形式绘制X1-Y1和X2-Y2两条曲线。

使用plotyy指令时需要注意的是,左侧的纵轴用来描述X1-Y1曲线,右侧的纵轴用来描述X2-Y2曲线。轴的范围与刻度值都是自动生成的,进行人工设置时,使用的绘图指令与一般的绘图指令相同。


x=0:0.01*pi;2*pi;
y=sin(0:0.01*pi:2*pi);
z=y.*(cos(x)+sqrt(-1)*sin(x));
[AX,H1,H2]=plotyy(0:200,abs(z),0:200,angle(z)*180/pi);
set(get(AX(1),'Ylabel'),'String','abs');
set(get(AX(2),'Ylabel'),'String','phase');
set(H1,'LineWidth',3);
set(H2,'Marker','*','LineWidth',3);


<think>我们正在使用CUDA 12.6和TensorRT 10.9,这是一个较新的组合。由于YOLOv5官方可能尚未正式支持TensorRT 10.9,因此我们需要确保使用兼容的YOLOv5版本和正确的导出方式。 根据之前的引用[2],我们知道在TensorRT 8.6.1上导出YOLOv5模型为engine的步骤。现在我们需要适配到TensorRT 10.9。 步骤: 1. 导出模型:将YOLOv5的PyTorch模型(.pt)导出为ONNX格式,然后再转换为TensorRT引擎(.engine)。但是,TensorRT 10.9可能已经直接支持从PyTorch模型转换,但为了通用性,我们还是采用ONNX作为中间格式。 2. 使用TensorRT Python API加载引擎并进行推理。 注意:由于TensorRT 10.9较新,我们需要确保使用的PyTorch版本和ONNX版本与之兼容。 参考步骤: - 首先,确保环境:CUDA 12.6, cuDNN(建议与CUDA 12.6匹配的版本),TensorRT 10.9,以及对应的PyTorch(支持CUDA 12.6的版本,如PyTorch 2.3+)。 - 导出ONNX:使用YOLOv5的export.py脚本,指定opset(建议使用13或更高,因为TensorRT 10.9支持较高的ONNX opset)。 - 使用TensorRT的trtexec工具或者TensorRT Python API将ONNX转换为engine。这里我们使用Python API,以便在代码中完成转换和推理。 但是,用户要求直接编写测试YOLOv5模型推理的代码,所以我们假设已经有一个转换好的TensorRT引擎文件(.engine)。 因此,代码步骤: 1. 导入必要的库:tensorrt, pycuda, numpy, opencv等。 2. 加载TensorRT引擎文件。 3. 创建执行上下文。 4. 准备输入数据(图像预处理)。 5. 执行推理。 6. 后处理(解析检测结果,应用NMS等)。 7. 绘制检测框并显示。 注意:由于TensorRT 10.9的API可能有变化,我们参考TensorRT官方Python示例。 由于代码较长,我们将分步骤编写。这里假设已经有一个转换好的yolov5s.engine文件(针对TensorRT 10.9和CUDA 12.6转换的)。 但是,请注意:YOLOv5的TensorRT引擎在导出时可能已经固定了输入尺寸,所以预处理需要按照导出时的尺寸进行。 我们将编写一个完整的测试脚本,包括以下部分: - 图像预处理:调整大小、归一化、转换为CHW格式等。 - 加载引擎并分配内存(输入和输出)。 - 执行推理。 - 后处理:将输出数据转换为检测框,并应用非极大值抑制(NMS)。 - 绘制结果。 由于TensorRT 10.9的API与之前版本可能略有不同,我们将按照TensorRT 10.9的文档来写。 注意:由于TensorRT 10.9是较新的版本,我们可能需要使用最新的API。以下代码基于TensorRT的Python示例编写。 步骤: 1. 导入库 2. 加载引擎 3. 创建上下文 4. 准备输入和输出的内存 5. 图像预处理 6. 执行推理 7. 后处理 8. 可视化 由于YOLOv5的输出层结构可能因版本而异,我们假设使用YOLOv5 v6.0或更高版本,其输出为单个张量(形状为[1, num_boxes, 85]),其中85表示每个检测框的坐标(4个值)、目标得分(1个值)和80个类别的概率(80个值)。 但是,在TensorRT中,当我们导出为engine时,输出层的形状和名称可能会变化。因此,我们需要知道引擎的输入和输出名称以及形状。我们可以通过引擎的信息来获取。 由于代码较长,我们将分步骤实现。 注意:由于我们使用的是TensorRT 10.9,所以需要安装对应的Python包(tensorrt)和pycuda(用于GPU内存管理和数据传输)。 如果还没有转换引擎,我们可以先写一个函数来从ONNX转换,但用户要求的是测试推理,所以我们假设引擎已经存在。 开始编写代码:</think>以下是为 CUDA 12.6 和 TensorRT 10.9 编写的 YOLOv5 模型推理测试代码,包含完整的引擎加载、预处理、推理和后处理流程: ```python import tensorrt as trt import pycuda.driver as cuda import pycuda.autoinit import numpy as np import cv2 import time import os class YOLOv5TRTInference: def __init__(self, engine_path, input_shape=(640, 640)): """ 初始化TensorRT推理引擎 :param engine_path: TensorRT引擎文件路径 :param input_shape: 模型输入尺寸 (高度, 宽度) """ self.input_shape = input_shape self.logger = trt.Logger(trt.Logger.INFO) # 加载TensorRT引擎 with open(engine_path, "rb") as f, trt.Runtime(self.logger) as runtime: self.engine = runtime.deserialize_cuda_engine(f.read()) # 创建执行上下文 self.context = self.engine.create_execution_context() # 分配输入输出内存 self.inputs, self.outputs, self.bindings, self.stream = self.allocate_buffers() def allocate_buffers(self): """分配GPU内存并创建流""" inputs, outputs, bindings = [], [], [] stream = cuda.Stream() for binding in self.engine: size = trt.volume(self.engine.get_binding_shape(binding)) dtype = trt.nptype(self.engine.get_binding_dtype(binding)) # 分配主机和设备内存 host_mem = cuda.pagelocked_empty(size, dtype) device_mem = cuda.mem_alloc(host_mem.nbytes) bindings.append(int(device_mem)) if self.engine.binding_is_input(binding): inputs.append({&#39;host&#39;: host_mem, &#39;device&#39;: device_mem}) else: outputs.append({&#39;host&#39;: host_mem, &#39;device&#39;: device_mem}) return inputs, outputs, bindings, stream def preprocess_image(self, image_path): """ 图像预处理 :param image_path: 输入图像路径 :return: 预处理后的图像数组 """ # 读取并调整图像尺寸 img = cv2.imread(image_path) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_resized = cv2.resize(img, (self.input_shape[1], self.input_shape[0])) # 归一化并转换为CHW格式 img_norm = img_resized.astype(np.float32) / 255.0 img_chw = np.transpose(img_norm, (2, 0, 1)) # 添加批次维度 return np.expand_dims(img_chw, axis=0) def inference(self, input_data): """执行推理""" # 复制数据到GPU np.copyto(self.inputs[0][&#39;host&#39;], input_data.ravel()) cuda.memcpy_htod_async(self.inputs[0][&#39;device&#39;], self.inputs[0][&#39;host&#39;], self.stream) # 执行推理 self.context.execute_async_v2( bindings=self.bindings, stream_handle=self.stream.handle ) # 将结果复制回主机 for out in self.outputs: cuda.memcpy_dtoh_async(out[&#39;host&#39;], out[&#39;device&#39;], self.stream) self.stream.synchronize() # 返回所有输出 return [out[&#39;host&#39;] for out in self.outputs] def postprocess(self, outputs, conf_thres=0.5, iou_thres=0.45): """ 后处理:非极大值抑制(NMS) :param outputs: 模型输出 :param conf_thres: 置信度阈值 :param iou_thres: IoU阈值 :return: 检测结果列表 [x1, y1, x2, y2, confidence, class_id] """ # 假设输出为[1, num_boxes, 85]格式 predictions = np.squeeze(outputs[0]) # 过滤低置信度检测 conf_mask = predictions[:, 4] > conf_thres predictions = predictions[conf_mask] if len(predictions) == 0: return [] # 获取类别分数 scores = predictions[:, 5:] * predictions[:, 4:5] class_ids = np.argmax(scores, axis=1) class_scores = scores[np.arange(len(scores)), class_ids] # 获取边界框坐标 boxes = predictions[:, :4] boxes[:, 0] -= boxes[:, 2] / 2 # x_center -> x1 boxes[:, 1] -= boxes[:, 3] / 2 # y_center -> y1 # 执行NMS indices = cv2.dnn.NMSBoxes( boxes.tolist(), class_scores.tolist(), conf_thres, iou_thres ) if len(indices) > 0: indices = indices.flatten() return np.hstack(( boxes[indices], class_scores[indices].reshape(-1, 1), class_ids[indices].reshape(-1, 1) )) return [] def visualize(self, image_path, detections): """可视化检测结果""" img = cv2.imread(image_path) h, w = img.shape[:2] # 缩放因子 scale_x = w / self.input_shape[1] scale_y = h / self.input_shape[0] for det in detections: x1, y1, x2, y2, conf, cls_id = det # 缩放回原始尺寸 x1 = int(x1 * scale_x) y1 = int(y1 * scale_y) x2 = int((x1 + x2) * scale_x) y2 = int((y1 + y2) * scale_y) # 绘制边界框和标签 cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) label = f"Class {int(cls_id)}: {conf:.2f}" cv2.putText(img, label, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) cv2.imshow("Detection Results", img) cv2.waitKey(0) cv2.destroyAllWindows() if __name__ == "__main__": # 配置参数 ENGINE_PATH = "yolov5s.engine" # TensorRT引擎文件 IMAGE_PATH = "test_image.jpg" # 测试图像 # 初始化推理器 inferencer = YOLOv5TRTInference(ENGINE_PATH) # 预处理 input_data = inferencer.preprocess_image(IMAGE_PATH) # 执行推理并计时 start_time = time.time() outputs = inferencer.inference(input_data) inference_time = time.time() - start_time # 后处理 detections = inferencer.postprocess(outputs) # 输出结果 print(f"Inference time: {inference_time*1000:.2f} ms") print(f"Detected {len(detections)} objects:") for i, det in enumerate(detections): print(f"Object {i+1}: class={int(det[5])}, conf={det[4]:.4f}, bbox={det[:4]}") # 可视化结果 inferencer.visualize(IMAGE_PATH, detections) ``` ### 关键说明: 1. **环境要求**: - CUDA 12.6 + TensorRT 10.9 - PyCUDA 2023.1+ - OpenCV 4.7+ - NumPy 1.23+ 2. **使用流程**: ```mermaid graph LR A[加载TensorRT引擎] --> B[预处理图像] B --> C[执行GPU推理] C --> D[后处理/NMS] D --> E[可视化结果] ``` 3. **性能优化**: - 使用`execute_async_v2`实现异步推理 - 使用`pagelocked memory`加速主机-设备传输 - 支持动态批量大小(需在导出时设置) 4. **注意事项**: - 确保引擎文件使用相同TensorRT版本导出 - 输入图像尺寸需匹配引擎输入尺寸 - 后处理逻辑需根据实际输出层结构调整 ### 引擎导出建议: 使用以下命令导出TensorRT引擎: ```bash python export.py --weights yolov5s.pt \ --include engine \ --device 0 \ --half \ --opset 18 \ --imgsz 640 \ --iou-thres 0.45 \ --conf-thres 0.5 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术提高效率

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值