YOLO11 ๋ชจ๋ธ ๋ฐ ๋ฐฐํฌ๋ฅผ ์ํ MNN ๋ด๋ณด๋ด๊ธฐ
MNN
MNN์ ๋งค์ฐ ํจ์จ์ ์ด๊ณ ๊ฐ๋ฒผ์ด ๋ฅ ๋ฌ๋ ํ๋ ์์ํฌ์ ๋๋ค. ๋ฅ๋ฌ๋ ๋ชจ๋ธ์ ์ถ๋ก ๊ณผ ํ์ต์ ์ง์ํ๋ฉฐ, ์ ๊ณ ์ต๊ณ ์์ค์ ์จ๋๋ฐ์ด์ค ์ถ๋ก ๋ฐ ํ์ต ์ฑ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ํ์ฌ MNN์ ํ์ค๋ฐ์ค, ํฐ๋ชฐ, ์ ์ฟ , ๋ฉํก, ์ ด์ ๋ฑ ์๋ฆฌ๋ฐ๋ฐ์ 30๊ฐ ์ด์์ ์ฑ์ ํตํฉ๋์ด ๋ผ์ด๋ธ ๋ฐฉ์ก, ์งง์ ๋์์ ์บก์ฒ, ๊ฒ์ ์ถ์ฒ, ์ด๋ฏธ์ง๋ก ์ํ ๊ฒ์, ๋ํํ ๋ง์ผํ , ์ฃผ์ ๋ถ๋ฐฐ, ๋ณด์ ์ํ ์ ์ด ๋ฑ 70๊ฐ ์ด์์ ์ฌ์ฉ ์๋๋ฆฌ์ค์ ์ ์ฉ๋๊ณ ์์ต๋๋ค. ๋ํ MNN์ IoT์ ๊ฐ์ ์๋ฒ ๋๋ ๋๋ฐ์ด์ค์์๋ ์ฌ์ฉ๋ฉ๋๋ค.
MNN์ผ๋ก ๋ด๋ณด๋ด๊ธฐ: YOLO11 ๋ชจ๋ธ ๋ณํํ๊ธฐ
YOLO11 ๋ชจ๋ธ์ 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")
์ง์๋๋ ๋ด๋ณด๋ด๊ธฐ ์ต์ ์ ๋ํ ์์ธํ ๋ด์ฉ์ ๋ฐฐํฌ ์ต์ ์ ๋ํUltralytics ๋ฌธ์ ํ์ด์ง๋ฅผ ์ฐธ์กฐํ์ธ์.
MNN ์ ์ฉ ์ถ๋ก
YOLO11 ์ถ๋ก ๋ฐ ์ ์ฒ๋ฆฌ๋ฅผ ์ํด MNN์๋ง ์์กดํ๋ ํจ์๊ฐ ๊ตฌํ๋์ด ์์ผ๋ฉฐ, 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]
)
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)
# 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)
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.});
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);
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;
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 ๋ฌธ์๋ฅผ ์ฐธ์กฐํ์ธ์.
์์ฃผ ๋ฌป๋ ์ง๋ฌธ
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
์์ธํ ๋ด๋ณด๋ด๊ธฐ ์ต์ ์ ๋ฌธ์์์ ๋ด๋ณด๋ด๊ธฐ ํ์ด์ง๋ฅผ ํ์ธํ์ธ์.
๋ด๋ณด๋ธ YOLO11 MNN ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ์์ธกํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ๋์?
๋ด๋ณด๋ธ YOLO11 MNN ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ์์ธกํ๋ ค๋ฉด ๋ค์์ ์ฌ์ฉํฉ๋๋ค. predict
ํจ์์์ YOLO ํด๋์ค์
์์ธก
from ultralytics import YOLO
# Load the YOLO11 MNN model
model = YOLO("yolo11n.mnn")
# Export to MNN format
results = mnn_model("https://ultralytics.com/images/bus.jpg") # predict with `fp32`
results = mnn_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
MNN์ ์ด๋ค ํ๋ซํผ์ ์ง์ํ๋์?
MNN์ ๋ค๋ชฉ์ ์ด๋ฉฐ ๋ค์ํ ํ๋ซํผ์ ์ง์ํฉ๋๋ค:
- Mobile: Android, iOS, ํ๋ชจ๋.
- ์๋ฒ ๋๋ ์์คํ ๋ฐ IoT ์ฅ์น: ๋ผ์ฆ๋ฒ ๋ฆฌ ํ์ด ๋ฐ NVIDIA Jetson๊ณผ ๊ฐ์ ์ฅ์น.
- ๋ฐ์คํฌํฑ ๋ฐ ์๋ฒ: Linux, Windows ๋ฐ macOS.
๋ชจ๋ฐ์ผ ๋๋ฐ์ด์ค์ Ultralytics YOLO11 MNN ๋ชจ๋ธ์ ๋ฐฐํฌํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ๋์?
๋ชจ๋ฐ์ผ ์ฅ์น์ YOLO11 ๋ชจ๋ธ์ ๋ฐฐํฌํ๋ ค๋ฉด:
- ๋น๋ Android: MNN์ ํ๋ก์ฐํ์ธ์ Android.
- ๋น๋ iOS: MNN์ ํ๋ก์ฐํ์ธ์ iOS.
- ํ๋ชจ๋๋ฅผ ์ํ ๋น๋: MNN ํ๋ชจ๋๋ฅผ ๋ฐ๋ฅด์ธ์.