
人工智能大模型推理引擎深度学习本地部署模型量化模型优化多模态【免费下载链接】MNNMNN: A blazing-fast, lightweight inference engine battle-tested by Alibaba, powering high-performance on-device LLMs and Edge AI.项目地址https://gitcode.com/GitHub_Trending/mn/MNN点击查看免费下载本文以 MNN 仓库中 resource/model/Portrait/README.md 的核心说明为主线完整讲解如何获取 Google 发布的 DeepLabV3 语义分割模型TFLite 格式并使用 MNN 的模型转换工具 MNNConvert 将其转换为可部署的.mnn模型。文章结合仓库内的 C 分割 Demo 与 Android 实时人像分割 Demo 的源码覆盖下载模型 → 转换格式 → 预处理 → 推理 → 后处理出掩码的完整链路读者学完后可直接在桌面端或移动端复现一个人像分割抠人像应用。上图为仓库 docs/start/demo.md 中图像实例分割 Demodemo/exec/segment.cpp的官方效果示例输入任意图片后输出 257×257 的逐像素分割结果。一、模型背景为什么选择 DeepLabV3 257×257resource/model/Portrait/README.md的说明非常简洁但信息量集中在一个明确的落地上模型来源Google 官方发布的 TFLite GPU 模型deeplabv3_257_mv_gpu.tflite由 TensorFlow 训练并导出是一个轻量化的 DeepLabV3 语义分割模型输入尺寸模型名中的257即输入分辨率 257×257这在 Android Demo 源码中也有印证PortraitActivity.java 中netInputWidth 257; netInputHeight 257;输出语义模型输出 21 个类别的逐像素分割得分对应 Pascal VOC 的 21 类语义标签其中类别 15 对应 person人像。这一事实可从两处源码交叉验证C Demo 的 segment.cpp 中const int humanIndex 15;以及 JNI 后处理 mnnportraitnative.cpp 中对c 21个通道取最大值、并判断第 15 通道是否最大的逻辑转换方式README 明确指出 And Then Converted with MNNConvert即下载的 TFLite 模型需要通过 MNN 官方转换器转为.mnn格式后方可在 MNN 各后端CPU/GPU/Metal/OpenCL 等上运行。在 MNN 仓库中该模型主要用于两类落地场景桌面端图像分割 Demodemo/exec/segment.cpp对单张图片做人像分割并输出 PNG 掩码Android 端实时人像分割 DemoPortraitActivity.java将相机预览帧送入模型实时抠出人像并叠加显示。二、一键获取get_model.sh / get_model.py 自动下载与转换MNN 仓库提供了现成的模型获取脚本其中就包含 PortraitDeepLabV3模型的完整下载与转换逻辑。以 tools/script/get_model.sh 为例脚本专门封装了get_portrait_lite函数get_portrait_lite() { if [ ! -e $4 ]; then mkdir -p build pushd build /dev/null download $1 $2 succ$? popd /dev/null [ $succ -eq 0 ] ./$CONVERTER -f TFLITE --modelFile build/$2 --MNNModel $4 --bizCode 0000 --keepInputFormat0 fi }对应的人像模型下载与转换调用见 get_model.shget_portrait_lite \ https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/deeplabv3_257_mv_gpu.tflite \ deeplabv3_257_mv_gpu.tflite \ deeplabv3 \ model/Portrait/Portrait.tflite.mnn从脚本逻辑可以看到该流程的四个要点下载从 Google 官方地址下载deeplabv3_257_mv_gpu.tflite到临时目录build/转换调用编译产物build/MNNConvert指定框架类型-f TFLITE输出生成的 MNN 模型命名为Portrait.tflite.mnn存放在resource/model/Portrait/目录下关键参数--keepInputFormat0用于将原模型的 NHWC 输入布局自动转换为 MNN 内部更高效的NC4HW4布局详见下文第三节。仓库同时提供了 Python 版脚本 tools/script/get_model.py逻辑一致同样把 Portrait 模型输出到resource/model/Portrait/Portrait.tflite.mnn。使用前提需要先编译出MNNConvert。根据 project/android/demo/README.md 与 docs/tools/convert.md编译命令为cd path/to/MNN mkdir build cd build cmake -DMNN_BUILD_CONVERTERON .. make -j8编译完成后回到仓库根目录执行即可sh tools/script/get_model.sh三、手动下载与 MNNConvert 转换详解不依赖脚本时可以完全手动复现整个转换过程对应 project/android/demo/README.md 中 DeepLab_v3 一节第一步下载模型wget https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/deeplabv3_257_mv_gpu.tflite第二步使用 MNNConvert 转换为 MNN 模型./MNNConvert -f TFLITE --modelFile deeplabv3_257_mv_gpu.tflite --MNNModel Portrait.tflite.mnn第三步将产物放到仓库约定位置mv Portrait.tflite.mnn ../resource/model/Portrait/3.1 关键转换参数说明根据 docs/tools/convert.md 的完整参数表本次转换涉及的核心参数含义如下参数取值说明-f, --frameworkTFLITE源模型框架类型可选TF/CAFFE/ONNX/TFLITE/MNN/TORCH/JSON--modelFiledeeplabv3_257_mv_gpu.tflite待转换的源模型文件--MNNModelPortrait.tflite.mnn转换后保存的 MNN 模型文件名--keepInputFormat0不保持原始 NHWC 输入格式自动转为 MNN 内部 NC4HW4 布局便于与 ImageProcess 预处理结合--bizCode0000MNN 模型的业务标识脚本中统一使用0000其中--keepInputFormat0是分割类模型落地时值得重点关注的选项NHWC 是 TFLite 常用的数据排布而 MNN 内部尤其 CPU/GPU 后端对 NC4HW4 布局做了深度优化。转换时关闭输入格式保持可以让后续推理直接以 NC4HW4 张量运行配合ImageProcess预处理更高效。MNN 的官方文档在 docs/tools/convert.md 中也特别注明如果使用 Interpreter-Session C 接口开发因为 NC4HW4 便于与 ImageProcess 结合可以考虑在转换模型时使用自动内存布局--keepInputFormat0。3.2 可选的模型压缩参数如果希望在端侧进一步减小模型体积可以在转换命令中追加 docs/tools/convert.md 中的压缩选项例如./MNNConvert -f TFLITE --modelFile deeplabv3_257_mv_gpu.tflite --MNNModel Portrait_fp16.mnn --fp16--fp16将 conv/matmul/LSTM 的 float32 参数保存为 float16模型体积约减小一半精度基本无损--weightQuantBits 8对 conv/matmul/LSTM 的 float32 权值做 8bit 量化模型体积约减小 4 倍加载后解码回 float32运行速度与原始模型一致具体取舍可参考 docs/tools/mnncompress.md 与 docs/tools/compress.md 中的压缩流程。四、转换后的模型结构输入输出一览转换完成后可以用 MNNConvert 直接查看模型的基本信息输入名、输入形状、输出名等./MNNConvert -f MNN --modelFile Portrait.tflite.mnn --info结合 Android Demo 的源码可以确认该模型转换后的运行形态输入张量尺寸为1 × 3 × 257 × 257NCHW 视角。PortraitActivity.java 在运行时通过mInputTensor.getDimensions()动态读取输入维度第 2/3 维即高宽均为 257输出张量尺寸为1 × 257 × 257 × 21每个像素在 21 个类别上的得分Android Demo 中同样通过mOutputTensor.getDimensions()动态获取输出高宽分割目标取 21 个通道中得分最高的类别索引若索引为 15person则该像素属于人像。五、C 推理demo/exec/segment.cpp 完整流程仓库在 demo/exec/segment.cpp 中提供了使用该模型的完整 C Demo是理解如何用转换后的人像分割模型最直接的参考实现。5.1 构建根据 demo/exec/README.mdLinux/macOScd path/to/MNN mkdir build cd build cmake -DMNN_BUILD_DEMOON .. make -j8segment.out由 demo/exec/CMakeLists.txt 定义并链接 MNN 核心库。5.2 运行./segment.out model.mnn input.jpg result.png三个参数依次为MNN 模型路径、输入图片路径、输出 PNG 路径。5.3 输入预处理源码级解析segment.cpp 中的预处理逻辑如下Matrix trans; trans.setScale((float)(width-1) / (size_w-1), (float)(height-1) / (size_h-1)); ImageProcess::Config config; config.filterType CV::BILINEAR; float mean[3] {127.5f, 127.5f, 127.5f}; float normals[3] {0.00785f, 0.00785f, 0.00785f}; ::memcpy(config.mean, mean, sizeof(mean)); ::memcpy(config.normal, normals, sizeof(normals)); config.sourceFormat RGBA; config.destFormat RGB; std::shared_ptrImageProcess pretreat(ImageProcess::create(config)); pretreat-setMatrix(trans); pretreat-convert((uint8_t*)inputImage, width, height, 0, input);要点拆解缩放方式通过Matrix仿射矩阵将原图缩放到模型输入尺寸257×257filterType BILINEAR使用双线性插值对应 docs/cpp/ImageProcess.md 中Filter枚举的BILINEAR归一化mean 127.5、normal 2/255 ≈ 0.00785即对每个像素执行(pixel - 127.5) × (2/255)把 0~255 的像素值归一化到[-1, 1]区间与 TFLite 模型训练时的预处理保持一致格式转换源图以 RGBA 读入stbi_load(..., 4)转换为模型需要的 RGB 输出。5.4 输出后处理MNN Express 表达式 API推理完成后segment.cpp 使用 MNN 的 Express 接口完成取类别 → 生成掩码的后处理auto output Variable::create(Expr::create(outputTensor)); output _Convert(output, NHWC); // 转为 NHWC 便于逐像素处理 const int humanIndex 15; output _Reshape(output, {-1, channel}); auto kv _TopKV2(output, _Scalarint(1)); // 取每个像素得分最高的类别 auto index kv[1]; auto mask _Select(_Equal(index, _Scalarint(humanIndex)), _Scalarint(255), _Scalarint(0)); mask _Castuint8_t(mask); stbi_write_png(argv[3], width, height, 1, mask-readMapuint8_t(), width);这条链路清晰地体现了 MNN Express 的便捷性_Convert调整数据排布 →_Reshape展平为逐像素向量 →_TopKV2取最高分类别索引 →_Equal/_Select把是 person索引 15的像素置 255、其余置 0最终用stbi_write_png写出单通道掩码图。注释中还提供了性能更快的等价写法_Equal(index, humanIndex) * 255。六、Android 实时人像分割PortraitActivity 端到端流程仓库的 Android 工程project/android/demo将上述模型落地为相机实时人像分割应用入口为 PortraitActivity.java其完整调用链如下。6.1 模型加载与会话创建mMobileModelFileName Portrait/Portrait.tflite.mnn; // 模型位于 assets/Portrait/ 下 mMobileModelPath getCacheDir() /Portrait.tflite.mnn; Common.copyAssetResource2File(getBaseContext(), mMobileModelFileName, mMobileModelPath); mNetInstance MNNNetInstance.createFromFile(modelPath); mConfig new MNNNetInstance.Config(); mConfig.numThread 4; mConfig.forwardType MNNForwardType.FORWARD_AUTO.type; mSession mNetInstance.createSession(mConfig); mInputTensor mSession.getInput(null); mOutputTensor mSession.getOutput(null);可见 Android 端同样以Portrait.tflite.mnn为模型文件FORWARD_AUTO让运行时自动选择合适的后端CPU/GPU 均可numThread 4控制 CPU 多线程推理。6.2 相机帧预处理NV21 → RGB 归一化相机回调中PortraitActivity.java预览帧以 NV21 格式通过MNNImageProcess.convertBuffer送入输入张量MNNImageProcess.Config config new MNNImageProcess.Config(); config.mean new float[]{127.5f, 127.5f, 127.5f}; config.normal new float[]{2.0f / 255.0f, 2.0f / 255.0f, 2.0f / 255.0f}; config.source MNNImageProcess.Format.YUV_NV21; // 相机原始输出格式 config.dest MNNImageProcess.Format.RGB; // 模型需要的输入格式 int needRotateAngle (angle mRotateDegree) % 360; Matrix matrix new Matrix(); matrix.setScale(1.0f / imageWidth, 1.0f / imageHeight); matrix.postRotate(needRotateAngle, 0.5f, 0.5f); matrix.postScale(netInputWidth, netInputHeight); matrix.invert(matrix); MNNImageProcess.convertBuffer(data, imageWidth, imageHeight, mInputTensor, config, matrix);与 C Demo 的预处理完全一致mean 127.5、normal 2/255区别在于 Android 端由ImageProcess直接完成YUV_NV21 → RGB 的格式转换 旋转 缩放一次调用到位。相机参数与旋转角度的管理封装在 PortraitCameraView.java 中包括前后摄像头切换、预览尺寸选择与setDisplayOrientation处理。6.3 推理与 JNI 掩码可视化推理并取出输出张量数据后调用 JNI 方法将 21 通道的 logits 转为 ARGB 掩码位图mSession.run(); float[] mask mOutputTensor.getFloatData(); int[] pixels nativeConvertMaskToPixelsMultiChannels(mask, netOutputWidth * netOutputHeight); final Bitmap maskBitmap Bitmap.createBitmap(pixels, netOutputWidth, netOutputHeight, Bitmap.Config.ARGB_8888);JNI 实现在 source/jni/mnnportraitnative.cpp其核心逻辑为对每个像素遍历 21 个类别得分取最大值若最大得分来自第 15 类person则像素为不透明alpha255否则透明alpha0并以 ARGB 格式写入位图for (int l 0; l length; l) { int *dst dst32 l; float *src scores l; float max scores[l]; for (int c 0; c 21; c) { if (max src[c * length]) max src[c * length]; } unsigned a src[15 * length] max ? 0 : 255; // 非 person 置 0person 置 255 ... dst[0] a 24 | r 16 | g 8 | b; // ARGB }Java 侧接口声明见 MNNPortraitNative.java。最终由drawBitmap将掩码位图按屏幕尺寸缩放叠加在相机画面上即实现实时人像抠图效果。七、转换正确性校验与问题排查如果手动执行了转换建议用 MNN 官方校验脚本确认转换后 MNN 推理结果与原始 TFLite 一致。根据 docs/tools/convert.md 的正确性校验一节TFLite 模型对应的校验脚本是 tools/script/testMNNFromTflite.pycd build # 需要包含编译好的 MNNConvert python ../tools/script/testMNNFromTflite.py deeplabv3_257_mv_gpu.tflite前置条件pip install tensorflow若 build 目录下没有编译好的MNNConvert脚本会自动改用 pymnn 完成校验校验通过时最终输出会显示TEST_SUCCESS说明模型转换与推理结果正确若输出TESTERROR value error ...说明转换后推理结果存在偏差可配合可视化工具逐层定位出错的算子详见 docs/tools/test.md 与 docs/tools/visual.md。八、注意事项与常见问题输入布局转换时建议保留--keepInputFormat0自动转为 NC4HW4并确保预处理输出格式RGB/BGR与模型原始训练输入一致预处理参数一致性mean/normal 必须与模型训练时一致。本模型的官方预处理为(pixel - 127.5) × (2/255)归一化到 [-1,1]C Demo 与 Android Demo 均已按此配置自行接入时不要随意更改动态读取输入输出维度如 PortraitActivity.java 所示模型输入输出尺寸应通过getDimensions()动态获取而非写死避免与转换参数不一致导致张量越界模型文件位置转换产物统一放到resource/model/Portrait/Portrait.tflite.mnnAndroid 工程通过 assets 目录引用同名文件iOS 工程在 docs/start/demo.md 中说明使用sh ../tools/script/get_model.sh获取全部模型后由 Xcode 工程编译运行量化与体积若面向内存受限的端侧设备可参考第三节的--fp16/--weightQuantBits选项压缩模型并利用 docs/tools/mnncompress.md 提供的压缩工具箱做更细粒度的通道剪枝与量化。至此从resource/model/Portrait/README.md中短短几句话出发配合仓库源码我们已经完整走通了DeepLabV3 TFLite 模型下载 → MNNConvert 转换 → 桌面端/移动端人像分割推理 → 掩码可视化的全链路。该模型文件及相关脚本是理解 MNN 模型转换流程与图像分割落地的极佳起点相关源码demo/exec/segment.cpp、PortraitActivity.java、tools/script/get_model.sh可直接作为二次开发模板。赞分享人工智能大模型推理引擎深度学习本地部署模型量化模型优化多模态【免费下载链接】MNNMNN: A blazing-fast, lightweight inference engine battle-tested by Alibaba, powering high-performance on-device LLMs and Edge AI.项目地址https://gitcode.com/GitHub_Trending/mn/MNN点击查看免费下载相关推荐MNN 模型转换指南使用 MNNConvert 将 TF / Caffe / ONNX / TFLite / PyTorch 模型转为 .mnn 格式MNN 模型转换指南使用 MNNConvert 将 TF / Caffe / ONNX / TFLite / PyTorch 模型转为 .mnn 格式 MNN人工智能大模型推理引擎深度学习本地部署模型量化模型优化多模态计算机视觉嵌入式MNN 模型转换工具 MNNConvert 完全指南编译、多框架转换与源码原理MNN 模型转换工具 MNNConvert 完全指南编译、多框架转换与源码原理 MNNConvert 是 MNN 推理引擎自带的官方模型转换工具负责将 Te人工智能大模型推理引擎深度学习本地部署模型量化模型优化多模态计算机视觉嵌入式OpenCV TensorFlow 语义分割模型转换与推理实战基于 DeepLabV3-MobileNetV2 的端到端流程OpenCV TensorFlow 语义分割模型转换与推理实战基于 DeepLabV3 MobileNetV2 的端到端流程 本文以当前仓库 tf_sem_s计算机视觉图像处理深度学习机器学习创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考