以下是 yolov8n.pt 到 NCNN INT8 模型的完整、可执行转换流程,专为你的环境(Windows 7 / C++ / 老旧 CPU)优化,包含所有工具下载、命令、代码和注意事项。


📦 一、准备工作

1. 确保你有以下文件

  • yolov8n.pt(Ultralytics YOLOv8n 权重)
  • 校准图像文件夹(如 D:\Datasets\quantization_pic,含 100~300 张 .jpg

2. 下载必要工具(Windows 兼容版)

工具 用途 下载链接
Python + Ultralytics 导出 ONNX pip install ultralytics onnx onnxsim
NCNN 工具包 ONNX → NCNN + 量化 ncnn-20230309-windows-vs2019.zip

💡 解压 ncnn-20230309-windows-vs2019.zipD:\ncnn,你会得到:

  • D:\ncnn\tools\onnx\onnx2ncnn.exe
  • D:\ncnn\tools\quantize\quantize.exe(已预编译)

🔧 二、完整转换流程(6 步)


✅ 步骤 1:从 .pt 导出干净的 FP32 ONNX

# export_onnx.py
from ultralytics import YOLO

model = YOLO("yolov8n.pt")
model.export(
    format="onnx",
    imgsz=320,          # 或 160(推荐提速)
    opset=13,           # NCNN 兼容性最佳
    simplify=True,      # 合并冗余节点
    dynamic=False,      # 固定输入尺寸
    device="cpu"        # 避免 CUDA 依赖
)
print("✅ FP32 ONNX 已生成: yolov8n.onnx")

运行:

python export_onnx.py

📌 输出:yolov8n.onnx(确保无 int8=True


✅ 步骤 2:简化 ONNX 模型(可选但推荐)

pip install onnxsim
python -m onnxsim yolov8n.onnx yolov8n-sim.onnx

💡 这能解决 onnx2ncnn 的常见兼容性问题(如 Unsqueeze 节点)。


✅ 步骤 3:ONNX → NCNN(生成 .param + .bin

# 在 D:\ncnn\tools\onnx 目录下运行
onnx2ncnn.exe yolov8n-sim.onnx yolov8n.param yolov8n.bin

✅ 成功标志:生成 yolov8n.param(文本)和 yolov8n.bin(二进制权重)
❌ 如果报错 Unsupported SiLU:升级 NCNN 到 2023+ 版本(你下载的 20230309 已支持 SiLU)


✅ 步骤 4:准备校准图像列表

创建 calibration.txt,每行一个图片路径(绝对路径):

# gen_calib_txt.py
import os

img_dir = r"D:\Datasets\quantization_pic"
with open("calibration.txt", "w") as f:
    for file in os.listdir(img_dir):
        if file.lower().endswith(('.jpg', '.jpeg', '.png')):
            f.write(os.path.join(img_dir, file) + "\n")
print("✅ calibration.txt 已生成")

📌 建议:使用 100~300 张有代表性的图像。


✅ 步骤 5:NCNN INT8 量化

# 在 D:\ncnn\tools\quantize 目录下运行
quantize.exe yolov8n.param yolov8n.bin yolov8n-int8.param yolov8n-int8.bin calibration.txt

✅ 成功标志:生成 yolov8n-int8.paramyolov8n-int8.bin
📝 量化过程会自动计算 scale/zero_point 并内嵌到模型中。


✅ 步骤 6:C++ 推理代码(完整模板)

// yolov8_ncnn.cpp
#include <iostream>
#include <opencv2/opencv.hpp>
#include "net.h"

int main() {
    // 1. 加载模型
    ncnn::Net net;
    net.load_param("yolov8n-int8.param");
    net.load_model("yolov8n-int8.bin");
    net.set_num_threads(2); // i5-7200U / i7-6500U 双核

    // 2. 读取图像
    cv::Mat img = cv::imread("test.jpg");
    if (img.empty()) return -1;

    // 3. 预处理: BGR -> RGB, resize, normalize [0,1]
    ncnn::Mat in = ncnn::Mat::from_pixels_resize(
        img.data, ncnn::Mat::PIXEL_BGR2RGB, img.cols, img.rows, 320, 320
    );
    const float mean_vals[3] = {0.f, 0.f, 0.f};
    const float norm_vals[3] = {1/255.f, 1/255.f, 1/255.f};
    in.substract_mean_normalize(mean_vals, norm_vals);

    // 4. 推理
    ncnn::Extractor ex = net.create_extractor();
    ex.input("images", in); // 输入 blob 名(从 .param 确认)

    ncnn::Mat out;
    ex.extract("output0", out); // 输出 blob 名(YOLOv8 通常是 output0)

    // 5. 解析检测结果 (out: [N, 84])
    for (int i = 0; i < out.h; i++) {
        const float* values = out.row(i);
        float x = values[0];
        float y = values[1];
        float w = values[2];
        float h = values[3];
        float conf = values[4];
        if (conf > 0.25f) {
            std::cout << "Box: (" << x << "," << y << ") conf=" << conf << std::endl;
        }
    }

    return 0;
}
🔧 编译说明(Windows + VS2019):
  1. 下载 OpenCV 4.5.5 Windows 版
  2. ncnn/includencnn/lib 加入项目
  3. 链接库:ncnn.lib, opencv_world455.lib
  4. 运行时需 ncnn.dll(或静态链接)

💡 blob 名确认:用文本编辑器打开 yolov8n.param,查找:

Input            images           0 1 images
...
Split            splitncnn_0      1 2 output output0 output1

→ 输入名:images,输出名:output0


⚠️ 三、关键注意事项

1. 输入/输出 blob 名必须匹配

  • 用记事本打开 .param 文件确认 InputOutput 层的名字;
  • YOLOv8 通常输出为 output0(检测头)。

2. 预处理必须与训练一致

  • 归一化:/255.0(Ultralytics 默认)
  • 通道顺序:BGR2RGB(OpenCV 默认 BGR)

3. Windows 7 部署建议

  • 使用 静态链接 避免 DLL 依赖:
    set(NCNN_STATIC ON)
    
  • 或将 ncnn.dllopencv_world455.dll 放在 exe 同目录。

4. 性能预期(i5-7200U)

模型 输入尺寸 推理时间 内存占用
ONNX FP32 320×320 ~100 ms ~200 MB
NCNN INT8 320×320 6080 ms ~100 MB

提速 1.3~1.8x,内存减半 —— 这是在无 VNNI CPU 上的最佳结果。


📝 四、验证量化是否成功

  1. 检查文件大小

    • yolov8n.bin(FP32):约 6MB
    • yolov8n-int8.bin(INT8):约 3MB(减半)
  2. 运行 C++ 程序

    • 如果能正常输出检测框,说明 INT8 推理成功;
    • 对比 FP32 和 INT8 的输出差异(应 < 1e-2)。

✅ 五、总结流程图

graph LR
A[yolov8n.pt] --> B[export_onnx.py → yolov8n.onnx]
B --> C[onnxsim → yolov8n-sim.onnx]
C --> D[onnx2ncnn.exe → .param/.bin]
D --> E[gen_calib_txt.py → calibration.txt]
E --> F[quantize.exe → INT8 .param/.bin]
F --> G[C++ ncnn 推理]
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐