同步推理(Synchronous Inference)
同步推理是最直接的推理方式,模型执行推理时会阻塞主线程,直到推理完成才返回结果。
特点:
简单直接:代码逻辑清晰,易于理解
阻塞执行:推理过程中主线程被阻塞
适合场景:单任务、实时性要求不高的应用
示例代码:
import cv2
import numpy as np
from openvino.runtime import Core
import time
# --------------------------
# 1. 配置参数
# --------------------------
MODEL_XML = "yolov8n_fp32.xml" # 模型结构文件
MODEL_BIN = "yolov8n_fp32.bin" # 模型权重文件
INPUT_VIDEO = "test.mp4" # 输入视频路径,可替换为0使用摄像头
CONF_THRESH = 0.5 # 置信度阈值
DEVICE = "CPU" # 推理设备(CPU/GPU/MYRIAD等)
# --------------------------
# 2. 模型加载与初始化
# --------------------------
def init_model(model_xml, model_bin, device):
"""初始化OpenVINO模型和推理引擎"""
core = Core()
# 读取模型
model = core.read_model(model=model_xml, weights=model_bin)
# 获取输入层信息
input_layer = next(iter(model.inputs))
input_shape = input_layer.shape # [1, 3, H, W]
input_h, input_w = input_shape[2], input_shape[3]
# 编译模型(指定设备)
compiled_model = core.compile_model(model=model, device_name=device)
return compiled_model, input_h, input_w
# --------------------------
# 3. 图像预处理
# --------------------------
def preprocess_frame(frame, input_h, input_w):
"""将视频帧预处理为模型输入格式"""
# 缩放图像
resized = cv2.resize(frame, (input_w, input_h))
# 转换通道顺序(HWC -> CHW)
transposed = resized.transpose(2, 0, 1)
# 增加batch维度
input_data = np.expand_dims(transposed, axis=0)
# 归一化(根据模型训练时的预处理方式调整)
input_data = input_data.astype(np.float32) / 255.0
return input_data
# --------------------------
# 4. 推理结果处理
# --------------------------
def process_results(output, frame, input_w, input_h):
"""处理推理结果(同步处理)"""
# 获取输出结果(YOLOv8输出格式:[1, 84, N],84=4坐标+80类别)
output_data = output[0] # 取出第一个输出
# 解析检测结果
boxes = []
for obj in output_data:
confidence = np.max(obj[4:]) # 置信度
if confidence < CONF_THRESH:
continue
class_id = np.argmax(obj[4:]) # 类别ID
# 边界框坐标转换(模型输出的是归一化坐标)
x, y, w, h = obj[:4]
x1 = int((x - w/2) * frame.shape[1] / input_w)
y1 = int((y - h/2) * frame.shape[0] / input_h)
x2 = int((x + w/2) * frame.shape[1] / input_w)
y2 = int((y + h/2) * frame.shape[0] / input_h)
boxes.append((x1, y1, x2, y2, class_id, confidence))
return boxes
# --------------------------
# 5. 主处理流程
# --------------------------
if __name__ == "__main__":
# 初始化模型
compiled_model, input_h, input_w = init_model(MODEL_XML, MODEL_BIN, DEVICE)
print(f"模型加载完成,输入尺寸: {input_h}x{input_w}")
# 打开视频流
cap = cv2.VideoCapture(INPUT_VIDEO)
if not cap.isOpened():
raise ValueError(f"无法打开视频: {INPUT_VIDEO}")
frame_count = 0
start_time = time.time()
print("开始处理视频...(按Q退出)")
while cap.isOpened():
# 读取视频帧
ret, frame = cap.read()
if not ret:
break # 视频结束
# 预处理帧
input_data = preprocess_frame(frame, input_h, input_w)
# 同步推理(直接获取结果)
output = compiled_model(inputs={0: input_data})
# 获取输出层结果(YOLOv8通常只有一个输出层)
results = process_results(output[0], frame, input_w, input_h)
# 绘制当前帧的推理结果
for (x1, y1, x2, y2, class_id, conf) in results:
# 绘制边界框
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
# 绘制类别和置信度
label = f"{class_id}: {conf:.2f}"
cv2.putText(frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
# 显示处理后的帧
cv2.imshow("OpenVINO Sync Inference", frame)
# 按Q退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
frame_count += 1
# 计算FPS
fps = frame_count / (time.time() - start_time)
print(f"处理完成,FPS: {fps:.2f}")
# 释放资源
cap.release()
cv2.destroyAllWindows()
输出结果:
模型加载完成,输入尺寸: 640x640
开始处理视频...(按Q退出)
处理完成,FPS: 27.90
异步推理
异步推理允许模型在后台执行推理,主线程可以继续执行其他任务,通过回调机制获取推理结果。
特点:
非阻塞执行:推理在后台进行,不阻塞主线程
提高吞吐量:可以同时处理多个推理请求
适合场景:实时应用、视频处理、多任务并发
示例代码:
import cv2
import numpy as np
from openvino.runtime import Core, AsyncInferQueue
import time
# --------------------------
# 1. 配置参数
# --------------------------
MODEL_XML = "yolov8n_fp32.xml" # 模型结构文件
MODEL_BIN = "yolov8n_fp32.bin" # 模型权重文件
INPUT_VIDEO = "test.mp4" # 输入视频路径,可替换为0使用摄像头
CONF_THRESH = 0.5 # 置信度阈值
DEVICE = "CPU" # 推理设备(CPU/GPU/MYRIAD等)
# --------------------------
# 2. 模型加载与初始化
# --------------------------
def init_model(model_xml, model_bin, device):
"""初始化OpenVINO模型和推理引擎"""
core = Core()
# 读取模型
model = core.read_model(model=model_xml, weights=model_bin)
# 获取输入层信息
input_layer = next(iter(model.inputs))
input_shape = input_layer.shape # [1, 3, H, W]
input_h, input_w = input_shape[2], input_shape[3]
# 编译模型(指定设备)
compiled_model = core.compile_model(model=model, device_name=device)
# 创建异步推理队列(2个请求,交替使用)
infer_queue = AsyncInferQueue(compiled_model, 2)
return infer_queue, input_h, input_w
# --------------------------
# 3. 图像预处理
# --------------------------
def preprocess_frame(frame, input_h, input_w):
"""将视频帧预处理为模型输入格式"""
# 缩放图像
resized = cv2.resize(frame, (input_w, input_h))
# 转换通道顺序(HWC -> CHW)
transposed = resized.transpose(2, 0, 1)
# 增加batch维度
input_data = np.expand_dims(transposed, axis=0)
# 归一化(根据模型训练时的预处理方式调整)
input_data = input_data.astype(np.float32) / 255.0
return input_data
# --------------------------
# 4. 异步推理回调函数
# --------------------------
def process_results(output, frame, input_w, input_h):
"""处理推理结果(同步处理)"""
# 获取输出结果(YOLOv8输出格式:[1, 84, N],84=4坐标+80类别)
output_data = output.get_output_tensor().data[0] # 取出第一个输出
# 解析检测结果
boxes = []
for obj in output_data:
confidence = np.max(obj[4:]) # 置信度
if confidence < CONF_THRESH:
continue
class_id = np.argmax(obj[4:]) # 类别ID
# 边界框坐标转换(模型输出的是归一化坐标)
x, y, w, h = obj[:4]
x1 = int((x - w/2) * frame.shape[1] / input_w)
y1 = int((y - h/2) * frame.shape[0] / input_h)
x2 = int((x + w/2) * frame.shape[1] / input_w)
y2 = int((y + h/2) * frame.shape[0] / input_h)
boxes.append((x1, y1, x2, y2, class_id, confidence))
return boxes
# --------------------------
# 5. 主处理流程
# --------------------------
if __name__ == "__main__":
# 初始化模型
infer_queue, input_h, input_w= init_model(MODEL_XML, MODEL_BIN, DEVICE)
print(f"模型加载完成,输入尺寸: {input_h}x{input_w}")
# 打开视频流
cap = cv2.VideoCapture(INPUT_VIDEO)
if not cap.isOpened():
raise ValueError(f"无法打开视频: {INPUT_VIDEO}")
# 存储上一帧的推理结果
last_results = None
frame_count = 0
start_time = time.time()
# 定义回调函数(处理推理结果)
def callback(request, userdata):
global last_results
last_results = process_results(request, userdata, input_w, input_h)
# 设置异步推理回调
infer_queue.set_callback(callback)
print("开始处理视频...(按Q退出)")
while cap.isOpened():
# 读取视频帧
ret, frame = cap.read()
if not ret:
break # 视频结束
# 预处理帧
input_data = preprocess_frame(frame, input_h, input_w)
# 提交异步推理请求(将原始帧作为用户数据传入回调)
infer_queue.start_async({0: input_data}, userdata=frame)
# 绘制上一帧的推理结果(与当前帧推理并行)
if last_results is not None:
for (x1, y1, x2, y2, class_id, conf) in last_results:
# 绘制边界框
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
# 绘制类别和置信度
label = f"{class_id}: {conf:.2f}"
cv2.putText(frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
# 显示处理后的帧
cv2.imshow("OpenVINO Async Inference", frame)
# 按Q退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
frame_count += 1
# 计算FPS
fps = frame_count / (time.time() - start_time)
print(f"处理完成,FPS: {fps:.2f}")
# 释放资源
cap.release()
cv2.destroyAllWindows()
infer_queue.wait_all() # 等待所有异步请求完成
输出结果:
模型加载完成,输入尺寸: 640x640
开始处理视频...(按Q退出)
处理完成,FPS: 35.54

169

被折叠的 条评论
为什么被折叠?



