Commit 546b4279 authored by limm's avatar limm
Browse files

add csrc and mmdeploy module

parent 502f4fb9
Pipeline #2810 canceled with stages
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class mmdeploy_TextDetector */
#ifndef _Included_mmdeploy_TextDetector
#define _Included_mmdeploy_TextDetector
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: mmdeploy_TextDetector
* Method: create
* Signature: (Ljava/lang/String;Ljava/lang/String;I)J
*/
JNIEXPORT jlong JNICALL Java_mmdeploy_TextDetector_create(JNIEnv *, jobject, jstring, jstring,
jint);
/*
* Class: mmdeploy_TextDetector
* Method: destroy
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_mmdeploy_TextDetector_destroy(JNIEnv *, jobject, jlong);
/*
* Class: mmdeploy_TextDetector
* Method: apply
* Signature: (J[Lmmdeploy/Mat;[I)[Lmmdeploy/TextDetector/Result;
*/
JNIEXPORT jobjectArray JNICALL Java_mmdeploy_TextDetector_apply(JNIEnv *, jobject, jlong,
jobjectArray, jintArray);
#ifdef __cplusplus
}
#endif
#endif
#include "mmdeploy_TextRecognizer.h"
#include <numeric>
#include "mmdeploy/apis/c/mmdeploy/text_recognizer.h"
#include "mmdeploy/apis/java/native/common.h"
#include "mmdeploy/core/logger.h"
jlong Java_mmdeploy_TextRecognizer_create(JNIEnv *env, jobject, jstring modelPath,
jstring deviceName, jint device_id) {
auto model_path = env->GetStringUTFChars(modelPath, nullptr);
auto device_name = env->GetStringUTFChars(deviceName, nullptr);
mmdeploy_text_recognizer_t text_recognizer{};
auto ec = mmdeploy_text_recognizer_create_by_path(model_path, device_name, (int)device_id,
&text_recognizer);
env->ReleaseStringUTFChars(modelPath, model_path);
env->ReleaseStringUTFChars(deviceName, device_name);
if (ec) {
MMDEPLOY_ERROR("failed to create text recognizer, code = {}", ec);
return -1;
}
return (jlong)text_recognizer;
}
void Java_mmdeploy_TextRecognizer_destroy(JNIEnv *, jobject, jlong handle) {
MMDEPLOY_DEBUG("Java_mmdeploy_TextRecognizer_destroy"); // maybe use info?
mmdeploy_text_recognizer_destroy((mmdeploy_text_recognizer_t)handle);
}
jobjectArray Java_mmdeploy_TextRecognizer_apply(JNIEnv *env, jobject thiz, jlong handle,
jobjectArray images) {
return With(env, images, [&](const mmdeploy_mat_t imgs[], int size) -> jobjectArray {
mmdeploy_text_recognition_t *results{};
auto ec =
mmdeploy_text_recognizer_apply((mmdeploy_text_recognizer_t)handle, imgs, size, &results);
if (ec) {
MMDEPLOY_ERROR("failed to apply text recognizer, code = {}", ec);
return NULL;
}
auto result_cls = env->FindClass("mmdeploy/TextRecognizer$Result");
auto result_ctor = env->GetMethodID(result_cls, "<init>", "([C[F)V");
auto array = env->NewObjectArray(size, result_cls, nullptr);
for (int i = 0; i < size; ++i) {
auto text = env->NewCharArray(results[i].length);
auto score = env->NewFloatArray(results[i].length);
env->SetCharArrayRegion(text, 0, results[i].length, (jchar *)results[i].text);
env->SetFloatArrayRegion(score, 0, results[i].length, (jfloat *)results[i].score);
auto res = env->NewObject(result_cls, result_ctor, text, score);
env->SetObjectArrayElement(array, i, res);
}
mmdeploy_text_recognizer_release_result(results, size);
return array;
});
}
jobjectArray Java_mmdeploy_TextRecognizer_applyBbox(JNIEnv *env, jobject thiz, jlong handle,
jobjectArray images, jobjectArray bboxes,
jintArray bbox_count) {
return With(env, images, [&](const mmdeploy_mat_t imgs[], int size) {
mmdeploy_text_recognition_t *recog_results{};
auto *det_results = new mmdeploy_text_detection_t[env->GetArrayLength(bboxes)];
int *det_result_count = new int[env->GetArrayLength(bbox_count)];
auto bbox_cls = env->FindClass("mmdeploy/TextDetector$Result");
auto pointf_cls = env->FindClass("mmdeploy/PointF");
auto bbox_id = env->GetFieldID(bbox_cls, "bbox", "[Lmmdeploy/PointF;");
auto score_id = env->GetFieldID(bbox_cls, "score", "F");
auto x_id = env->GetFieldID(pointf_cls, "x", "F");
auto y_id = env->GetFieldID(pointf_cls, "y", "F");
env->GetIntArrayRegion(bbox_count, 0, env->GetArrayLength(bbox_count), det_result_count);
int total_bboxes = env->GetArrayLength(bboxes);
for (int i = 0; i < total_bboxes; ++i) {
auto bboxi = env->GetObjectArrayElement(bboxes, i);
auto point_array = (jobjectArray)env->GetObjectField(bboxi, bbox_id);
for (int j = 0; j < 4; ++j) {
auto pointj = env->GetObjectArrayElement(point_array, j);
det_results[i].bbox[j].x = (float)env->GetFloatField(pointj, x_id);
det_results[i].bbox[j].y = (float)env->GetFloatField(pointj, y_id);
det_results[i].score = (float)env->GetFloatField(bboxi, score_id);
}
}
auto ec = mmdeploy_text_recognizer_apply_bbox((mmdeploy_text_recognizer_t)handle, imgs, size,
(const mmdeploy_text_detection_t *)det_results,
det_result_count, &recog_results);
if (ec) {
MMDEPLOY_ERROR("failed to apply bbox for text recognizer, code = {}", ec);
}
auto result_cls = env->FindClass("mmdeploy/TextRecognizer$Result");
auto result_ctor = env->GetMethodID(result_cls, "<init>", "([B[F)V");
auto array = env->NewObjectArray(total_bboxes, result_cls, nullptr);
for (int i = 0; i < total_bboxes; ++i) {
auto text = env->NewByteArray(recog_results[i].length);
auto score = env->NewFloatArray(recog_results[i].length);
env->SetByteArrayRegion(text, 0, recog_results[i].length, (jbyte *)recog_results[i].text);
env->SetFloatArrayRegion(score, 0, recog_results[i].length, (jfloat *)recog_results[i].score);
auto res = env->NewObject(result_cls, result_ctor, text, score);
env->SetObjectArrayElement(array, i, res);
}
mmdeploy_text_recognizer_release_result(recog_results, size);
mmdeploy_text_detector_release_result(det_results, det_result_count, 1);
return array;
});
}
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class mmdeploy_TextRecognizer */
#ifndef _Included_mmdeploy_TextRecognizer
#define _Included_mmdeploy_TextRecognizer
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: mmdeploy_TextRecognizer
* Method: create
* Signature: (Ljava/lang/String;Ljava/lang/String;I)J
*/
JNIEXPORT jlong JNICALL Java_mmdeploy_TextRecognizer_create(JNIEnv *, jobject, jstring, jstring,
jint);
/*
* Class: mmdeploy_TextRecognizer
* Method: destroy
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_mmdeploy_TextRecognizer_destroy(JNIEnv *, jobject, jlong);
/*
* Class: mmdeploy_TextRecognizer
* Method: apply
* Signature: (J[Lmmdeploy/Mat;)[Lmmdeploy/TextRecognizer/Result;
*/
JNIEXPORT jobjectArray JNICALL Java_mmdeploy_TextRecognizer_apply(JNIEnv *, jobject, jlong,
jobjectArray);
/*
* Class: mmdeploy_TextRecognizer
* Method: applyBbox
* Signature: (J[Lmmdeploy/Mat;[Lmmdeploy/TextDetector/Result;[I)[Lmmdeploy/TextRecognizer/Result;
*/
JNIEXPORT jobjectArray JNICALL Java_mmdeploy_TextRecognizer_applyBbox(JNIEnv *, jobject, jlong,
jobjectArray, jobjectArray,
jintArray);
#ifdef __cplusplus
}
#endif
#endif
# Copyright (c) OpenMMLab. All rights reserved.
cmake_minimum_required(VERSION 3.14)
project(mmdeploy_runtime)
set(MMDEPLOY_RUNTIME_SRCS
common.cpp
internal.cpp
pipeline.cpp)
set(CMAKE_CXX_STANDARD 17)
if (${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME})
# standard alone project
add_subdirectory(${CMAKE_SOURCE_DIR}/../../../../third_party/pybind11
${CMAKE_CURRENT_BINARY_DIR}/pybind11)
find_package(MMDeploy REQUIRED)
elseif (NOT TARGET pybind11)
add_subdirectory(${CMAKE_SOURCE_DIR}/third_party/pybind11 pybind11)
endif ()
foreach (task_name ${MMDEPLOY_TASKS})
list(APPEND MMDEPLOY_RUNTIME_SRCS ${task_name}.cpp)
endforeach ()
pybind11_add_module(${PROJECT_NAME} ${MMDEPLOY_RUNTIME_SRCS})
# disable MMDEPLOY_CXX_USE_OPENCV in apis/cxx/mmdeploy/common.hpp
target_compile_definitions(${PROJECT_NAME} PRIVATE -DMMDEPLOY_CXX_USE_OPENCV=0)
if (APPLE)
set_target_properties(${PROJECT_NAME} PROPERTIES
BUILD_RPATH "@loader_path"
INSTALL_RPATH "@loader_path")
else ()
set_target_properties(${PROJECT_NAME} PROPERTIES
BUILD_RPATH "\$ORIGIN"
INSTALL_RPATH "\$ORIGIN")
endif ()
# https://github.com/pybind/pybind11/issues/1604
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
target_compile_options(${PROJECT_NAME} PRIVATE -fsized-deallocation)
endif ()
if (MMDEPLOY_BUILD_SDK_MONOLITHIC)
target_link_libraries(${PROJECT_NAME} PRIVATE mmdeploy)
else ()
mmdeploy_load_static(${PROJECT_NAME} MMDeployStaticModules)
mmdeploy_load_dynamic(${PROJECT_NAME} MMDeployDynamicModules)
target_link_libraries(${PROJECT_NAME} PRIVATE MMDeployLibs)
endif ()
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/..
${CMAKE_CURRENT_SOURCE_DIR})
install(DIRECTORY ${CMAKE_SOURCE_DIR}/demo/python/ DESTINATION example/python)
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/classifier.h"
#include "common.h"
namespace mmdeploy::python {
class PyClassifier {
public:
PyClassifier(const char* model_path, const char* device_name, int device_id) {
auto status =
mmdeploy_classifier_create_by_path(model_path, device_name, device_id, &classifier_);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to create classifier");
}
}
~PyClassifier() {
mmdeploy_classifier_destroy(classifier_);
classifier_ = {};
}
std::vector<std::vector<std::tuple<int, float>>> Apply(const std::vector<PyImage>& imgs) {
std::vector<mmdeploy_mat_t> mats;
mats.reserve(imgs.size());
for (const auto& img : imgs) {
auto mat = GetMat(img);
mats.push_back(mat);
}
mmdeploy_classification_t* results{};
int* result_count{};
auto status = mmdeploy_classifier_apply(classifier_, mats.data(), (int)mats.size(), &results,
&result_count);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to apply classifier, code: " + std::to_string(status));
}
auto output = std::vector<std::vector<std::tuple<int, float>>>{};
output.reserve(mats.size());
auto result_ptr = results;
for (int i = 0; i < mats.size(); ++i) {
std::vector<std::tuple<int, float>> label_score;
for (int j = 0; j < result_count[i]; ++j) {
label_score.emplace_back(result_ptr[j].label_id, result_ptr[j].score);
}
output.push_back(std::move(label_score));
result_ptr += result_count[i];
}
mmdeploy_classifier_release_result(results, result_count, (int)mats.size());
return output;
}
private:
mmdeploy_classifier_t classifier_{};
};
static PythonBindingRegisterer register_classifier{[](py::module& m) {
py::class_<PyClassifier>(m, "Classifier")
.def(py::init([](const char* model_path, const char* device_name, int device_id) {
return std::make_unique<PyClassifier>(model_path, device_name, device_id);
}),
py::arg("model_path"), py::arg("device_name"), py::arg("device_id") = 0)
.def("__call__",
[](PyClassifier* self, const PyImage& img) { return self->Apply(std::vector{img})[0]; })
.def("batch", &PyClassifier::Apply);
}};
} // namespace mmdeploy::python
// Copyright (c) OpenMMLab. All rights reserved.
#include "common.h"
#include "mmdeploy/common.hpp"
#include "mmdeploy/core/model.h"
#include "mmdeploy/core/utils/formatter.h"
#include "pybind11/numpy.h"
namespace mmdeploy::python {
std::vector<void (*)(py::module&)>& gPythonBindings() {
static std::vector<void (*)(py::module&)> v;
return v;
}
mmdeploy_mat_t GetMat(const PyImage& img) {
auto info = img.request();
if (info.ndim != 3) {
fprintf(stderr, "info.ndim = %d\n", (int)info.ndim);
throw std::runtime_error("continuous uint8 HWC array expected");
}
auto channels = (int)info.shape[2];
mmdeploy_mat_t mat{};
if (channels == 1) {
mat.format = MMDEPLOY_PIXEL_FORMAT_GRAYSCALE;
} else if (channels == 3) {
mat.format = MMDEPLOY_PIXEL_FORMAT_BGR;
} else {
throw std::runtime_error("images of 1 or 3 channels are supported");
}
mat.height = (int)info.shape[0];
mat.width = (int)info.shape[1];
mat.channel = channels;
mat.type = MMDEPLOY_DATA_TYPE_UINT8;
mat.data = (uint8_t*)info.ptr;
return mat;
}
py::object ToPyObject(const Value& value) {
switch (value.type()) {
case ValueType::kNull:
return py::none();
case ValueType::kBool:
return py::bool_(value.get<bool>());
case ValueType::kInt:
return py::int_(value.get<int64_t>());
case ValueType::kUInt:
return py::int_(value.get<uint64_t>());
case ValueType::kFloat:
return py::float_(value.get<double>());
case ValueType::kString:
return py::str(value.get<std::string>());
case ValueType::kArray: {
py::list list;
for (const auto& x : value) {
list.append(ToPyObject(x));
}
return list;
}
case ValueType::kObject: {
py::dict dict;
for (auto it = value.begin(); it != value.end(); ++it) {
dict[it.key().c_str()] = ToPyObject(*it);
}
return dict;
}
case ValueType::kAny:
return py::str("<any>");
default:
return py::str("<unknown>");
}
}
std::optional<Value> _to_value_internal(const void* object, mmdeploy_context_type_t type);
Value FromPyObject(const py::object& obj) {
if (py::isinstance<py::none>(obj)) {
return nullptr;
} else if (py::isinstance<py::bool_>(obj)) {
return obj.cast<bool>();
} else if (py::isinstance<py::int_>(obj)) {
return obj.cast<int>();
} else if (py::isinstance<py::float_>(obj)) {
return obj.cast<double>();
} else if (py::isinstance<py::str>(obj)) {
return obj.cast<std::string>();
} else if (py::isinstance<py::list>(obj) || py::isinstance<py::tuple>(obj)) {
py::list src(obj);
Value::Array dst;
dst.reserve(src.size());
for (const auto& item : src) {
dst.push_back(FromPyObject(py::reinterpret_borrow<py::object>(item)));
}
return dst;
} else if (py::isinstance<py::dict>(obj)) {
py::dict src(obj);
Value::Object dst;
for (const auto& item : src) {
dst.emplace(item.first.cast<std::string>(),
FromPyObject(py::reinterpret_borrow<py::object>(item.second)));
}
return dst;
} else if (py::isinstance<py::array>(obj)) {
const auto& array = obj.cast<py::array>();
return *_to_value_internal(&array, MMDEPLOY_TYPE_MAT);
} else if (py::isinstance<Model>(obj)) {
const auto& model =
*reinterpret_cast<framework::Model*>(static_cast<mmdeploy_model_t>(obj.cast<Model>()));
return model;
} else {
std::stringstream ss;
ss << obj.get_type();
MMDEPLOY_ERROR("unsupported Python object type: {}", ss.str());
return nullptr;
}
return nullptr;
}
std::pair<std::string, int> parse_device(const std::string& device) {
auto pos = device.find(':');
if (pos == std::string::npos) {
return {device, 0}; // logic for index -1 is not ready on some devices
}
auto name = device.substr(0, pos);
auto index = std::stoi(device.substr(pos + 1));
return {name, index};
}
static PythonBindingRegisterer register_model{[](py::module& m) {
py::class_<Model>(m, "Model")
.def(py::init([](const py::str& path) {
MMDEPLOY_DEBUG("py::init([](const py::str& path)");
return Model(path.cast<std::string>().c_str());
}))
.def(py::init([](const py::bytes& buffer) {
MMDEPLOY_DEBUG("py::init([](const py::bytes& buffer)");
py::buffer_info info(py::buffer(buffer).request());
return Model(info.ptr, info.size);
}));
}};
static PythonBindingRegisterer register_device{[](py::module& m) {
py::class_<Device>(m, "Device")
.def(py::init([](const std::string& device) {
auto [name, index] = parse_device(device);
return Device(name, index);
}))
.def(py::init([](const std::string& name, int index) { return Device(name, index); }));
}};
static PythonBindingRegisterer register_context{[](py::module& m) {
py::class_<Context>(m, "Context")
.def(py::init([](const Device& device) { return Context(device); }))
.def("add", [](Context* self, const std::string& name, const Scheduler& sched) {
self->Add(name, sched);
});
}};
static PythonBindingRegisterer register_scheduler{[](py::module& m) {
py::class_<Scheduler>(m, "Scheduler")
.def_static("thread_pool", [](int n_workers) { return Scheduler::ThreadPool(n_workers); })
.def_static("thread", [] { return Scheduler::Thread(); });
}};
} // namespace mmdeploy::python
PYBIND11_MODULE(mmdeploy_runtime, m) {
for (const auto& f : mmdeploy::python::gPythonBindings()) {
f(m);
}
}
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_CSRC_APIS_PYTHON_COMMON_H_
#define MMDEPLOY_CSRC_APIS_PYTHON_COMMON_H_
#include <stdexcept>
#include "mmdeploy/common.h"
#include "mmdeploy/core/value.h"
#include "pybind11/numpy.h"
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"
namespace py = pybind11;
namespace mmdeploy::python {
using PyImage = py::array_t<uint8_t, py::array::c_style | py::array::forcecast>;
std::vector<void (*)(py::module&)>& gPythonBindings();
mmdeploy_mat_t GetMat(const PyImage& img);
py::object ToPyObject(const Value& value);
Value FromPyObject(const py::object& obj);
class PythonBindingRegisterer {
public:
explicit PythonBindingRegisterer(void (*register_fn)(py::module& m)) {
gPythonBindings().push_back(register_fn);
}
};
} // namespace mmdeploy::python
#endif // MMDEPLOY_CSRC_APIS_PYTHON_COMMON_H_
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/detector.h"
#include "common.h"
namespace mmdeploy::python {
class PyDetector {
public:
PyDetector(const char* model_path, const char* device_name, int device_id) {
auto status = mmdeploy_detector_create_by_path(model_path, device_name, device_id, &detector_);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to create detector");
}
}
py::list Apply(const std::vector<PyImage>& imgs) {
std::vector<mmdeploy_mat_t> mats;
mats.reserve(imgs.size());
for (const auto& img : imgs) {
auto mat = GetMat(img);
mats.push_back(mat);
}
mmdeploy_detection_t* detection{};
int* result_count{};
auto status = mmdeploy_detector_apply(detector_, mats.data(), (int)mats.size(), &detection,
&result_count);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to apply detector, code: " + std::to_string(status));
}
using Sptr = std::shared_ptr<mmdeploy_detection_t>;
Sptr holder(detection, [result_count, n = mats.size()](auto p) {
mmdeploy_detector_release_result(p, result_count, n);
});
auto output = py::list{};
auto result = detection;
for (int i = 0; i < mats.size(); ++i) {
auto bboxes = py::array_t<float>({result_count[i], 5});
auto labels = py::array_t<int>(result_count[i]);
auto masks = std::vector<py::array>();
masks.reserve(result_count[i]);
for (int j = 0; j < result_count[i]; ++j, ++result) {
auto bbox = bboxes.mutable_data(j);
bbox[0] = result->bbox.left;
bbox[1] = result->bbox.top;
bbox[2] = result->bbox.right;
bbox[3] = result->bbox.bottom;
bbox[4] = result->score;
labels.mutable_at(j) = result->label_id;
if (result->mask) {
masks.emplace_back(std::array{result->mask->height, result->mask->width}, // shape
reinterpret_cast<uint8_t*>(result->mask->data), // data
py::capsule(new Sptr(holder), // handle
[](void* p) { delete reinterpret_cast<Sptr*>(p); }));
} else {
masks.emplace_back();
}
}
output.append(py::make_tuple(std::move(bboxes), std::move(labels), std::move(masks)));
}
return output;
}
~PyDetector() {
mmdeploy_detector_destroy(detector_);
detector_ = {};
}
private:
mmdeploy_detector_t detector_{};
};
static PythonBindingRegisterer register_detector{[](py::module& m) {
py::class_<PyDetector>(m, "Detector")
.def(py::init([](const char* model_path, const char* device_name, int device_id) {
return std::make_unique<PyDetector>(model_path, device_name, device_id);
}),
py::arg("model_path"), py::arg("device_name"), py::arg("device_id") = 0)
.def("__call__",
[](PyDetector* self, const PyImage& img) -> py::tuple {
return self->Apply(std::vector{img})[0];
})
.def("batch", &PyDetector::Apply);
}};
} // namespace mmdeploy::python
// Copyright (c) OpenMMLab. All rights reserved.
#include "common.h"
#include "mmdeploy/core/utils/formatter.h"
#include "mmdeploy/execution/execution.h"
#include "mmdeploy/execution/schedulers/inlined_scheduler.h"
#include "mmdeploy/execution/schedulers/registry.h"
#include "mmdeploy/execution/schedulers/single_thread_context.h"
#include "mmdeploy/execution/schedulers/static_thread_pool.h"
namespace mmdeploy::python {
struct PySender {
TypeErasedSender<Value> sender_;
explicit PySender(TypeErasedSender<Value> sender) : sender_(std::move(sender)) {}
struct gil_guarded_deleter {
void operator()(py::object* p) const {
py::gil_scoped_acquire _;
delete p;
}
};
using object_ptr = std::unique_ptr<py::object, gil_guarded_deleter>;
py::object __await__() {
auto future = py::module::import("concurrent.futures").attr("Future")();
{
py::gil_scoped_release _;
StartDetached(std::move(sender_) |
Then([future = object_ptr{new py::object(future)}](const Value& value) mutable {
py::gil_scoped_acquire _;
future->attr("set_result")(ToPyObject(value));
delete future.release();
}));
}
return py::module::import("asyncio").attr("wrap_future")(future).attr("__await__")();
}
};
static PythonBindingRegisterer register_sender{[](py::module& m) {
py::class_<PySender, std::unique_ptr<PySender>>(m, "PySender")
.def("__await__", &PySender::__await__);
}};
} // namespace mmdeploy::python
// Copyright (c) OpenMMLab. All rights reserved.
#include <optional>
#include "common.h"
#include "mmdeploy/common.h"
#include "mmdeploy/core/device.h"
#include "mmdeploy/core/mat.h"
#include "mmdeploy/core/model.h"
#include "mmdeploy/core/value.h"
namespace mmdeploy {
namespace python {
framework::Mat _get_mat(const PyImage& img) {
auto info = img.request();
if (info.ndim != 3) {
fprintf(stderr, "info.ndim = %d\n", (int)info.ndim);
throw std::runtime_error("continuous uint8 HWC array expected");
}
auto channels = (int)info.shape[2];
PixelFormat format;
if (channels == 1) {
format = PixelFormat::kGRAYSCALE;
} else if (channels == 3) {
format = PixelFormat::kBGR;
} else {
throw std::runtime_error("images of 1 or 3 channels are supported");
}
return {
(int)info.shape[0], // height
(int)info.shape[1], // width
format, // format
DataType::kINT8, // type
std::shared_ptr<void>(info.ptr, [](void*) {}), // data
framework::Device(0), // device
};
}
std::optional<Value> _to_value_internal(const void* object, mmdeploy_context_type_t type) {
switch (type) {
case MMDEPLOY_TYPE_MODEL:
return Value(*(const framework::Model*)object);
case MMDEPLOY_TYPE_DEVICE:
return Value(*(const framework::Device*)object);
case MMDEPLOY_TYPE_MAT:
return _get_mat(*(const py::array*)object);
default:
return std::nullopt;
}
}
} // namespace python
} // namespace mmdeploy
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/pipeline.hpp"
#include "common.h"
#include "mmdeploy/common.h"
#include "mmdeploy/core/logger.h"
#include "mmdeploy/core/utils/formatter.h"
namespace mmdeploy::python {
using namespace std::literals;
static PythonBindingRegisterer register_pipeline{[](py::module& m) {
py::class_<Pipeline>(m, "Pipeline")
.def(py::init([](const py::object& config, const Context& context) {
auto _config = FromPyObject(config);
return std::make_unique<Pipeline>(_config, context);
}))
.def("__call__",
[](Pipeline* pipeline, const py::args& args) {
auto inputs = FromPyObject(args);
for (auto& input : inputs) {
input = Value::Array{std::move(input)};
}
auto outputs = pipeline->Apply(inputs);
for (auto& output : outputs) {
output = std::move(output[0]);
}
py::tuple rets(outputs.size());
for (int i = 0; i < outputs.size(); ++i) {
rets[i] = ToPyObject(outputs[i]);
}
return rets;
})
.def("batch", [](Pipeline* pipeline, const py::args& args) {
auto inputs = FromPyObject(args);
auto outputs = pipeline->Apply(inputs);
py::tuple rets(outputs.size());
for (int i = 0; i < outputs.size(); ++i) {
rets[i] = ToPyObject(outputs[i]);
}
return rets;
});
}};
} // namespace mmdeploy::python
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/pose_detector.h"
#include <array>
#include <sstream>
#include "common.h"
namespace mmdeploy::python {
using Rect = std::array<float, 4>;
class PyPoseDetector {
public:
PyPoseDetector(const char* model_path, const char* device_name, int device_id) {
auto status =
mmdeploy_pose_detector_create_by_path(model_path, device_name, device_id, &detector_);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to create pose_detector");
}
}
py::list Apply(const std::vector<PyImage>& imgs, const std::vector<std::vector<Rect>>& bboxes) {
if (imgs.size() == 0 && bboxes.size() == 0) {
return py::list{};
}
if (bboxes.size() != 0 && bboxes.size() != imgs.size()) {
std::ostringstream os;
os << "imgs length not equal with vboxes [" << imgs.size() << " vs " << bboxes.size() << "]";
throw std::invalid_argument(os.str());
}
std::vector<mmdeploy_mat_t> mats;
std::vector<mmdeploy_rect_t> boxes;
std::vector<int> bbox_count;
mats.reserve(imgs.size());
for (const auto& img : imgs) {
auto mat = GetMat(img);
mats.push_back(mat);
}
for (auto _boxes : bboxes) {
for (auto _box : _boxes) {
mmdeploy_rect_t box = {_box[0], _box[1], _box[2], _box[3]};
boxes.push_back(box);
}
bbox_count.push_back(_boxes.size());
}
// full image
if (bboxes.size() == 0) {
for (int i = 0; i < mats.size(); i++) {
mmdeploy_rect_t box = {0.f, 0.f, mats[i].width - 1.f, mats[i].height - 1.f};
boxes.push_back(box);
bbox_count.push_back(1);
}
}
mmdeploy_pose_detection_t* detection{};
auto status = mmdeploy_pose_detector_apply_bbox(detector_, mats.data(), (int)mats.size(),
boxes.data(), bbox_count.data(), &detection);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to apply pose_detector, code: " + std::to_string(status));
}
auto output = py::list{};
auto result = detection;
for (int i = 0; i < mats.size(); i++) {
int n_point = result->length;
auto pred = py::array_t<float>({bbox_count[i], n_point, 3});
auto dst = pred.mutable_data();
for (int j = 0; j < bbox_count[i]; j++) {
for (int k = 0; k < n_point; k++) {
dst[0] = result->point[k].x;
dst[1] = result->point[k].y;
dst[2] = result->score[k];
dst += 3;
}
result++;
}
output.append(std::move(pred));
}
int total = std::accumulate(bbox_count.begin(), bbox_count.end(), 0);
mmdeploy_pose_detector_release_result(detection, total);
return output;
}
~PyPoseDetector() {
mmdeploy_pose_detector_destroy(detector_);
detector_ = {};
}
private:
mmdeploy_pose_detector_t detector_{};
};
static PythonBindingRegisterer register_pose_detector{[](py::module& m) {
py::class_<PyPoseDetector>(m, "PoseDetector")
.def(py::init([](const char* model_path, const char* device_name, int device_id) {
return std::make_unique<PyPoseDetector>(model_path, device_name, device_id);
}),
py::arg("model_path"), py::arg("device_name"), py::arg("device_id") = 0)
.def("__call__",
[](PyPoseDetector* self, const PyImage& img) -> py::array {
return self->Apply({img}, {})[0];
})
.def(
"__call__",
[](PyPoseDetector* self, const PyImage& img, const Rect& box) -> py::array {
std::vector<std::vector<Rect>> bboxes;
bboxes.push_back({box});
return self->Apply({img}, bboxes)[0];
},
py::arg("img"), py::arg("box"))
.def(
"__call__",
[](PyPoseDetector* self, const PyImage& img,
const std::vector<Rect>& bboxes) -> py::array {
std::vector<std::vector<Rect>> _bboxes;
_bboxes.push_back(bboxes);
return self->Apply({img}, _bboxes)[0];
},
py::arg("img"), py::arg("bboxes"))
.def("batch", &PyPoseDetector::Apply, py::arg("imgs"),
py::arg("bboxes") = std::vector<std::vector<Rect>>());
}};
} // namespace mmdeploy::python
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/pose_tracker.hpp"
#include "common.h"
#include "mmdeploy/common.hpp"
namespace mmdeploy::python {
namespace {
std::vector<py::tuple> Apply(mmdeploy::PoseTracker* self,
const std::vector<mmdeploy::PoseTracker::State*>& _states,
const std::vector<PyImage>& _frames, std::vector<int> detect) {
std::vector<mmdeploy_pose_tracker_state_t> tmp;
for (const auto& s : _states) {
tmp.push_back(static_cast<mmdeploy_pose_tracker_state_t>(*s));
}
mmdeploy::Span states(reinterpret_cast<mmdeploy::PoseTracker::State*>(tmp.data()), tmp.size());
std::vector<mmdeploy::Mat> frames;
for (const auto& f : _frames) {
frames.emplace_back(GetMat(f));
}
if (detect.empty()) {
detect.resize(frames.size(), -1);
}
assert(states.size() == frames.size());
assert(states.size() == detect.size());
auto results = self->Apply(states, frames, detect);
std::vector<py::tuple> batch_ret;
batch_ret.reserve(frames.size());
for (const auto& rs : results) {
py::array_t<float> keypoints(
{static_cast<int>(rs.size()), rs.size() > 0 ? rs[0].keypoint_count : 0, 3});
py::array_t<float> bboxes({static_cast<int>(rs.size()), 4});
py::array_t<uint32_t> track_ids(static_cast<int>(rs.size()));
auto kpts_ptr = keypoints.mutable_data();
auto bbox_ptr = bboxes.mutable_data();
auto track_id_ptr = track_ids.mutable_data();
for (const auto& r : rs) {
for (int i = 0; i < r.keypoint_count; ++i) {
kpts_ptr[0] = r.keypoints[i].x;
kpts_ptr[1] = r.keypoints[i].y;
kpts_ptr[2] = r.scores[i];
kpts_ptr += 3;
}
{
auto tmp_bbox = (std::array<float, 4>&)r.bbox;
bbox_ptr[0] = tmp_bbox[0];
bbox_ptr[1] = tmp_bbox[1];
bbox_ptr[2] = tmp_bbox[2];
bbox_ptr[3] = tmp_bbox[3];
bbox_ptr += 4;
}
*track_id_ptr++ = r.target_id;
}
batch_ret.push_back(
py::make_tuple(std::move(keypoints), std::move(bboxes), std::move(track_ids)));
}
return batch_ret;
}
template <typename T, size_t N>
void Copy(const py::handle& h, T (&a)[N]) {
auto array = h.cast<py::array_t<float>>();
assert(array.size() == N);
auto data = array.data();
for (int i = 0; i < N; ++i) {
a[i] = data[i];
}
}
void Parse(const py::dict& dict, PoseTracker::Params& params, py::array_t<float>& sigmas) {
for (const auto& [_name, value] : dict) {
auto name = _name.cast<std::string>();
if (name == "det_interval") {
params->det_interval = value.cast<int32_t>();
} else if (name == "det_label") {
params->det_label = value.cast<int32_t>();
} else if (name == "det_thr") {
params->det_thr = value.cast<float>();
} else if (name == "det_min_bbox_size") {
params->det_min_bbox_size = value.cast<float>();
} else if (name == "det_nms_thr") {
params->det_nms_thr = value.cast<float>();
} else if (name == "pose_max_num_bboxes") {
params->pose_max_num_bboxes = value.cast<int32_t>();
} else if (name == "pose_min_keypoints") {
params->pose_min_keypoints = value.cast<int32_t>();
} else if (name == "pose_min_bbox_size") {
params->pose_min_bbox_size = value.cast<float>();
} else if (name == "pose_nms_thr") {
params->pose_nms_thr = value.cast<float>();
} else if (name == "track_kpt_thr") {
params->pose_kpt_thr = value.cast<float>();
} else if (name == "track_iou_thr") {
params->track_iou_thr = value.cast<float>();
} else if (name == "pose_bbox_scale") {
params->pose_bbox_scale = value.cast<float>();
} else if (name == "track_max_missing") {
params->track_max_missing = value.cast<float>();
} else if (name == "track_history_size") {
params->track_history_size = value.cast<int32_t>();
} else if (name == "keypoint_sigmas") {
sigmas = value.cast<py::array_t<float>>();
params->keypoint_sigmas = const_cast<float*>(sigmas.data());
params->keypoint_sigmas_size = sigmas.size();
} else if (name == "std_weight_position") {
params->std_weight_position = value.cast<float>();
} else if (name == "std_weight_velocity") {
params->std_weight_velocity = value.cast<float>();
} else if (name == "smooth_params") {
Copy(value, params->smooth_params);
} else {
MMDEPLOY_ERROR("unused argument: {}", name);
}
}
}
} // namespace
static PythonBindingRegisterer register_pose_tracker{[](py::module& m) {
py::class_<mmdeploy::PoseTracker::State>(m, "PoseTracker.State");
py::class_<mmdeploy::PoseTracker>(m, "PoseTracker")
.def(py::init([](const char* det_model_path, const char* pose_model_path,
const char* device_name, int device_id) {
return mmdeploy::PoseTracker(
mmdeploy::Model(det_model_path), mmdeploy::Model(pose_model_path),
mmdeploy::Context(mmdeploy::Device(device_name, device_id)));
}),
py::arg("det_model"), py::arg("pose_model"), py::arg("device_name"),
py::arg("device_id") = 0)
.def(
"__call__",
[](mmdeploy::PoseTracker* self, mmdeploy::PoseTracker::State* state, const PyImage& img,
int detect) { return Apply(self, {state}, {img}, {detect})[0]; },
py::arg("state"), py::arg("frame"), py::arg("detect") = -1)
.def("batch", &Apply, py::arg("states"), py::arg("frames"),
py::arg("detects") = std::vector<int>{})
.def("create_state", [](mmdeploy::PoseTracker* self, const py::kwargs& kwargs) {
PoseTracker::Params params;
py::array_t<float> sigmas;
if (kwargs) {
Parse(kwargs, params, sigmas);
}
return self->CreateState(params);
});
}};
} // namespace mmdeploy::python
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/restorer.h"
#include "common.h"
namespace mmdeploy::python {
class PyRestorer {
public:
PyRestorer(const char* model_path, const char* device_name, int device_id) {
auto status = mmdeploy_restorer_create_by_path(model_path, device_name, device_id, &restorer_);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to create restorer");
}
}
~PyRestorer() {
mmdeploy_restorer_destroy(restorer_);
restorer_ = {};
}
std::vector<py::array> Apply(const std::vector<PyImage>& imgs) {
std::vector<mmdeploy_mat_t> mats;
mats.reserve(imgs.size());
for (const auto& img : imgs) {
auto mat = GetMat(img);
mats.push_back(mat);
}
mmdeploy_mat_t* results{};
auto status = mmdeploy_restorer_apply(restorer_, mats.data(), (int)mats.size(), &results);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to apply restorer, code: " + std::to_string(status));
}
using Sptr = std::shared_ptr<mmdeploy_mat_t>;
Sptr holder(results, [n = mats.size()](auto p) { mmdeploy_restorer_release_result(p, n); });
std::vector<py::array> rets(mats.size());
for (int i = 0; i < mats.size(); ++i) {
rets[i] = {
{results[i].height, results[i].width, results[i].channel}, // shape
results[i].data, // data
py::capsule(new Sptr(holder), // handle
[](void* p) { delete reinterpret_cast<Sptr*>(p); }) //
};
}
return rets;
}
private:
mmdeploy_restorer_t restorer_{};
};
static PythonBindingRegisterer register_restorer{[](py::module& m) {
py::class_<PyRestorer>(m, "Restorer")
.def(py::init([](const char* model_path, const char* device_name, int device_id) {
return std::make_unique<PyRestorer>(model_path, device_name, device_id);
}),
py::arg("model_path"), py::arg("device_name"), py::arg("device_id") = 0)
.def("__call__",
[](PyRestorer* self, const PyImage& img) -> py::array {
return self->Apply(std::vector{img})[0];
})
.def("batch", &PyRestorer::Apply);
}};
} // namespace mmdeploy::python
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/rotated_detector.h"
#include "common.h"
namespace mmdeploy::python {
class PyRotatedDetector {
public:
PyRotatedDetector(const char* model_path, const char* device_name, int device_id) {
auto status =
mmdeploy_rotated_detector_create_by_path(model_path, device_name, device_id, &detector_);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to create rotated detector");
}
}
py::list Apply(const std::vector<PyImage>& imgs) {
std::vector<mmdeploy_mat_t> mats;
mats.reserve(imgs.size());
for (const auto& img : imgs) {
auto mat = GetMat(img);
mats.push_back(mat);
}
mmdeploy_rotated_detection_t* rbboxes{};
int* res_count{};
auto status = mmdeploy_rotated_detector_apply(detector_, mats.data(), (int)mats.size(),
&rbboxes, &res_count);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to apply rotated detector, code: " + std::to_string(status));
}
auto output = py::list{};
auto result = rbboxes;
auto counts = res_count;
for (int i = 0; i < mats.size(); i++) {
auto _dets = py::array_t<float>({*counts, 6});
auto _labels = py::array_t<int>({*counts});
auto dets = _dets.mutable_data();
auto labels = _labels.mutable_data();
for (int j = 0; j < *counts; j++) {
for (int k = 0; k < 5; k++) {
*dets++ = result->rbbox[k];
}
*dets++ = result->score;
*labels++ = result->label_id;
result++;
}
counts++;
output.append(py::make_tuple(std::move(_dets), std::move(_labels)));
}
mmdeploy_rotated_detector_release_result(rbboxes, res_count);
return output;
}
~PyRotatedDetector() {
mmdeploy_rotated_detector_destroy(detector_);
detector_ = {};
}
private:
mmdeploy_rotated_detector_t detector_{};
};
static PythonBindingRegisterer register_rotated_detector{[](py::module& m) {
py::class_<PyRotatedDetector>(m, "RotatedDetector")
.def(py::init([](const char* model_path, const char* device_name, int device_id) {
return std::make_unique<PyRotatedDetector>(model_path, device_name, device_id);
}),
py::arg("model_path"), py::arg("device_name"), py::arg("device_id") = 0)
.def("__call__",
[](PyRotatedDetector* self, const PyImage& img) -> py::tuple {
return self->Apply(std::vector{img})[0];
})
.def("batch", &PyRotatedDetector::Apply);
}};
} // namespace mmdeploy::python
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/segmentor.h"
#include "common.h"
namespace mmdeploy::python {
class PySegmentor {
public:
PySegmentor(const char* model_path, const char* device_name, int device_id) {
auto status =
mmdeploy_segmentor_create_by_path(model_path, device_name, device_id, &segmentor_);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to create segmentor");
}
}
~PySegmentor() {
mmdeploy_segmentor_destroy(segmentor_);
segmentor_ = {};
}
std::vector<py::array> Apply(const std::vector<PyImage>& imgs) {
std::vector<mmdeploy_mat_t> mats;
mats.reserve(imgs.size());
for (const auto& img : imgs) {
auto mat = GetMat(img);
mats.push_back(mat);
}
mmdeploy_segmentation_t* segm{};
auto status = mmdeploy_segmentor_apply(segmentor_, mats.data(), (int)mats.size(), &segm);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to apply segmentor, code: " + std::to_string(status));
}
using Sptr = std::shared_ptr<mmdeploy_segmentation_t>;
Sptr holder(segm, [n = mats.size()](auto p) { mmdeploy_segmentor_release_result(p, n); });
std::vector<py::array> rets(mats.size());
for (size_t i = 0; i < mats.size(); ++i) {
if (segm[i].mask != nullptr) {
rets[i] = {
{segm[i].height, segm[i].width}, // shape
segm[i].mask, // mask
py::capsule(new Sptr(holder), // handle
[](void* p) { delete reinterpret_cast<Sptr*>(p); }) //
};
}
if (segm[i].score != nullptr) {
rets[i] = {
{segm[i].classes, segm[i].height, segm[i].width}, // shape
segm[i].score, // score
py::capsule(new Sptr(holder), // handle
[](void* p) { delete reinterpret_cast<Sptr*>(p); }) //
};
}
}
return rets;
}
private:
mmdeploy_segmentor_t segmentor_{};
};
static PythonBindingRegisterer register_segmentor{[](py::module& m) {
py::class_<PySegmentor>(m, "Segmentor")
.def(py::init([](const char* model_path, const char* device_name, int device_id) {
return std::make_unique<PySegmentor>(model_path, device_name, device_id);
}),
py::arg("model_path"), py::arg("device_name"), py::arg("device_id") = 0)
.def("__call__",
[](PySegmentor* self, const PyImage& img) -> py::array {
return self->Apply(std::vector{img})[0];
})
.def("batch", &PySegmentor::Apply);
}};
} // namespace mmdeploy::python
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/text_detector.h"
#include "common.h"
namespace mmdeploy::python {
class PyTextDetector {
public:
PyTextDetector(const char* model_path, const char* device_name, int device_id) {
auto status =
mmdeploy_text_detector_create_by_path(model_path, device_name, device_id, &detector_);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to create text_detector");
}
}
std::vector<py::array_t<float>> Apply(const std::vector<PyImage>& imgs) {
std::vector<mmdeploy_mat_t> mats;
mats.reserve(imgs.size());
for (const auto& img : imgs) {
auto mat = GetMat(img);
mats.push_back(mat);
}
mmdeploy_text_detection_t* detection{};
int* result_count{};
auto status = mmdeploy_text_detector_apply(detector_, mats.data(), (int)mats.size(), &detection,
&result_count);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to apply text_detector, code: " + std::to_string(status));
}
auto output = std::vector<py::array_t<float>>{};
auto result = detection;
for (int i = 0; i < mats.size(); ++i) {
auto bboxes = py::array_t<float>({result_count[i], 9});
for (int j = 0; j < result_count[i]; ++j, ++result) {
auto data = bboxes.mutable_data(j);
for (const auto& p : result->bbox) {
*data++ = p.x;
*data++ = p.y;
}
*data++ = result->score;
}
output.push_back(std::move(bboxes));
}
mmdeploy_text_detector_release_result(detection, result_count, (int)mats.size());
return output;
}
~PyTextDetector() {
mmdeploy_text_detector_destroy(detector_);
detector_ = {};
}
private:
mmdeploy_text_detector_t detector_{};
};
static PythonBindingRegisterer register_text_detector{[](py::module& m) {
py::class_<PyTextDetector>(m, "TextDetector")
.def(py::init([](const char* model_path, const char* device_name, int device_id) {
return std::make_unique<PyTextDetector>(model_path, device_name, device_id);
}),
py::arg("model_path"), py::arg("device_name"), py::arg("device_id") = 0)
.def("__call__",
[](PyTextDetector* self, const PyImage& img) -> py::array {
return self->Apply(std::vector{img})[0];
})
.def("batch", &PyTextDetector::Apply);
}};
} // namespace mmdeploy::python
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/text_recognizer.h"
#include "common.h"
namespace mmdeploy::python {
class PyTextRecognizer {
public:
PyTextRecognizer(const char* model_path, const char* device_name, int device_id) {
auto status =
mmdeploy_text_recognizer_create_by_path(model_path, device_name, device_id, &recognizer_);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to create text_recognizer");
}
}
std::vector<std::tuple<std::string, std::vector<float>>> Apply(const std::vector<PyImage>& imgs) {
std::vector<mmdeploy_mat_t> mats;
mats.reserve(imgs.size());
for (const auto& img : imgs) {
auto mat = GetMat(img);
mats.push_back(mat);
}
mmdeploy_text_recognition_t* results{};
auto status =
mmdeploy_text_recognizer_apply(recognizer_, mats.data(), (int)mats.size(), &results);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to apply text_recognizer, code: " + std::to_string(status));
}
auto output = std::vector<std::tuple<std::string, std::vector<float>>>{};
for (int i = 0; i < mats.size(); ++i) {
std::vector<float> score(results[i].score, results[i].score + results[i].length);
output.emplace_back(results[i].text, std::move(score));
}
mmdeploy_text_recognizer_release_result(results, (int)mats.size());
return output;
}
std::vector<std::tuple<std::string, std::vector<float>>> Apply(const PyImage& img,
const std::vector<float>& bboxes) {
if (bboxes.size() * sizeof(float) % sizeof(mmdeploy_text_detection_t)) {
throw std::invalid_argument("bboxes is not a list of 'mmdeploy_text_detection_t'");
}
auto mat = GetMat(img);
int bbox_count = bboxes.size() * sizeof(float) / sizeof(mmdeploy_text_detection_t);
mmdeploy_text_recognition_t* results{};
auto status = mmdeploy_text_recognizer_apply_bbox(
recognizer_, &mat, 1, (mmdeploy_text_detection_t*)bboxes.data(), &bbox_count, &results);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to apply text_recognizer, code: " + std::to_string(status));
}
auto output = std::vector<std::tuple<std::string, std::vector<float>>>{};
for (int i = 0; i < bbox_count; ++i) {
std::vector<float> score(results[i].score, results[i].score + results[i].length);
output.emplace_back(results[i].text, std::move(score));
}
mmdeploy_text_recognizer_release_result(results, bbox_count);
return output;
}
~PyTextRecognizer() {
mmdeploy_text_recognizer_destroy(recognizer_);
recognizer_ = {};
}
private:
mmdeploy_text_recognizer_t recognizer_{};
};
static PythonBindingRegisterer register_text_recognizer{[](py::module& m) {
py::class_<PyTextRecognizer>(m, "TextRecognizer")
.def(py::init([](const char* model_path, const char* device_name, int device_id) {
return std::make_unique<PyTextRecognizer>(model_path, device_name, device_id);
}),
py::arg("model_path"), py::arg("device_name"), py::arg("device_id") = 0)
.def("__call__", [](PyTextRecognizer* self,
const PyImage& img) { return self->Apply(std::vector{img})[0]; })
.def("__call__", [](PyTextRecognizer* self, const PyImage& img,
const std::vector<float>& bboxes) { return self->Apply(img, bboxes); })
.def("batch", py::overload_cast<const std::vector<PyImage>&>(&PyTextRecognizer::Apply));
}};
} // namespace mmdeploy::python
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/video_recognizer.h"
#include "common.h"
namespace mmdeploy::python {
class PyVideoRecognizer {
public:
PyVideoRecognizer(const char* model_path, const char* device_name, int device_id) {
auto status =
mmdeploy_video_recognizer_create_by_path(model_path, device_name, device_id, &recognizer_);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to create video_recognizer");
}
}
std::vector<std::vector<std::tuple<int, float>>> Apply(
const std::vector<std::vector<PyImage>>& imgs, const std::vector<std::pair<int, int>>& info) {
if (info.size() != imgs.size()) {
throw std::invalid_argument("the length of info is not equal with imgs");
}
for (int i = 0; i < info.size(); i++) {
if (imgs[i].size() != info[i].first * info[i].second) {
throw std::invalid_argument("invalid info");
}
}
int total = 0;
for (int i = 0; i < imgs.size(); i++) {
total += imgs[i].size();
}
std::vector<mmdeploy_mat_t> clips;
std::vector<mmdeploy_video_sample_info_t> clip_info;
clips.reserve(total);
clip_info.reserve(total);
for (int i = 0; i < imgs.size(); i++) {
for (const auto& img : imgs[i]) {
auto mat = GetMat(img);
clips.push_back(mat);
}
clip_info.push_back({info[i].first, info[i].second});
}
mmdeploy_video_recognition_t* results{};
int* result_count{};
auto status = mmdeploy_video_recognizer_apply(recognizer_, clips.data(), clip_info.data(), 1,
&results, &result_count);
if (status != MMDEPLOY_SUCCESS) {
throw std::runtime_error("failed to apply video_recognizer, code: " + std::to_string(status));
}
auto output = std::vector<std::vector<std::tuple<int, float>>>{};
output.reserve(imgs.size());
auto result_ptr = results;
for (int i = 0; i < imgs.size(); ++i) {
std::vector<std::tuple<int, float>> label_score;
for (int j = 0; j < result_count[i]; ++j) {
label_score.emplace_back(result_ptr[j].label_id, result_ptr[j].score);
}
output.push_back(std::move(label_score));
result_ptr += result_count[i];
}
mmdeploy_video_recognizer_release_result(results, result_count, (int)imgs.size());
return output;
}
~PyVideoRecognizer() {
mmdeploy_video_recognizer_destroy(recognizer_);
recognizer_ = {};
}
private:
mmdeploy_video_recognizer_t recognizer_{};
};
static PythonBindingRegisterer register_video_recognizer{[](py::module& m) {
py::class_<PyVideoRecognizer>(m, "VideoRecognizer")
.def(py::init([](const char* model_path, const char* device_name, int device_id) {
return std::make_unique<PyVideoRecognizer>(model_path, device_name, device_id);
}),
py::arg("model_path"), py::arg("device_name"), py::arg("device_id") = 0)
.def("__call__",
[](PyVideoRecognizer* self, const std::vector<PyImage>& imgs,
const std::pair<int, int>& info) { return self->Apply({imgs}, {info})[0]; })
.def("batch", &PyVideoRecognizer::Apply);
}};
} // namespace mmdeploy::python
# Copyright (c) OpenMMLab. All rights reserved.
project(mmdeploy_archive)
add_library(${PROJECT_NAME} INTERFACE)
target_link_libraries(${PROJECT_NAME} INTERFACE mmdeploy::core)
add_library(mmdeploy::archive ALIAS mmdeploy_archive)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/csrc/mmdeploy/archive
DESTINATION include/mmdeploy
FILES_MATCHING PATTERN "*.h")
install(FILES ${CMAKE_SOURCE_DIR}/third_party/json/json.hpp
DESTINATION include/mmdeploy/third_party/json)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment