Files
alibaba--mnn/docs/start/quickstart_cpp.md
T
2026-07-13 13:33:03 +08:00

141 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# C++ 快速开始
本教程带你从源码编译到 C++ 推理,完成一个端到端的图像分类任务。
## 1. 编译 MNN
```bash
cd MNN
mkdir build && cd build
cmake .. -DMNN_BUILD_CONVERTER=ON
make -j8
```
> 更多平台(iOS/Android/Windows)编译方式请参考 [从源码构建](../compile/engine.md)。
## 2. 转换模型
```bash
./MNNConvert -f ONNX --modelFile mobilenet_v1.onnx --MNNModel mobilenet_v1.mnn --weightQuantBits 8
```
## 3. 编写推理代码
使用推荐的 **Module API** 进行推理(参考 `demo/exec/pictureRecognition_module.cpp`):
```cpp
#include <stdio.h>
#include <MNN/expr/Module.hpp>
#include <MNN/expr/Executor.hpp>
#include <MNN/expr/ExprCreator.hpp>
#include <MNN/ImageProcess.hpp>
using namespace MNN;
using namespace MNN::Express;
int main(int argc, const char* argv[]) {
if (argc < 3) {
printf("Usage: ./classify model.mnn input.jpg\n");
return 1;
}
// 1. 创建 RuntimeManager 配置后端
ScheduleConfig sConfig;
sConfig.type = MNN_FORWARD_CPU;
sConfig.numThread = 4;
auto rtmgr = std::shared_ptr<Executor::RuntimeManager>(
Executor::RuntimeManager::createRuntimeManager(sConfig));
// 2. 加载模型(空 vector 表示自动检测输入输出名)
std::shared_ptr<Module> net(
Module::load({}, {}, argv[1], rtmgr));
if (!net) {
printf("Failed to load model\n");
return 1;
}
// 3. 创建输入 (NC4HW4 是 MNN 内部优化格式)
int width = 224, height = 224;
auto input = _Input({1, 3, height, width}, NC4HW4);
// 4. 图像预处理(使用 MNN ImageProcess
// 实际项目中用 stb_image/opencv 读图后用 ImageProcess 转换
// 此处简化为填充测试数据
auto inputPtr = input->writeMap<float>();
// ... 填充预处理后的图像数据到 inputPtr ...
input->unMap();
// 5. 推理
auto outputs = net->onForward({input});
// 6. 读取输出
auto output = _Convert(outputs[0], NHWC);
output = _Reshape(output, {0, -1});
auto outputPtr = output->readMap<float>();
// 找到概率最大的类别
int classId = 0;
float maxVal = outputPtr[0];
int outputSize = output->getInfo()->size;
for (int i = 1; i < outputSize; i++) {
if (outputPtr[i] > maxVal) {
maxVal = outputPtr[i];
classId = i;
}
}
printf("预测类别编号: %d, 置信度: %f\n", classId, maxVal);
return 0;
}
```
## 4. 编译并运行
在 MNN build 目录下:
```bash
g++ -std=c++11 -o classify classify.cpp \
-I ../include \
-L . -lMNN -lMNN_Express
./classify mobilenet_v1.mnn test.jpg
```
## 5. 完整的图像处理示例
实际项目中使用 `ImageProcess` 完成图像解码和预处理,参考 `demo/exec/pictureRecognition_module.cpp`,核心流程:
```cpp
#include <MNN/ImageProcess.hpp>
// 配置预处理参数
MNN::CV::ImageProcess::Config imgConfig;
imgConfig.filterType = MNN::CV::BILINEAR;
imgConfig.sourceFormat = MNN::CV::RGBA;
imgConfig.destFormat = MNN::CV::RGB;
imgConfig.mean[0] = 103.94f;
imgConfig.mean[1] = 116.78f;
imgConfig.mean[2] = 123.68f;
imgConfig.normal[0] = 0.017f;
imgConfig.normal[1] = 0.017f;
imgConfig.normal[2] = 0.017f;
auto pretreat = std::shared_ptr<MNN::CV::ImageProcess>(
MNN::CV::ImageProcess::create(imgConfig));
// 设置缩放矩阵
MNN::CV::Matrix trans;
trans.setScale((float)(inputWidth - 1) / (width - 1),
(float)(inputHeight - 1) / (height - 1));
pretreat->setMatrix(trans);
// 转换图像数据到 input VARP
pretreat->convert(imageData, inputWidth, inputHeight, 0,
input->writeMap<float>(), width, height, 4, 0,
halide_type_of<float>());
```
## 下一步
- [Module API 详解](../inference/module.md) — 完整的 C++ 推理接口说明
- [LLM 部署指南](../transformers/llm.md) — 部署大语言模型
- [模型压缩](../tools/compress.md) — 权值量化、离线量化等
- [Session API](../inference/session.md) — 低层推理接口(特殊场景使用)