تصدير MNN لنماذج YOLO11 والنشر
MNN
MNN هو إطار عمل للتعلم العميق عالي الكفاءة وخفيف الوزن. وهو يدعم الاستدلال والتدريب لنماذج التعلم العميق ولديه أداء رائد في الصناعة للاستدلال والتدريب على الجهاز. في الوقت الحاضر، تم دمج MNN في أكثر من 30 تطبيقًا لشركة Alibaba Inc، مثل Taobao و Tmall و Youku و DingTalk و Xianyu وما إلى ذلك، والتي تغطي أكثر من 70 سيناريو استخدام مثل البث المباشر والتقاط الفيديو القصير والتوصية بالبحث والبحث عن المنتجات عن طريق الصورة والتسويق التفاعلي وتوزيع الأسهم والتحكم في مخاطر الأمان. بالإضافة إلى ذلك، يتم استخدام MNN أيضًا على الأجهزة المدمجة، مثل إنترنت الأشياء.
التصدير إلى MNN: تحويل نموذج YOLO11 الخاص بك
يمكنك توسيع توافق النموذج ومرونة النشر عن طريق تحويل نماذج Ultralytics YOLO إلى تنسيق MNN. يعمل هذا التحويل على تحسين النماذج الخاصة بك لبيئات الأجهزة المحمولة والمضمنة، مما يضمن أداءً فعالاً على الأجهزة ذات الموارد المحدودة.
التثبيت
لتثبيت الحزم المطلوبة، قم بتشغيل:
التثبيت
# Install the required package for YOLO11 and MNN
pip install ultralytics
pip install MNN
الاستخدام
تم تصميم جميع نماذج Ultralytics YOLO11 لدعم التصدير خارج الصندوق، مما يسهل دمجها في سير عمل النشر المفضل لديك. يمكنك عرض القائمة الكاملة لتنسيقات التصدير المدعومة وخيارات التكوين لاختيار أفضل إعداد لتطبيقك.
الاستخدام
from ultralytics import YOLO
# Load the YOLO11 model
model = YOLO("yolo11n.pt")
# Export the model to MNN format
model.export(format="mnn") # creates 'yolo11n.mnn'
# Load the exported MNN model
mnn_model = YOLO("yolo11n.mnn")
# Run inference
results = mnn_model("https://ultralytics.com/images/bus.jpg")
# Export a YOLO11n PyTorch model to MNN format
yolo export model=yolo11n.pt format=mnn # creates 'yolo11n.mnn'
# Run inference with the exported model
yolo predict model='yolo11n.mnn' source='https://ultralytics.com/images/bus.jpg'
وسائط التصدير
الوسيطة | النوع | افتراضي | الوصف |
---|---|---|---|
format |
str |
'mnn' |
تنسيق الهدف للنموذج الذي تم تصديره، والذي يحدد التوافق مع بيئات النشر المختلفة. |
imgsz |
int أو tuple |
640 |
حجم الصورة المطلوب لإدخال النموذج. يمكن أن يكون عددًا صحيحًا للصور المربعة أو صفًا. (height, width) لأبعاد محددة. |
half |
bool |
False |
يتيح تكميم FP16 (نصف الدقة)، مما يقلل من حجم النموذج وربما يسرع الاستدلال على الأجهزة المدعومة. |
int8 |
bool |
False |
يقوم بتنشيط تكميم INT8، مما يزيد من ضغط النموذج وتسريع الاستدلال مع الحد الأدنى من فقدان الدقة، خاصةً للأجهزة الطرفية. |
batch |
int |
1 |
يحدد حجم الاستدلال الدفعي لنموذج التصدير أو الحد الأقصى لعدد الصور التي سيعالجها النموذج المصدر في وقت واحد في predict الوضع. |
device |
str |
None |
يحدد الجهاز للتصدير: GPU (device=0 )، وحدة معالجة مركزية (CPU) (device=cpu )، MPS لـ Apple silicon (device=mps ). |
لمزيد من التفاصيل حول عملية التصدير، قم بزيارة صفحة وثائق Ultralytics حول التصدير.
الاستدلال باستخدام MNN فقط
يتم تنفيذ وظيفة تعتمد فقط على MNN لاستنتاج YOLO11 والمعالجة المسبقة، مما يوفر إصدارات Python و C ++ لسهولة النشر في أي سيناريو.
MNN
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 = np.expand_dims(image, 0)
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 yolo11 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)
#include <stdio.h>
#include <MNN/ImageProcess.hpp>
#include <MNN/expr/Module.hpp>
#include <MNN/expr/Executor.hpp>
#include <MNN/expr/ExprCreator.hpp>
#include <MNN/expr/Executor.hpp>
#include <cv/cv.hpp>
using namespace MNN;
using namespace MNN::Express;
using namespace MNN::CV;
int main(int argc, const char* argv[]) {
if (argc < 3) {
MNN_PRINT("Usage: ./yolo11_demo.out model.mnn input.jpg [forwardType] [precision] [thread]\n");
return 0;
}
int thread = 4;
int precision = 0;
int forwardType = MNN_FORWARD_CPU;
if (argc >= 4) {
forwardType = atoi(argv[3]);
}
if (argc >= 5) {
precision = atoi(argv[4]);
}
if (argc >= 6) {
thread = atoi(argv[5]);
}
MNN::ScheduleConfig sConfig;
sConfig.type = static_cast<MNNForwardType>(forwardType);
sConfig.numThread = thread;
BackendConfig bConfig;
bConfig.precision = static_cast<BackendConfig::PrecisionMode>(precision);
sConfig.backendConfig = &bConfig;
std::shared_ptr<Executor::RuntimeManager> rtmgr = std::shared_ptr<Executor::RuntimeManager>(Executor::RuntimeManager::createRuntimeManager(sConfig));
if(rtmgr == nullptr) {
MNN_ERROR("Empty RuntimeManger\n");
return 0;
}
rtmgr->setCache(".cachefile");
std::shared_ptr<Module> net(Module::load(std::vector<std::string>{}, std::vector<std::string>{}, argv[1], rtmgr));
auto original_image = imread(argv[2]);
auto dims = original_image->getInfo()->dim;
int ih = dims[0];
int iw = dims[1];
int len = ih > iw ? ih : iw;
float scale = len / 640.0;
std::vector<int> padvals { 0, len - ih, 0, len - iw, 0, 0 };
auto pads = _Const(static_cast<void*>(padvals.data()), {3, 2}, NCHW, halide_type_of<int>());
auto image = _Pad(original_image, pads, CONSTANT);
image = resize(image, Size(640, 640), 0, 0, INTER_LINEAR, -1, {0., 0., 0.}, {1./255., 1./255., 1./255.});
image = cvtColor(image, COLOR_BGR2RGB);
auto input = _Unsqueeze(image, {0});
input = _Convert(input, NC4HW4);
auto outputs = net->onForward({input});
auto output = _Convert(outputs[0], NCHW);
output = _Squeeze(output);
// output shape: [84, 8400]; 84 means: [cx, cy, w, h, prob * 80]
auto cx = _Gather(output, _Scalar<int>(0));
auto cy = _Gather(output, _Scalar<int>(1));
auto w = _Gather(output, _Scalar<int>(2));
auto h = _Gather(output, _Scalar<int>(3));
std::vector<int> startvals { 4, 0 };
auto start = _Const(static_cast<void*>(startvals.data()), {2}, NCHW, halide_type_of<int>());
std::vector<int> sizevals { -1, -1 };
auto size = _Const(static_cast<void*>(sizevals.data()), {2}, NCHW, halide_type_of<int>());
auto probs = _Slice(output, start, size);
// [cx, cy, w, h] -> [y0, x0, y1, x1]
auto x0 = cx - w * _Const(0.5);
auto y0 = cy - h * _Const(0.5);
auto x1 = cx + w * _Const(0.5);
auto y1 = cy + h * _Const(0.5);
auto boxes = _Stack({x0, y0, x1, y1}, 1);
// ensure ratio is within the valid range [0.0, 1.0]
boxes = _Maximum(boxes, _Scalar<float>(0.0f));
boxes = _Minimum(boxes, _Scalar<float>(1.0f));
auto scores = _ReduceMax(probs, {0});
auto ids = _ArgMax(probs, 0);
auto result_ids = _Nms(boxes, scores, 100, 0.45, 0.25);
auto result_ptr = result_ids->readMap<int>();
auto box_ptr = boxes->readMap<float>();
auto ids_ptr = ids->readMap<int>();
auto score_ptr = scores->readMap<float>();
for (int i = 0; i < 100; i++) {
auto idx = result_ptr[i];
if (idx < 0) break;
auto x0 = box_ptr[idx * 4 + 0] * scale;
auto y0 = box_ptr[idx * 4 + 1] * scale;
auto x1 = box_ptr[idx * 4 + 2] * scale;
auto y1 = box_ptr[idx * 4 + 3] * scale;
// clamp to the original image size to handle cases where padding was applied
x1 = std::min(static_cast<float>(iw), x1);
y1 = std::min(static_cast<float>(ih), y1);
auto class_idx = ids_ptr[idx];
auto score = score_ptr[idx];
rectangle(original_image, {x0, y0}, {x1, y1}, {0, 0, 255}, 2);
}
if (imwrite("res.jpg", original_image)) {
MNN_PRINT("result image write to `res.jpg`.\n");
}
rtmgr->updateCache();
return 0;
}
ملخص
في هذا الدليل، نقدم كيفية تصدير نموذج Ultralytics YOLO11 إلى MNN واستخدام MNN للاستدلال. يوفر تنسيق MNN أداءً ممتازًا لتطبيقات الذكاء الاصطناعي الطرفي، مما يجعله مثاليًا لنشر نماذج رؤية الكمبيوتر على الأجهزة ذات الموارد المحدودة.
لمزيد من الاستخدام، يرجى الرجوع إلى وثائق MNN.
الأسئلة الشائعة
كيف يمكنني تصدير نماذج Ultralytics YOLO11 إلى تنسيق MNN؟
لتصدير نموذج Ultralytics YOLO11 الخاص بك إلى تنسيق MNN، اتبع الخطوات التالية:
تصدير
from ultralytics import YOLO
# Load the YOLO11 model
model = YOLO("yolo11n.pt")
# Export to MNN format
model.export(format="mnn") # creates 'yolo11n.mnn' with fp32 weight
model.export(format="mnn", half=True) # creates 'yolo11n.mnn' with fp16 weight
model.export(format="mnn", int8=True) # creates 'yolo11n.mnn' with int8 weight
yolo export model=yolo11n.pt format=mnn # creates 'yolo11n.mnn' with fp32 weight
yolo export model=yolo11n.pt format=mnn half=True # creates 'yolo11n.mnn' with fp16 weight
yolo export model=yolo11n.pt format=mnn int8=True # creates 'yolo11n.mnn' with int8 weight
للحصول على خيارات تصدير مفصلة، تحقق من صفحة تصدير في الوثائق.
كيف يمكنني التنبؤ بنموذج YOLO11 MNN الذي تم تصديره؟
للتنبؤ باستخدام نموذج YOLO11 MNN مُصدَّر، استخدم predict
الدالة من فئة YOLO.
توقع
from ultralytics import YOLO
# Load the YOLO11 MNN model
model = YOLO("yolo11n.mnn")
# Export to MNN format
results = model("https://ultralytics.com/images/bus.jpg") # predict with `fp32`
results = model("https://ultralytics.com/images/bus.jpg", half=True) # predict with `fp16` if device support
for result in results:
result.show() # display to screen
result.save(filename="result.jpg") # save to disk
yolo predict model='yolo11n.mnn' source='https://ultralytics.com/images/bus.jpg' # predict with `fp32`
yolo predict model='yolo11n.mnn' source='https://ultralytics.com/images/bus.jpg' --half=True # predict with `fp16` if device support
ما هي الأنظمة الأساسية المدعومة لـ MNN؟
MNN متعدد الاستخدامات ويدعم العديد من المنصات:
- الأجهزة المحمولة: Android و iOS و Harmony.
- Embedded Systems and IoT Devices: أجهزة مثل Raspberry Pi و NVIDIA Jetson.
- أجهزة سطح المكتب والخوادم: Linux و Windows و macOS.
كيف يمكنني نشر نماذج Ultralytics YOLO11 MNN على الأجهزة المحمولة؟
لنشر نماذج YOLO11 الخاصة بك على الأجهزة المحمولة:
- بناء لنظام Android: اتبع دليل MNN Android.
- بناء لنظام iOS: اتبع دليل MNN iOS.
- بناء لنظام Harmony: اتبع دليل MNN Harmony.