如何从YOLOv7-OpenVINO模型输出中提取坐标绘制Bounding Box?
处理YOLOv7 OpenVINO输出并绘制Bounding Box
先搞懂模型输出的含义
你的模型有4个输出:
- 第一个输出
names[812] shape{1,25200,85}:这是YOLOv7已经整合好的所有候选框集合,优先用这个输出最省事,不用自己处理多尺度特征图。25200:是所有尺度下的锚框总数((8080+4040+20*20)*3=25200)85:每个框的参数:前4个是x_center, y_center, width, height(相对于输入图像的640x640尺寸),第5个是框的置信度(表示这个框里有物体的概率),剩下80个是COCO数据集的80个类别的概率。
- 后面三个输出是不同尺度的特征图(80x80/40x40/20x20),每个网格对应3个锚框,每个锚框同样是85个参数,适合需要自定义后处理的场景,但新手用第一个输出足够。
完整处理流程(代码+解释)
下面是从推理到绘制框的完整代码,替换你现有代码的后半部分即可:
import cv2 import numpy as np from openvino.runtime import Core model_path = "./yolov7.xml" ie_core = Core() def model_init(model_path): model = ie_core.read_model(model=model_path) compiled_model = ie_core.compile_model(model=model, device_name="CPU") input_key = compiled_model.input(0) # 取第一个整合好的候选框输出 output_key = compiled_model.output(0) return input_key, output_key, compiled_model input_key, output_key, compiled_model = model_init(model_path) # ---------------------- 图像预处理 ---------------------- # 读取目标图像(替换为你的图像路径) image = cv2.imread("test_image.jpg") original_h, original_w = image.shape[:2] # 模型输入固定为640x640 input_h, input_w = 640, 640 # 缩放图像到输入尺寸 resized_image = cv2.resize(image, (input_w, input_h)) # 转换为模型要求的CHW格式(OpenCV默认是HWC) input_image = resized_image.transpose((2, 0, 1)) # 添加batch维度(模型输入格式为[1,3,640,640]) input_image = input_image.reshape(1, 3, input_h, input_w) # 归一化到0-1范围(YOLO模型要求输入为float32类型) input_image = input_image.astype(np.float32) / 255.0 # ---------------------- 推理 ---------------------- results = compiled_model([input_image])[output_key] # 去掉batch维度,得到(25200,85)的候选框数组 predictions = results[0] # ---------------------- 后处理:过滤无效框+去重 ---------------------- # 1. 过滤低置信度的框 conf_threshold = 0.5 # 可调整,值越高过滤越严格 valid_mask = predictions[:, 4] > conf_threshold valid_predictions = predictions[valid_mask] if len(valid_predictions) == 0: print("未检测到任何物体") cv2.imshow("Result", image) cv2.waitKey(0) exit() # 2. 提取类别信息 class_scores = valid_predictions[:, 5:] class_ids = np.argmax(class_scores, axis=1) class_confidences = np.max(class_scores, axis=1) # 计算综合得分:框置信度 × 类别概率 final_scores = valid_predictions[:, 4] * class_confidences # 3. 转换YOLO坐标为OpenCV可用的左上角/右下角格式 boxes = [] for pred in valid_predictions: x_center, y_center, w, h = pred[:4] x1 = int((x_center - w/2) * input_w) y1 = int((y_center - h/2) * input_h) x2 = int((x_center + w/2) * input_w) y2 = int((y_center + h/2) * input_h) boxes.append([x1, y1, x2, y2]) # 4. 非极大值抑制(NMS):去除重叠度高的重复框 nms_threshold = 0.4 # 可调整,值越低去重越严格 indices = cv2.dnn.NMSBoxes(boxes, final_scores.tolist(), conf_threshold, nms_threshold) # ---------------------- 用OpenCV绘制框和标签 ---------------------- # COCO数据集类别名称(和YOLOv7默认训练集对应) coco_classes = [ "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch", "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush" ] # 遍历NMS筛选后的有效框 for i in indices: i = i[0] if isinstance(i, (list, np.ndarray)) else i box = boxes[i] x1, y1, x2, y2 = box # 将框坐标缩放回原始图像尺寸 scale_x = original_w / input_w scale_y = original_h / input_h x1 = int(x1 * scale_x) y1 = int(y1 * scale_y) x2 = int(x2 * scale_x) y2 = int(y2 * scale_y) # 绘制框 cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2) # 绘制类别标签 class_id = class_ids[i] score = final_scores[i] label = f"{coco_classes[class_id]}: {score:.2f}" # 调整标签位置避免超出图像 label_size, _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 2) y_label = y1 - label_size[1] if y1 - label_size[1] > 10 else y1 + label_size[1] cv2.rectangle(image, (x1, y_label - label_size[1] - 5), (x1 + label_size[0], y_label + 5), (0, 255, 0), -1) cv2.putText(image, label, (x1, y_label), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2) # 显示结果 cv2.imshow("YOLOv7 Detection Result", image) cv2.waitKey(0) cv2.destroyAllWindows()
关键步骤解释
- 图像预处理:必须匹配模型要求的输入格式(CHW布局、float32类型、0-1归一化),否则推理结果会完全错误。
- 输出选择:优先用第一个整合好的输出,避免手动处理多尺度特征图的复杂逻辑。
- 置信度过滤:快速剔除明显无效的预测框,减少后续计算量。
- NMS去重:解决YOLO对同一物体生成多个重叠框的问题,保留最准确的预测结果。
- 坐标转换:将YOLO的中心坐标格式转换为OpenCV支持的左上角/右下角格式,并缩放回原始图像尺寸,保证框的位置准确。
宏观学习路径
- 先理解YOLO系列的核心输出逻辑:重点掌握锚框、置信度、类别概率这三个核心概念,可以看YOLO官方文档或基础入门教程。
- 学习计算机视觉后处理基础:搞懂置信度过滤、非极大值抑制(NMS)的作用和实现原理。
- 熟悉OpenCV绘图API:掌握
cv2.rectangle、cv2.putText等函数的用法,理解图像坐标系统的转换逻辑。 - 动手调试验证:打印每一步的中间结果(比如过滤后的框、NMS后的索引),直观理解每个步骤的作用,逐步调整阈值参数找到最优效果。
内容的提问来源于stack exchange,提问作者bbartling
相关产品推荐
相关产品推荐

