openvino同步和异步推理

同步推理(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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

给算法爸爸上香

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

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

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

打赏作者

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

抵扣说明:

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

余额充值