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

伊利丹~怒风
企业官方账号
2025-07-04 12:12:49

 前言

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

Qualcomm Dragonwing™ QCM8550 | Qualcomm

 YOLO11-cli

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

本次测试采用的硬件设备

 

  YOLO11-cli分类模型性能指标

模型

尺寸640*640

CPU

NPU QNN2.31

NPU QNN2.31
FP32FP16INT8
YOLO11n-cli120.95 ms8.27 FPS6.11 ms163.67 FPS3.22 ms310.56 FPS
​YOLO11s-cli300.23 ms3.32 FPS7.41 ms134.95 FPS4.03 ms248.14 FPS
YOLO11m-cli676.82 ms1.48 FPS11.84 ms84.46 FPS5.18 ms193.05 FPS
YOLO11l-cli918.29 ms1.09 FPS13.88 ms72.05 FPS6.57 ms152.21 FPS
YOLO11x-cli1727.29 ms0.58 FPS27.4 ms36.50 FPS10.83 ms92.34 FPS

点击链接可以下载YOLO11-cli系列模型的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-cli系列模型的pt格式转换为onnx格式

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

from ultralytics import YOLO

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

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

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

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

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

 

 (二)使用AIMO将onnx模型转换高通NPU可以运行的模型格式

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

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

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

使用Netnron工具查看onnx模型结构,选择剪枝位置

/model.10/linear/Gemm_output_0

 

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

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

 (三)在QCS8550的NPU中推理Yolov11n-cli_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推理测试代码(qnn)

import time
import numpy as np
import cv2
import os
import aidlite
import argparse
from pathlib import Path

# ---------- 新增辅助函数 ----------
def load_class_names(names_path: str):
    """
    从 txt 文件或逗号分隔字符串载入类别名称
    
    参数:
        names_path: 类别名称文件路径或逗号分隔字符串
    返回:
        类别名称列表
    """
    # 如果未提供名称路径,生成默认类别名称列表
    if not names_path:
        return [f"class_{i}" for i in range(1000)]        # 默认 1000 类占位
    
    # 从文件加载类别名称
    if os.path.isfile(names_path):
        with open(names_path, 'r', encoding='utf-8') as f:
            names = [l.strip() for l in f.readlines() if l.strip()]
    # 从逗号分隔字符串加载类别名称
    else:  
        names = [x.strip() for x in names_path.split(',') if x.strip()]
    return names

def visualize_and_save(image_bgr, label, score, save_path):
    """
    在图片左上角绘制分类结果并写入文件
    
    参数:
        image_bgr: BGR格式图像
        label: 预测类别标签
        score: 预测置信度分数
        save_path: 保存路径
    """
    # 格式化显示文本
    txt = f"{label}: {score*100:.1f}%"
    # 设置字体
    font = cv2.FONT_HERSHEY_SIMPLEX
    # 在图像上绘制文本
    cv2.putText(image_bgr, txt, (10, 30), font, 1.0, (0, 255, 0), 2, cv2.LINE_AA)
    # 保存图像
    cv2.imwrite(str(save_path), image_bgr)
    print(f"预测结果已保存到: {save_path}")

# ---------- 主函数 ----------
def main(args):
    '''
    主函数流程:
    1. 初始化模型和配置
    2. 读取和预处理图像
    3. 执行模型推理
    4. 可视化并保存结果
    '''
    print("Start image inference ... ...")
    size = 640  # 模型输入尺寸

    # ---------- 1. 初始化模型 ----------
    # 创建配置实例
    config = aidlite.Config.create_instance()
    if config is None:
        print("Create config failed !")
        return False
    
    # 设置实现类型为本地实现
    config.implement_type = aidlite.ImplementType.TYPE_LOCAL
    
    # 根据命令行参数设置框架类型
    if args.model_type.lower() == "qnn":
        config.framework_type = aidlite.FrameworkType.TYPE_QNN231
    elif args.model_type.lower() in ("snpe2", "snpe"):
        config.framework_type = aidlite.FrameworkType.TYPE_SNPE2
    
    # 设置加速类型为DSP
    config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
    # 设置为量化模型
    config.is_quantify_model = 1

    # 创建模型实例
    model = aidlite.Model.create_instance(args.target_model)
    if model is None:
        print("Create model failed !")
        return False
    
    # 定义输入输出张量形状
    input_shapes  = [[1, size, size, 3]]
    output_shapes = [[1, args.num_classes]]

    # 设置模型属性
    model.set_model_properties(
        input_shapes,  aidlite.DataType.TYPE_FLOAT32,
        output_shapes, aidlite.DataType.TYPE_FLOAT32)

    # 构建并初始化解释器
    interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
    if interpreter is None or interpreter.init() != 0 or interpreter.load_model() != 0:
        print("Interpreter build/init/load 失败")
        return False
    print("Model loaded successfully ✔")

    # ---------- 2. 读取 & 预处理 ----------
    # 读取输入图像
    img_bgr = cv2.imread(args.image_path)
    if img_bgr is None:
        print("Error: Could not open image file")
        return False
    
    # 获取图像尺寸
    h, w, _ = img_bgr.shape
    # 计算填充后图像的边长
    length = max(h, w)
    # 计算缩放比例
    scale  = length / size

    # 创建黑色画布并将原始图像放置在左上角
    canvas = np.zeros((length, length, 3), dtype=np.uint8)
    canvas[0:h, 0:w] = img_bgr
    
    # 颜色空间转换 BGR -> RGB
    img_rgb = cv2.cvtColor(canvas, cv2.COLOR_BGR2RGB)
    # 调整图像大小为模型输入尺寸
    img_rgb = cv2.resize(img_rgb, (size, size))
    # 归一化处理,将像素值从0-255缩放到0-1
    img_norm = (img_rgb.astype(np.float32) - 0) / 255.0  # 归一化到 0~1
    img_input = img_norm  # HWC

    # ---------- 3. 推理 & 性能测试 ----------
    # 预热推理,消除首次推理的额外开销
    warmup_iters = 5
    for _ in range(warmup_iters):
        interpreter.set_input_tensor(0, img_input.data)
        interpreter.invoke()

    # 多次推理测量性能
    invoke_nums, invoke_times = 20, []
    for i in range(invoke_nums):
        t1 = time.time()
        interpreter.set_input_tensor(0, img_input.data)
        interpreter.invoke()
        t2 = time.time()
        invoke_times.append((t2 - t1) * 1000)  # 转换为毫秒
    
    # 计算性能统计指标
    mean_invoke_time = np.mean(invoke_times)  # 平均推理时间
    max_invoke_time = np.max(invoke_times)    # 最大推理时间
    min_invoke_time = np.min(invoke_times)    # 最小推理时间
    var_invoke_time = np.var(invoke_times)    # 推理时间方差
    fps = 1000 / mean_invoke_time  # 计算FPS
    
    # 打印性能统计结果
    print(f"\nInference {invoke_nums} times:\n"
          f"-- mean_invoke_time is {mean_invoke_time:.2f} ms\n"
          f"-- max_invoke_time is {max_invoke_time:.2f} ms\n"
          f"-- min_invoke_time is {min_invoke_time:.2f} ms\n"
          f"-- var_invoke_time is {var_invoke_time:.2f}\n"
          f"-- FPS: {fps:.2f}\n")

    # 获取最后一次推理输出
    logits = interpreter.get_output_tensor(0).reshape(*output_shapes)   # (1, num_classes)
    probs  = logits[0]                                                  # (num_classes,)

    # ---------- 4. 结果后处理 ----------
    # 获取概率最高的前5个类别索引
    top5_idx = probs.argsort()[-5:][::-1]
    # 加载类别名称
    class_names = load_class_names(args.class_names)
    # 获取概率最高的类别索引
    top1 = top5_idx[0]
    
    # 打印Top-5预测结果
    print("\nTop‑5 结果:")
    for rank, idx in enumerate(top5_idx, 1):
        print(f"{rank}. {class_names[idx]}  {probs[idx]*100:.2f}%")

    # ---------- 5. 可视化并保存 ----------
    # 创建保存目录
    save_dir = Path(args.save_dir)
    save_dir.mkdir(parents=True, exist_ok=True)
    # 生成保存路径
    save_path = save_dir / f"pred_{Path(args.image_path).stem}.jpg"
    # 可视化结果并保存
    visualize_and_save(img_bgr, class_names[top1], probs[top1], save_path)

    # ---------- 6. 资源释放 ----------
    interpreter.destory()

# ---------- 命令行参数 ----------
def parser_args():
    """解析命令行参数"""
    parser = argparse.ArgumentParser(description="AidLite image classification demo")
    parser.add_argument('--target_model', type=str, default='yolov11n_cls/cutoff_yolo11n-cls_qcs8550_fp16.qnn231.ctx.bin',
                        help="模型文件路径")
    parser.add_argument('--image_path', type=str, default='bus.jpg', help="待预测图片路径")
    parser.add_argument('--model_type',  type=str, default='QNN', help="后端类型: QNN / SNPE2")
    parser.add_argument('--num_classes', type=int, default=1000, help="模型输出类别数")
    parser.add_argument('--class_names', type=str, default='', help="类别名称 txt 路径或逗号分隔字符串")
    parser.add_argument('--save_dir', type=str, default='results', help="预测图片输出目录")
    return parser.parse_args()

if __name__ == "__main__":
    # 解析命令行参数
    args = parser_args()
    # 执行主函数
    main(args)

结果

yolo11n-cli

 

 

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

3,231

社区成员

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

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