高通QCS8550部署YOLO11-seg模型与性能测试

伊利丹~怒风
企业官方账号
2025-07-08 17:10:33

 前言

在人工智能与边缘计算深度融合的当下,强大的硬件平台与先进的算法模型成为推动各领域智能化变革的核心要素。高通骁龙 QCS8550 作为一款面向物联网(IoT)领域的旗舰级处理器,采用先进的 4 纳米工艺制程,集强大计算能力、高达 48TOPS 的极致边缘 AI 处理性能、前沿的 Wi-Fi 7 连接技术以及卓越的视频和图形处理能力于一身 。其搭载的 Qualcomm Kryo 中央处理器,计算能力相较于前代提升达 1.5 倍;Qualcomm Adreno GPU 性能更是前代的三倍之多,支持硬件加速光线追踪技术,能同时处理多种格式与分辨率的视频会话,并通过多显示接口以超高清分辨率在不同面板上同步渲染内容。此外,AidLux为 AI 应用赋能。这些特性使其成为众多对性能要求严苛的 IoT 应用,如自主移动机器人、工业无人机、智能安防监控、视频协作系统等的理想硬件基石。

 

YOLO11-seg 作为 YOLO11 系列中专注于实例分割任务的模型,在计算机视觉领域有着极为重要的作用。实例分割需要精准识别图像或视频中的每个目标实例,并为其生成像素级别的分割掩码,这在众多实际场景中都不可或缺。例如在智能安防中,它能够精确区分不同的人物、物体,不仅识别出目标,还能清晰勾勒出其轮廓,为安防监控提供更细致准确的信息,助力快速精准地判断异常情况;在工业检测中,可对生产线上的产品进行细致的缺陷检测与分割,明确缺陷所在位置及范围,极大提高产品质量检测的精度和效率;在自动驾驶领域,能精准分割出道路上的行人、车辆、交通标识等各类目标,为车辆的决策与行驶提供关键的视觉基础。

 

本次对高通 QCS8550 部署 YOLO11-seg 模型的研究与性能测试,旨在深入探究如何充分发挥 QCS8550 强大的硬件性能,高效运行 YOLO11-seg 这一先进的实例分割模型,为相关领域的应用落地提供有力的技术支撑和实践参考 。通过对模型部署过程的详细分析以及全面的性能测试,期望为后续基于该硬件平台和模型的应用开发、优化等工作提供极具价值的经验与数据,进一步推动人工智能在边缘计算场景下的广泛应用与深度发展。

Qualcomm Dragonwing™ QCM8550 | Qualcomm

实例分割 -Ultralytics YOLO 文档

模型优化平台 (AIMO) 用户指南 | APLUX Doc Center

高通QCS8550开发板

  YOLO11-seg模型性能指标

模型

尺寸640*640

CPU

NPU QNN2.31

NPU QNN2.31
FP32FP16INT8
​YOLO11n-seg119.67 ms8.36 FPS16.71 ms59.84 FPS 5.54 ms180.51 FPS
YOLO11s-seg510.43 ms1.96 FPS9.62 ms103.95 FPS3.94 ms253.81 FPS
YOLO11m-seg1568.51 ms0.64 FPS24.97 ms40.05 FPS7.33 ms136.43 FPS
​YOLO11l-seg1921.28 ms0.52 FPS26.97 ms37.08 FPS8.52 ms117.37 FPS
​YOLO11x-seg3981.91 ms0.25 FPS67.32 ms14.85 FPS20.64 ms48.45 FPS

点击链接可以下载YOLO11-seg系列模型的pt格式,其他模型尺寸可以通过AIMO转换模型,并修改下面参考代码中的model_size测试即可。

(一)将pt模型转换为onnx格式

Step1:升级pip版本为25.1.1

python3.10 -m pip install --upgrade pip
pip -V
aidlux@aidlux:~/aidcode$ pip -V
pip 25.1.1 from /home/aidlux/.local/lib/python3.10/site-packages/pip (python 3.10)

Step2:安装ultralytics和onnx

pip install ultralytics onnx

Step3:设置yolo命令的环境变量

方法 1:临时添加环境变量(立即生效)

在终端中执行以下命令,将 ~/.local/bin 添加到当前会话的环境变量中

export PATH="$PATH:$HOME/.local/bin"
  • 说明:此操作仅对当前终端会话有效,关闭终端后失效。
  • 验证:执行 yolo --version,若输出版本号(如 0.0.2),则说明命令已生效。

方法 2:永久添加环境变量(长期有效)

echo 'export PATH="$PATH:$HOME/.local/bin"' >> ~/.bashrc
source ~/.bashrc  # 使修改立即生效

验证:执行 yolo --version,若输出版本号(如 0.0.2),则说明命令已生效。

测试环境中安装yolo版本为8.3.152

 提示:如果遇到用户组权限问题,可以忽悠,因为yolo命令会另外构建临时文件,也可以执行下面命令更改用户组,执行后下面的警告会消失:

sudo chown -R aidlux:aidlux ~/.config/
sudo chown -R aidlux:aidlux ~/.config/Ultralytics

可能遇见的报错如下:

WARNING ⚠️ user config directory '/home/aidlux/.config/Ultralytics' is not writeable, defaulting to '/tmp' or CWD.Alternatively you can define a YOLO_CONFIG_DIR environment variable for this path.

Step4:将Yolov11系列模型的pt格式转换为onnx格式

新建一个python文件,命名自定义即可,用于模型转换以及导出:

from ultralytics import YOLO

# 加载同级目录下的.pt模型文件
model = YOLO('yolo11n-seg.pt')  # 替换为实际模型文件名

# 导出ONNX配置参数
export_params = {
    'format': 'onnx',
    'opset': 12,          # 推荐算子集版本
    'simplify': True,     # 启用模型简化
    'dynamic': False,     # 固定输入尺寸
    'imgsz': 640,         # 标准输入尺寸
    'half': False         # 保持FP32精度
}

# 执行转换并保存到同级目录
model.export(**export_params)

执行该程序完成将pt模型导出为onnx模型。

提示:Yolo11s-seg,Yolo11m-seg,Yolo11l-seg,Yolo11x-seg替换代码中Yolo11n即可;

(二)使用模型优化平台 (AIMO) 用户指南 | APLUX Doc Center将onnx模型转换高通NPU可以运行的模型格式

Step1:选择模型优化,模型格式选择onnx格式上传模型

Step2:选择芯片型号以及目标框架,这里我们选择QCS8550+Qnn2.31

Step3:点击查看模型,使用Netron查看模型结构,进行输入输出的填写

使用Netron工具查看onnx模型结构,选择剪枝位置,由于yolov11-seg的输出有两个,所以剪枝参数有四个输入。

 

 

参考上图中红色框部分填写,其他不变,注意开启自动量化功能,AIMO更多操作查看使用说明或参考AIMO平台

 

output1
/model.23/Concat_output_0
/model.23/Mul_2_output_0
/model.23/Sigmoid_output_0

 

Step4:接下来进行提交即可,转换完成后将目标模型文件下载,解压缩后其中的.bin.aidem文件即为模型文件

 (三)在QCS8550的NPU中推理Yolov11n-seg_int8模型

检查aidlux环境中的aidlite版本是否与我们转换模型时选择的Qnn版本一致,终端执行:

sudo aid-pkg installed 

如果没有aidlite-qnn231,需要安装:

sudo aid-pkg update
sudo aid-pkg install aidlite-sdk
 
# Install the latest version of AidLite (latest QNN version)
sudo aid-pkg install aidlite

💡注意

Linux环境下,安装指定QNN版本的AidLite SDK:sudo aid-pkg install aidlite-{QNN Version}

例如:安装QNN2.31版本的AidLite SDK —— sudo aid-pkg install aidlite-qnn231

模型进行AI推理

import numpy as np
import cv2
import aidlite  # Qualcomm硬件加速库
import os
import time
import argparse
import onnxruntime

# 定义COCO数据集的类别名称
CLASSES = ("person", "bicycle", "car", "motorbike ", "aeroplane ", "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", "sofa",
           "pottedplant", "bed", "diningtable", "toilet ", "tvmonitor", "laptop\t", "mouse\t", "remote ", "keyboard ", "cell phone", "microwave ",
           "oven ", "toaster", "sink", "refrigerator ", "book", "clock", "vase", "scissors ", "teddy bear ", "hair drier", "toothbrush ")

# 定义相似度计算函数(用于比较不同框架输出结果)
def get_acc(onnx_out, other_out):
    """
    计算两个输出向量的余弦相似度
    :param onnx_out: 第一个输出向量
    :param other_out: 第二个输出向量
    :return: 余弦相似度
    """
    cosine_similarity = np.dot(np.array(onnx_out), np.array(other_out)) / \
                      (np.linalg.norm(np.array(onnx_out)) * np.linalg.norm(np.array(other_out)))
    return cosine_similarity

def eqprocess(image, size1, size2):
    """
    对图像进行等比例缩放并填充,保持长宽比
    :param image: 输入图像
    :param size1: 目标高度
    :param size2: 目标宽度
    :return: 处理后的图像和缩放比例
    """
    h, w, _ = image.shape
    mask = np.zeros((size1, size2, 3), dtype=np.float32)
    scale1 = h / size1
    scale2 = w / size2
    if scale1 > scale2:
        scale = scale1
    else:
        scale = scale2
    img = cv2.resize(image, (int(w / scale), int(h / scale)))
    mask[:int(h / scale), :int(w / scale), :] = img
    return mask, scale

def xywh2xyxy(x):
    """
    将边界框的格式从 (center x, center y, width, height) 转换为 (x1, y1, x2, y2)
    :param x: 输入的边界框数组
    :return: 转换后的边界框数组
    """
    y = np.copy(x)
    y[:, 0] = x[:, 0] - x[:, 2] / 2  # top left x
    y[:, 1] = x[:, 1] - x[:, 3] / 2  # top left y
    y[:, 2] = x[:, 0] + x[:, 2] / 2  # bottom right x
    y[:, 3] = x[:, 1] + x[:, 3] / 2  # bottom right y
    return y

def xyxy2xywh(box):
    """
    将边界框的格式从 (left_top x, left_top y, right_bottom x, right_bottom y) 转换为 (left_top x, left_top y, width, height)
    :param box: 输入的边界框数组
    :return: 转换后的边界框数组
    """
    box[:, 2:] = box[:, 2:] - box[:, :2]
    return box

def NMS(dets, scores, thresh):
    """
    单类NMS算法
    :param dets: 边界框数组,形状为 (N, 5),格式为 (left_top x, left_top y, right_bottom x, right_bottom y, Scores)
    :param scores: 置信度分数数组
    :param thresh: IOU阈值
    :return: 保留的边界框索引列表
    """
    x1 = dets[:, 0]
    y1 = dets[:, 1]
    x2 = dets[:, 2]
    y2 = dets[:, 3]
    areas = (y2 - y1 + 1) * (x2 - x1 + 1)
    keep = []
    index = scores.argsort()[::-1]
    while index.size > 0:
        i = index[0]  # every time the first is the biggest, and add it directly
        keep.append(i)
        x11 = np.maximum(x1[i], x1[index[1:]])  # calculate the points of overlap
        y11 = np.maximum(y1[i], y1[index[1:]])
        x22 = np.minimum(x2[i], x2[index[1:]])
        y22 = np.minimum(y2[i], y2[index[1:]])
        w = np.maximum(0, x22 - x11 + 1)  # the weights of overlap
        h = np.maximum(0, y22 - y11 + 1)  # the height of overlap
        overlaps = w * h
        ious = overlaps / (areas[i] + areas[index[1:]] - overlaps)
        idx = np.where(ious <= thresh)[0]
        index = index[idx + 1]  # because index start from 1

    return keep

def draw_detect_res(img, det_pred, segments):
    """
    绘制检测结果(边界框、类别标签和分割掩码)
    修改说明:为不同类别生成不同颜色,使分割实例按类别区分颜色
    :param img: 原始图像
    :param det_pred: 检测结果数组 [N, 6],每行格式为 [x1, y1, x2, y2, conf, class_id]
    :param segments: 分割轮廓列表,每个元素是一个点集
    :return: 绘制后的图像
    """
    if det_pred is None:
        return img

    img = img.astype(np.uint8)
    im_canvas = img.copy()  # 用于透明效果的底图

    # 预定义20种鲜艳的BGR颜色(可以根据需要扩展)
    color_palette = [
        (255, 0, 0),  # 红色
        (0, 255, 0),  # 绿色
        (0, 0, 255),  # 蓝色
        (255, 255, 0),  # 青色
        (255, 0, 255),  # 品红
        (0, 255, 255),  # 黄色
        (128, 0, 0),  # 深红
        (0, 128, 0),  # 深绿
        (0, 0, 128),  # 深蓝
        (128, 128, 0),  # 橄榄绿
        (128, 0, 128),  # 紫色
        (0, 128, 128),  # 蓝绿色
        (255, 165, 0),  # 橙色
        (255, 192, 203),  # 粉红
        (75, 0, 130),  # 靛蓝
        (0, 255, 127),  # 春绿色
        (220, 20, 60),  # 猩红色
        (0, 191, 255),  # 天蓝色
        (147, 112, 219),  # 中紫色
        (255, 215, 0)  # 金色
    ]

    for i in range(len(det_pred)):
        x1, y1, x2, y2 = [int(t) for t in det_pred[i][:4]]  # 边界框坐标
        cls_id = int(det_pred[i][5])  # 类别ID

        # 为不同类别选择不同颜色(使用取模运算循环使用调色板)
        color = color_palette[cls_id % len(color_palette)]

        # 绘制类别标签(带背景框提高可读性)
        (text_w, text_h), _ = cv2.getTextSize(f'{CLASSES[cls_id]}',
                                              cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
        cv2.rectangle(img, (x1, y1 - 20), (x1 + text_w, y1), color, -1)  # 标签背景
        cv2.putText(img, f'{CLASSES[cls_id]}', (x1, y1 - 6),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)

        # 绘制边界框(使用类别对应颜色)
        cv2.rectangle(img, (x1, y1), (x2, y2), color, thickness=2)

        # 绘制分割结果(使用类别对应颜色)
        if len(segments[i]) > 0:
            # 创建透明层用于填充
            overlay = img.copy()

            # 填充分割区域(半透明效果)
            cv2.fillPoly(overlay, np.int32([segments[i]]), color)

            # 绘制轮廓线(实线)
            cv2.polylines(overlay, np.int32([segments[i]]), True, color, 2)

            # 合并透明层
            img = cv2.addWeighted(overlay, 0.3, img, 0.7, 0)

    return img

def scale_mask(masks, im0_shape):
    """
    对掩码进行缩放,使其尺寸与原始图像一致
    :param masks: 输入的掩码数组
    :param im0_shape: 原始图像的形状
    :return: 缩放后的掩码数组
    """
    masks = cv2.resize(masks, (im0_shape[1], im0_shape[0]),
                       interpolation=cv2.INTER_LINEAR)
    if len(masks.shape) == 2:
        masks = masks[:, :, None]
    return masks

def crop_mask(masks, boxes):
    """
    根据边界框裁剪掩码
    :param masks: 输入的掩码数组
    :param boxes: 边界框数组
    :return: 裁剪后的掩码数组
    """
    n, h, w = masks.shape
    x1, y1, x2, y2 = np.split(boxes[:, :, None], 4, 1)
    r = np.arange(w, dtype=x1.dtype)[None, None, :]
    c = np.arange(h, dtype=x1.dtype)[None, :, None]
    return masks * ((r >= x1) * (r < x2) * (c >= y1) * (c < y2))

def process_mask(protos, masks_in, bboxes, im0_shape):
    """
    处理掩码输出,包括矩阵乘法、缩放和裁剪
    :param protos: 原型掩码数组
    :param masks_in: 输入的掩码特征数组
    :param bboxes: 边界框数组
    :param im0_shape: 原始图像的形状
    :return: 处理后的掩码数组
    """
    c, mh, mw = protos.shape
    masks = np.matmul(masks_in, protos.reshape((c, -1))).reshape((-1, mh, mw)).transpose(1, 2, 0)  # HWN
    masks = np.ascontiguousarray(masks)
    masks = scale_mask(masks, im0_shape)  # re-scale mask from P3 shape to original input image shape
    masks = np.einsum('HWN -> NHW', masks)  # HWN -> NHW
    masks = crop_mask(masks, bboxes)
    return np.greater(masks, 0.5)

def masks2segments(masks):
    """
    将掩码转换为轮廓线段
    :param masks: 输入的掩码数组
    :return: 轮廓线段列表
    """
    segments = []
    for x in masks.astype('uint8'):
        c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]  # CHAIN_APPROX_SIMPLE
        if c:
            c = np.array(c[np.array([len(x) for x in c]).argmax()]).reshape(-1, 2)
        else:
            c = np.zeros((0, 2))  # no segments found
        segments.append(c.astype('float32'))
    return segments

class qnn_predict(object):
    """
    QNN加速的YOLOv8-seg模型推理类
    """
    def __init__(self, args) -> None:
        # 初始化QNN推理环境 aidlite.Config.create_instance()
        config = aidlite.Config.create_instance()
        if config is None:
            print("Create model failed !")

        # 配置QNN运行参数
        config.implement_type = aidlite.ImplementType.TYPE_LOCAL  # 本地执行
        config.framework_type = aidlite.FrameworkType.TYPE_QNN  # 使用QNN框架
        config.accelerate_type = aidlite.AccelerateType.TYPE_DSP  # 使用DSP加速
        config.is_quantify_model = 1  # 使用量化模型

        # 加载模型文件
        model = aidlite.Model.create_instance(args.target_model)
        if model is None:
            print("Create model failed !")

        # 初始化模型参数
        self.conf = args.conf_thres  # 置信度阈值
        self.iou = args.iou_thres  # IOU阈值(NMS用)
        self.width = args.width  # 模型输入宽度
        self.height = args.height  # 模型输入高度
        self.class_num = args.class_num  # 类别数量(COCO为80)

        # 输入输出张量形状配置
        self.input_shape = [[1, self.height, self.width, 3]]  # NHWC格式

        # 输出特征图计算参数
        self.blocks = int(self.height * self.width * (1 / 64 + 1 / 256 + 1 / 1024))  # 多尺度特征图总锚点数
        self.maskw = int(self.width / 4)  # 掩码宽度
        self.maskh = int(self.height / 4)  # 掩码高度

        # 输出层形状配置(4个输出层)
        self.output_shape = [
            [1, 32, self.blocks],  # 原型掩码(protos)
            [1, 4, self.blocks],  # 边界框(xywh)
            [1, self.class_num, self.blocks],  # 类别置信度
            [1, self.maskh, self.maskw, 32]  # 分割特征
        ]

        # 设置模型属性
        model.set_model_properties(self.input_shape, aidlite.DataType.TYPE_FLOAT32, self.output_shape, aidlite.DataType.TYPE_FLOAT32)
        self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
        if self.interpreter is None:
            print("build_interpretper_from_model_and_config failed !")

        # 初始化模型
        result = self.interpreter.init()
        if result != 0:
            print(f"interpreter init failed !")

        # 加载模型
        result = self.interpreter.load_model()
        if result != 0:
            print("interpreter load model failed !")
        print("detect model load success!")

    def pretreat_img(self, frame):
        """
        图像预处理函数
        :param frame: 输入的图像帧
        :return: 处理后的图像和缩放比例
        """
        # 1. 等比例缩放并填充(保持长宽比)
        img, scale = eqprocess(frame, self.height, self.width)
        # 2. 归一化到0-1范围
        img = img / 255
        # 3. 转换为float32类型
        img = img.astype(np.float32)
        return img, scale

    def qnn_run(self, orig_imgs, args):
        """
        执行推理的主函数
        :param orig_imgs: 原始图像
        :param args: 命令行参数
        :return: 检测框和分割轮廓
        """
        # 1. 图像预处理
        input_img_f, scale = self.pretreat_img(orig_imgs)  # 获取处理后的图像和缩放比例
        input_img = np.expand_dims(input_img_f, 0)  # 增加batch维度(NHWC)

        invoke_time = []  # 记录每次推理耗时
        for i in range(args.invoke_nums):
            # 2. 设置输入张量
            self.interpreter.set_input_tensor(0, input_img.data)

            # 3. 执行推理并计时
            t0 = time.time()
            self.interpreter.invoke()
            t1 = time.time()
            cost_time = (t1 - t0) * 1000
            invoke_time.append(cost_time)

            # 4. 获取输出结果(4个输出层)
            # output[2]: 32维特征向量(用于掩码计算)
            input0_data = self.interpreter.get_output_tensor(3).reshape(1, 4, self.blocks)
            input1_data = self.interpreter.get_output_tensor(2).reshape(1, self.class_num, self.blocks)
            input2_data = self.interpreter.get_output_tensor(1).reshape(1, 32, self.blocks)
            protos = self.interpreter.get_output_tensor(0).reshape(1, self.maskh, self.maskw, 32).transpose(0, 3, 1, 2)

            # 5. 合并输出结果
            boxes = np.concatenate([input0_data, input1_data, input2_data], axis=1)
            x = boxes.transpose(0, 2, 1)  # 转置为[blocks, features]

            # 6. 根据置信度阈值过滤低质量检测
            x = x[np.amax(x[..., 4:-32], axis=-1) > self.conf]
            if len(x) < 1:
                return None, None  # 未检测到目标

            # 7. 重组输出格式: [x1,y1,x2,y2,conf,class_id,mask_features]
            x = np.c_[x[..., :4], np.amax(x[..., 4:-32], axis=-1), np.argmax(x[..., 4:-32], axis=-1), x[..., -32:]]

            # 8. 转换框格式(xywh -> xyxy)
            x[:, :4] = xywh2xyxy(x[:, :4])
            # 9. 执行NMS非极大值抑制
            index = NMS(x[:, :4], x[:, 4], self.iou)
            out_boxes = x[index]
            # 10. 将框坐标还原到原图尺寸
            out_boxes[..., :4] = out_boxes[..., :4] * scale

            # 11. 处理掩码输出
            masks = process_mask(protos[0], out_boxes[:, -32:], out_boxes[:, :4], orig_imgs.shape)
            # 12. 将掩码转换为轮廓线段
            segments = masks2segments(masks)

        # 13. 统计推理时间性能
        max_invoke_time = max(invoke_time)
        min_invoke_time = min(invoke_time)
        mean_invoke_time = sum(invoke_time) / args.invoke_nums
        var_invoketime = np.var(invoke_time)
        print("========================================")
        print(f"QNN inference {args.invoke_nums} times :\n --mean_invoke_time is {mean_invoke_time} \n --max_invoke_time is {max_invoke_time} \n --min_invoke_time is {min_invoke_time} \n --var_invoketime is {var_invoketime}")
        print("========================================")

        return out_boxes, segments  # 返回检测框和分割轮廓


def parser_args():
    """
    命令行参数解析
    :return: 解析后的命令行参数
    """
    parser = argparse.ArgumentParser(description="Run model benchmarks")
    parser.add_argument('--target_model', type=str, default='yolov11n_seg/cutoff_yolo11n-seg_qcs8550_fp16.qnn231.ctx.bin',
                        help="inference model path")
    parser.add_argument('--imgs', type=str, default='./python/bus.jpg', help="Predict images path")
    parser.add_argument('--invoke_nums', type=int, default=10, help="Inference nums")
    parser.add_argument('--model_type', type=str, default='QNN', help="run backend")
    parser.add_argument('--width', type=int, default=640, help="Model input size")
    parser.add_argument('--height', type=int, default=640, help="Model input size")
    parser.add_argument('--conf_thres', type=float, default=0.45, help="confidence threshold for filtering the annotations")
    parser.add_argument('--iou_thres', type=float, default=0.45, help="Iou threshold for filtering the annotations")
    parser.add_argument('--class_num', type=int, default=80, help="Iou threshold for filtering the annotations")
    args = parser.parse_args()
    return args

def main(args):
    """
    主执行函数
    :param args: 命令行参数
    """
    # 1. 初始化模型
    model = qnn_predict(args)
    # 2. 读取图像
    frame = cv2.imread(args.imgs)
    # 3. 执行推理
    qnn_out_boxes, qnn_segments = model.qnn_run(frame, args)
    # 4. 绘制结果
    result = draw_detect_res(frame, qnn_out_boxes, qnn_segments)
    # 5. 保存结果图像
    cv2.imwrite("./bus_result.jpg", result)

if __name__ == "__main__":
    args = parser_args()
    main(args)

测试结果

...全文
26 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

3,303

社区成员

发帖
与我相关
我的任务
社区描述
本论坛以AI、WoS 、XR、IoT、Auto、生成式AI等核心板块组成,为开发者提供便捷及高效的学习和交流平台。 高通开发者专区主页:https://qualcomm.csdn.net/
人工智能物联网机器学习 技术论坛(原bbs) 北京·东城区
社区管理员
  • csdnsqst0050
  • chipseeker
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧