用于 YOLO26 模型和部署的 MNN 导出#
MNN#
MNN 是一个高效且轻量级的深度学习框架。它支持深度学习模型的推理与训练,并在端侧推理和训练方面具备行业领先的性能。目前,MNN 已集成到阿里巴巴集团的 30 多个应用中,例如淘宝、天猫、优酷、钉钉、闲鱼等,涵盖直播、短视频采集、搜索推荐、拍立淘、互动营销、权益发放、安全风控等 70 多个使用场景。此外,MNN 也被应用于物联网等嵌入式设备中。
Watch: How to Export Ultralytics YOLO26 to MNN Format | Speed up Inference on Mobile Devices📱
支持的任务#
MNN 导出支持所有七个 Ultralytics 任务。语义分割和深度估计仅在 YOLO26 中可用,这是唯一提供这些预测头的产品系列。
导出至 MNN:转换你的 YOLO26 模型#
你可以通过将 Ultralytics YOLO 模型转换为 MNN 格式,来扩展模型的兼容性与部署灵活性。此转换可针对移动和嵌入式环境优化你的模型,确保其在资源受限的设备上高效运行。
安装#
要安装所需的软件包,请运行:
# Install the required package for YOLO26 and MNN
pip install ultralytics
pip install MNN用法#
所有Ultralytics YOLO26 模型都旨在开箱即用支持导出,这使得将它们集成到你首选的部署工作流中变得轻而易举。你可以查看支持的导出格式和配置选项完整列表,为你的应用选择最佳设置。
MNN 格式支持导出、预测和验证模式。导出你的模型,然后加载导出的模型以运行推理或验证其准确性。
from ultralytics import YOLO
# Load a YOLO26 model
model = YOLO("yolo26n.pt")
# Export the model to MNN format
model.export(format="mnn") # creates 'yolo26n.mnn'from ultralytics import YOLO
# Load the exported MNN model
model = YOLO("yolo26n.mnn")
# Run inference
results = model("https://ultralytics.com/images/bus.jpg")from ultralytics import YOLO
# Load the exported MNN model
model = YOLO("yolo26n.mnn")
# Validate accuracy on the COCO8 dataset
metrics = model.val(data="coco8.yaml")导出参数#
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
format | str | 'mnn' | 导出模型的目标格式,定义了与各种部署环境的兼容性。 |
imgsz | int 或 tuple | 640 | 模型输入的所需图像大小。对于正方形图像可以是整数,或者对于特定尺寸可以是元组 (height, width)。 |
quantize | int 或 str | None | 量化精度:16(FP16)、8(INT8 权重量化),或者 32 / 未设置(FP32)。替换了已弃用的 half / int8 标志。 |
simplify | bool | True | 使用 onnxslim 简化中间 ONNX 图。 |
opset | int | None | 为中间 ONNX 图指定 ONNX opset 版本。如果未设置,则使用支持的最新版本。 |
batch | int | 1 | 指定导出模型的批处理推理大小,或导出的模型在 predict 模式下同时处理的最大图像数量。 |
dynamic | bool | False | 启用动态输入图像尺寸。不能与 nms=True 结合使用。 |
nms | bool | False | 为检测和姿态估计模型添加 NMS。不能与 dynamic=True 结合使用。 |
device | str | None | 指定用于导出的设备:GPU(device=0)、CPU(device=cpu)、适用于 Apple 硅芯片的 MPS(device=mps)。 |
有关导出过程的更多详细信息,请访问 Ultralytics 关于导出的文档页面。
仅使用 MNN 进行推理#
我们实现了一个仅依赖 MNN 进行 YOLO26 推理和预处理的函数,并提供了 Python 和 C++ 版本,方便在任何场景下进行部署。
import argparse
import MNN
import MNN.cv as cv2
import MNN.numpy as np
def inference(model, img, precision, backend, thread):
config = {}
config["precision"] = precision
config["backend"] = backend
config["numThread"] = thread
rt = MNN.nn.create_runtime_manager((config,))
# net = MNN.nn.load_module_from_file(model, ['images'], ['output0'], runtime_manager=rt)
net = MNN.nn.load_module_from_file(model, [], [], runtime_manager=rt)
original_image = cv2.imread(img)
ih, iw, _ = original_image.shape
length = max((ih, iw))
scale = length / 640
image = np.pad(original_image, [[0, length - ih], [0, length - iw], [0, 0]], "constant")
image = cv2.resize(
image, (640, 640), 0.0, 0.0, cv2.INTER_LINEAR, -1, [0.0, 0.0, 0.0], [1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0]
)
image = image[..., ::-1] # BGR to RGB
input_var = image[None]
input_var = MNN.expr.convert(input_var, MNN.expr.NC4HW4)
output_var = net.forward(input_var)
output_var = MNN.expr.convert(output_var, MNN.expr.NCHW)
output_var = output_var.squeeze()
# output_var shape: [84, 8400]; 84 means: [cx, cy, w, h, prob * 80]
cx = output_var[0]
cy = output_var[1]
w = output_var[2]
h = output_var[3]
probs = output_var[4:]
# [cx, cy, w, h] -> [y0, x0, y1, x1]
x0 = cx - w * 0.5
y0 = cy - h * 0.5
x1 = cx + w * 0.5
y1 = cy + h * 0.5
boxes = np.stack([x0, y0, x1, y1], axis=1)
# ensure ratio is within the valid range [0.0, 1.0]
boxes = np.clip(boxes, 0, 1)
# get max prob and idx
scores = np.max(probs, 0)
class_ids = np.argmax(probs, 0)
result_ids = MNN.expr.nms(boxes, scores, 100, 0.45, 0.25)
print(result_ids.shape)
# nms result box, score, ids
result_boxes = boxes[result_ids]
result_scores = scores[result_ids]
result_class_ids = class_ids[result_ids]
for i in range(len(result_boxes)):
x0, y0, x1, y1 = result_boxes[i].read_as_tuple()
y0 = int(y0 * scale)
y1 = int(y1 * scale)
x0 = int(x0 * scale)
x1 = int(x1 * scale)
# clamp to the original image size to handle cases where padding was applied
x1 = min(iw, x1)
y1 = min(ih, y1)
print(result_class_ids[i])
cv2.rectangle(original_image, (x0, y0), (x1, y1), (0, 0, 255), 2)
cv2.imwrite("res.jpg", original_image)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--model", type=str, required=True, help="the yolo26 model path")
parser.add_argument("--img", type=str, required=True, help="the input image path")
parser.add_argument("--precision", type=str, default="normal", help="inference precision: normal, low, high, lowBF")
parser.add_argument(
"--backend",
type=str,
default="CPU",
help="inference backend: CPU, OPENCL, OPENGL, NN, VULKAN, METAL, TRT, CUDA, HIAI",
)
parser.add_argument("--thread", type=int, default=4, help="inference using thread: int")
args = parser.parse_args()
inference(args.model, args.img, args.precision, args.backend, args.thread)总结#
在本指南中,我们介绍如何将 Ultralytics YOLO26 模型导出为 MNN 并使用 MNN 进行推理。MNN 格式为边缘 AI 应用提供了卓越的性能,使其非常适合在资源受限的设备上部署计算机视觉模型。
有关更多用法,请参考 MNN 文档。
常见问题解答#
要将你的 Ultralytics YOLO26 模型导出为 MNN 格式,请按照以下步骤操作:
导出from ultralytics import YOLO # Load a YOLO26 model model = YOLO("yolo26n.pt") # Export to MNN format model.export(format="mnn") # creates 'yolo26n.mnn' with fp32 weight model.export(format="mnn", quantize=16) # creates 'yolo26n.mnn' with fp16 weight model.export(format="mnn", quantize=8) # creates 'yolo26n.mnn' with int8 weight有关详细的导出选项,请查看文档中的导出页面。
要使用导出的 YOLO26 MNN 模型进行预测,请使用 YOLO 类中的
predict函数。预测from ultralytics import YOLO # Load the YOLO26 MNN model model = YOLO("yolo26n.mnn") # Run inference results = model("https://ultralytics.com/images/bus.jpg") # predict with `fp32` results = model("https://ultralytics.com/images/bus.jpg", quantize=16) # predict with `fp16` if device support for result in results: result.show() # display to screen result.save(filename="result.jpg") # save to diskMNN 功能强大且支持多种平台:
- 移动端:Android、iOS、Harmony。
- 嵌入式系统与物联网设备:诸如 Raspberry Pi 和 NVIDIA Jetson 等设备。
- 桌面端和服务器:Linux, Windows, macOS。
要在移动设备上部署你的 YOLO26 模型,请执行以下操作:
- 为 Android 构建:遵循 MNN Android 指南。
- 为 iOS 构建:遵循 MNN iOS 指南。
- 为 Harmony 构建:遵循 MNN Harmony 指南。