تخطي إلى المحتوى

تصدير MNN لنماذج YOLO26 والنشر

MNN

إطار استدلال الشبكة العصبية المتنقلة MNN

MNN هو إطار عمل للتعلم العميق عالي الكفاءة وخفيف الوزن. وهو يدعم الاستدلال والتدريب لنماذج التعلم العميق ولديه أداء رائد في الصناعة للاستدلال والتدريب على الجهاز. في الوقت الحاضر، تم دمج MNN في أكثر من 30 تطبيقًا لشركة Alibaba Inc، مثل Taobao و Tmall و Youku و DingTalk و Xianyu وما إلى ذلك، والتي تغطي أكثر من 70 سيناريو استخدام مثل البث المباشر والتقاط الفيديو القصير والتوصية بالبحث والبحث عن المنتجات عن طريق الصورة والتسويق التفاعلي وتوزيع الأسهم والتحكم في مخاطر الأمان. بالإضافة إلى ذلك، يتم استخدام MNN أيضًا على الأجهزة المدمجة، مثل إنترنت الأشياء.



شاهد: كيفية تصدير Ultralytics YOLO26 إلى تنسيق MNN | تسريع الاستدلال على الأجهزة المحمولة 📱

التصدير إلى MNN: تحويل نموذج YOLO26 الخاص بك

يمكنك توسيع توافق النموذج ومرونة النشر عن طريق تحويل نماذج Ultralytics YOLO إلى تنسيق MNN. يعمل هذا التحويل على تحسين النماذج الخاصة بك لبيئات الأجهزة المحمولة والمضمنة، مما يضمن أداءً فعالاً على الأجهزة ذات الموارد المحدودة.

التثبيت

لتثبيت الحزم المطلوبة، قم بتشغيل:

التثبيت

# Install the required package for YOLO26 and MNN
pip install ultralytics
pip install MNN

الاستخدام

تم تصميم جميع نماذج Ultralytics YOLO26 لدعم التصدير جاهزة للاستخدام، مما يسهل دمجها في سير عمل النشر المفضل لديك. يمكنك عرض القائمة الكاملة لتنسيقات التصدير المدعومة وخيارات التكوين لاختيار أفضل إعداد لتطبيقك.

الاستخدام

from ultralytics import YOLO

# Load the YOLO26 model
model = YOLO("yolo26n.pt")

# Export the model to MNN format
model.export(format="mnn")  # creates 'yolo26n.mnn'

# Load the exported MNN model
mnn_model = YOLO("yolo26n.mnn")

# Run inference
results = mnn_model("https://ultralytics.com/images/bus.jpg")
# Export a YOLO26n PyTorch model to MNN format
yolo export model=yolo26n.pt format=mnn # creates 'yolo26n.mnn'

# Run inference with the exported model
yolo predict model='yolo26n.mnn' source='https://ultralytics.com/images/bus.jpg'

وسائط التصدير

الوسيطةالنوعافتراضيالوصف
formatstr'mnn'تنسيق الهدف للنموذج الذي تم تصديره، والذي يحدد التوافق مع بيئات النشر المختلفة.
imgszint أو tuple640حجم الصورة المطلوب لإدخال النموذج. يمكن أن يكون عددًا صحيحًا للصور المربعة أو صفًا. (height, width) لأبعاد محددة.
halfboolFalseيتيح تكميم FP16 (نصف الدقة)، مما يقلل من حجم النموذج وربما يسرع الاستدلال على الأجهزة المدعومة.
int8boolFalseيقوم بتنشيط تكميم INT8، مما يزيد من ضغط النموذج وتسريع الاستدلال مع الحد الأدنى من فقدان الدقة، خاصةً للأجهزة الطرفية.
batchint1يحدد حجم الاستدلال الدفعي لنموذج التصدير أو الحد الأقصى لعدد الصور التي سيعالجها النموذج المصدر في وقت واحد في predict الوضع.
devicestrNoneيحدد الجهاز للتصدير: GPU (device=0)، وحدة معالجة مركزية (CPU) (device=cpu)، MPS لـ Apple silicon (device=mps).

لمزيد من التفاصيل حول عملية التصدير، قم بزيارة صفحة وثائق Ultralytics حول التصدير.

الاستدلال باستخدام MNN فقط

تم تنفيذ دالة تعتمد فقط على MNN لاستدلال YOLO26 والمعالجة المسبقة، وتوفر إصدارات 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 = 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)
#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: ./yolo26_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 YOLO26 إلى MNN واستخدام MNN للاستدلال. يوفر تنسيق MNN أداءً ممتازًا لتطبيقات الذكاء الاصطناعي الحافي، مما يجعله مثاليًا لنشر نماذج رؤية الكمبيوتر على الأجهزة ذات الموارد المحدودة.

لمزيد من الاستخدام، يرجى الرجوع إلى وثائق MNN.

الأسئلة الشائعة

كيف أقوم بتصدير نماذج Ultralytics YOLO26 إلى تنسيق MNN؟

لتصدير نموذج Ultralytics YOLO26 الخاص بك إلى تنسيق MNN، اتبع هذه الخطوات:

تصدير

from ultralytics import YOLO

# Load the YOLO26 model
model = YOLO("yolo26n.pt")

# Export to MNN format
model.export(format="mnn")  # creates 'yolo26n.mnn' with fp32 weight
model.export(format="mnn", half=True)  # creates 'yolo26n.mnn' with fp16 weight
model.export(format="mnn", int8=True)  # creates 'yolo26n.mnn' with int8 weight
yolo export model=yolo26n.pt format=mnn           # creates 'yolo26n.mnn' with fp32 weight
yolo export model=yolo26n.pt format=mnn half=True # creates 'yolo26n.mnn' with fp16 weight
yolo export model=yolo26n.pt format=mnn int8=True # creates 'yolo26n.mnn' with int8 weight

للحصول على خيارات تصدير مفصلة، تحقق من صفحة تصدير في الوثائق.

كيف أتنبأ باستخدام نموذج YOLO26 MNN مُصدَّر؟

للتنبؤ باستخدام نموذج YOLO26 MNN مُصدَّر، استخدم الـ predict الدالة من فئة YOLO.

توقع

from ultralytics import YOLO

# Load the YOLO26 MNN model
model = YOLO("yolo26n.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='yolo26n.mnn' source='https://ultralytics.com/images/bus.jpg'             # predict with `fp32`
yolo predict model='yolo26n.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 YOLO26 MNN على الأجهزة المحمولة؟

لنشر نماذج YOLO26 الخاصة بك على الأجهزة المحمولة:

  1. بناء لنظام Android: اتبع دليل MNN Android.
  2. بناء لنظام iOS: اتبع دليل MNN iOS.
  3. بناء لنظام Harmony: اتبع دليل MNN Harmony.


📅 تم الإنشاء قبل 1 عام ✏️ تم التحديث قبل 5 أيام
glenn-jocherjules-ailakshanthadLaughing-qRizwanMunawarlakshanthadwangzhaode

تعليقات