使用OpenCV、ONNXRuntime部署YOLOV7实时目标检测的代码
时间: 2023-12-31 20:04:00 浏览: 203
好的,下面是使用OpenCV和ONNXRuntime来部署YOLOV7实时目标检测的代码:
```python
import cv2
import numpy as np
import onnxruntime as ort
# 加载模型
model_path = "yolov7.onnx"
session = ort.InferenceSession(model_path)
# 输入、输出名
input_name = session.get_inputs()[0].name
output_names = [session.get_outputs()[i].name for i in range(len(session.get_outputs()))]
# 类别名称
class_names = ["person", "car", "truck", "bus"]
# 预处理函数
def preprocess(image, target_shape):
# 图像缩放
h, w = image.shape[:2]
scale = min(target_shape[0] / h, target_shape[1] / w)
new_h, new_w = int(h * scale), int(w * scale)
image_resized = cv2.resize(image, (new_w, new_h))
# 图像填充
pad_h = target_shape[0] - new_h
pad_w = target_shape[1] - new_w
top, bottom = pad_h // 2, pad_h - pad_h // 2
left, right = pad_w // 2, pad_w - pad_w // 2
image_padded = cv2.copyMakeBorder(image_resized, top, bottom, left, right, cv2.BORDER_CONSTANT)
# 图像归一化
image_scaled = image_padded / 255.0
image_normalized = (image_scaled - [0.485, 0.456, 0.406]) / [0.229, 0.224, 0.225]
image_transposed = np.transpose(image_normalized, [2, 0, 1])
image_batched = np.expand_dims(image_transposed, axis=0)
return image_batched
# 后处理函数
def postprocess(outputs, conf_threshold, iou_threshold):
# 输出解码
objects = []
for i, output in enumerate(outputs):
grid_size = output.shape[2]
anchor_size = 3
num_classes = output.shape[1] - 5
boxes = output.reshape([-1, 5 + num_classes])
boxes[:, 0:2] = (boxes[:, 0:2] + np.arange(grid_size).reshape([1, -1, 1])) / grid_size
boxes[:, 2:4] = np.exp(boxes[:, 2:4]) * anchor_size / grid_size
boxes[:, 4:] = np.exp(boxes[:, 4:]) / (1 + np.exp(-boxes[:, 4:]))
boxes[:, 5:] = boxes[:, 4:5] * boxes[:, 5:]
mask = boxes[:, 4] > conf_threshold
boxes = boxes[mask]
classes = np.argmax(boxes[:, 5:], axis=-1)
scores = boxes[:, 4] * boxes[:, 5 + classes]
mask = scores > conf_threshold
boxes = boxes[mask]
classes = classes[mask]
scores = scores[mask]
for cls, score, box in zip(classes, scores, boxes):
if cls >= num_classes:
continue
x, y, w, h = box[:4]
x1, y1, x2, y2 = x - w / 2, y - h / 2, x + w / 2, y + h / 2
objects.append([x1, y1, x2, y2, score, class_names[cls]])
# 非极大抑制
objects = sorted(objects, key=lambda x: x[4], reverse=True)
for i in range(len(objects)):
if objects[i][4] == 0:
continue
for j in range(i + 1, len(objects)):
if iou(objects[i][:4], objects[j][:4]) > iou_threshold:
objects[j][4] = 0
# 输出筛选
objects = [obj for obj in objects if obj[4] > conf_threshold]
return objects
# IOU计算函数
def iou(box1, box2):
x1, y1, x2, y2 = box1
x3, y3, x4, y4 = box2
left = max(x1, x3)
top = max(y1, y3)
right = min(x2, x4)
bottom = min(y2, y4)
intersection = max(0, right - left) * max(0, bottom - top)
area1 = (x2 - x1) * (y2 - y1)
area2 = (x4 - x3) * (y4 - y3)
union = area1 + area2 - intersection
return intersection / (union + 1e-6)
# 摄像头读取
cap = cv2.VideoCapture(0)
while True:
# 读取帧
ret, frame = cap.read()
# 预处理
image = preprocess(frame, (416, 416))
# 推理
outputs = session.run(output_names, {input_name: image})
# 后处理
objects = postprocess(outputs, conf_threshold=0.5, iou_threshold=0.5)
# 可视化
for obj in objects:
x1, y1, x2, y2, score, class_name = obj
cv2.rectangle(frame, (int(x1 * frame.shape[1]), int(y1 * frame.shape[0])),
(int(x2 * frame.shape[1]), int(y2 * frame.shape[0])), (0, 255, 0), 2)
cv2.putText(frame, class_name + ": " + str(round(score, 2)), (int(x1 * frame.shape[1]), int(y1 * frame.shape[0]) - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
# 显示结果
cv2.imshow("YOLOV7", frame)
# 退出
if cv2.waitKey(1) == ord("q"):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
```
这段代码通过摄像头实时读取视频流,对每一帧进行目标检测,并将检测结果可视化显示在窗口中。在代码中,我们首先加载了YOLOV7模型,并定义了输入、输出名和类别名称。接着,我们定义了预处理函数和后处理函数,用于对输入图像进行预处理和输出结果进行解码、筛选和可视化。最后,我们通过OpenCV读取摄像头视频流,对每一帧进行目标检测并实时显示在窗口中,直到按下“q”键退出程序。
阅读全文