-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial version of python bindings (#252)
* Add initial version of python bindings * Update python deps * Update linkage flags for GCC * Classification bindings without config * Wrap batch inference * Wrap load() to enable setting correct number of infer requests * Add a simple any map converter * Add license * Wrap tensor results * Update bindings directory structure * Add cmake option to anable/disable bindings * Fix linter * Update copyrights * Update CI scripts * Fix more issues in CI scripts * Add missing requirements * Dismiss pre-defined gha-specific ython paath * Force cmake to use python from venv * Workaround missing nanobind with global package installation * Try python 3.10 * Try to reduce the amount of warning in tests * Limit ubuntu version in cpp build * Ignore warnings on cpp pre-commit * Update installation script * Update cpp accuracy build settings
- Loading branch information
Showing
12 changed files
with
239 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Copyright (C) 2025 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
# | ||
|
||
set(DEV_MODULE Development.Module) | ||
|
||
find_package(Python COMPONENTS Interpreter ${DEV_MODULE} REQUIRED) | ||
|
||
execute_process( | ||
COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir | ||
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE nanobind_ROOT) | ||
find_package(nanobind CONFIG REQUIRED) | ||
|
||
|
||
file(GLOB BINDINGS_SOURCES ./*.cpp) | ||
file(GLOB BINDINGS_HEADERS ./*.hpp) | ||
|
||
nanobind_add_module(py_model_api NB_STATIC STABLE_ABI LTO ${BINDINGS_SOURCES} ${BINDINGS_HEADERS}) | ||
|
||
target_link_libraries(py_model_api PRIVATE model_api) | ||
|
||
nanobind_add_stub( | ||
py_model_api_stub | ||
MODULE py_model_api | ||
OUTPUT py_model_api.pyi | ||
PYTHON_PATH $<TARGET_FILE_DIR:py_model_api> | ||
DEPENDS py_model_api | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* Copyright (C) 2025 Intel Corporation | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <nanobind/nanobind.h> | ||
#include <nanobind/stl/string.h> | ||
|
||
#include <openvino/openvino.hpp> | ||
|
||
#include "models/image_model.h" | ||
#include "models/results.h" | ||
|
||
namespace nb = nanobind; | ||
|
||
void init_base_modules(nb::module_& m) { | ||
nb::class_<ResultBase>(m, "ResultBase").def(nb::init<>()); | ||
|
||
nb::class_<ModelBase>(m, "ModelBase") | ||
.def("load", [](ModelBase& self, const std::string& device, size_t num_infer_requests) { | ||
auto core = ov::Core(); | ||
self.load(core, device, num_infer_requests); | ||
}); | ||
|
||
nb::class_<ImageModel, ModelBase>(m, "ImageModel"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* Copyright (C) 2025 Intel Corporation | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <nanobind/ndarray.h> | ||
#include <nanobind/operators.h> | ||
#include <nanobind/stl/map.h> | ||
#include <nanobind/stl/string.h> | ||
#include <nanobind/stl/unique_ptr.h> | ||
#include <nanobind/stl/vector.h> | ||
|
||
#include "models/classification_model.h" | ||
#include "models/results.h" | ||
#include "py_utils.hpp" | ||
|
||
namespace pyutils = vision::nanobind::utils; | ||
|
||
void init_classification(nb::module_& m) { | ||
nb::class_<ClassificationResult::Classification>(m, "Classification") | ||
.def(nb::init<unsigned int, const std::string, float>()) | ||
.def_rw("id", &ClassificationResult::Classification::id) | ||
.def_rw("label", &ClassificationResult::Classification::label) | ||
.def_rw("score", &ClassificationResult::Classification::score); | ||
|
||
nb::class_<ClassificationResult, ResultBase>(m, "ClassificationResult") | ||
.def(nb::init<>()) | ||
.def_ro("topLabels", &ClassificationResult::topLabels) | ||
.def("__repr__", &ClassificationResult::operator std::string) | ||
.def_prop_ro( | ||
"feature_vector", | ||
[](ClassificationResult& r) { | ||
if (!r.feature_vector) { | ||
return nb::ndarray<float, nb::numpy, nb::c_contig>(); | ||
} | ||
|
||
return nb::ndarray<float, nb::numpy, nb::c_contig>(r.feature_vector.data(), | ||
r.feature_vector.get_shape().size(), | ||
r.feature_vector.get_shape().data()); | ||
}, | ||
nb::rv_policy::reference_internal) | ||
.def_prop_ro( | ||
"saliency_map", | ||
[](ClassificationResult& r) { | ||
if (!r.saliency_map) { | ||
return nb::ndarray<float, nb::numpy, nb::c_contig>(); | ||
} | ||
|
||
return nb::ndarray<float, nb::numpy, nb::c_contig>(r.saliency_map.data(), | ||
r.saliency_map.get_shape().size(), | ||
r.saliency_map.get_shape().data()); | ||
}, | ||
nb::rv_policy::reference_internal); | ||
|
||
nb::class_<ClassificationModel, ImageModel>(m, "ClassificationModel") | ||
.def_static( | ||
"create_model", | ||
[](const std::string& model_path, | ||
const std::map<std::string, nb::object>& configuration, | ||
bool preload, | ||
const std::string& device) { | ||
auto ov_any_config = ov::AnyMap(); | ||
for (const auto& item : configuration) { | ||
ov_any_config[item.first] = pyutils::py_object_to_any(item.second, item.first); | ||
} | ||
|
||
return ClassificationModel::create_model(model_path, ov_any_config, preload, device); | ||
}, | ||
nb::arg("model_path"), | ||
nb::arg("configuration") = ov::AnyMap({}), | ||
nb::arg("preload") = true, | ||
nb::arg("device") = "AUTO") | ||
|
||
.def("__call__", | ||
[](ClassificationModel& self, const nb::ndarray<>& input) { | ||
return self.infer(pyutils::wrap_np_mat(input)); | ||
}) | ||
.def("infer_batch", [](ClassificationModel& self, const std::vector<nb::ndarray<>> inputs) { | ||
std::vector<ImageInputData> input_mats; | ||
input_mats.reserve(inputs.size()); | ||
|
||
for (const auto& input : inputs) { | ||
input_mats.push_back(pyutils::wrap_np_mat(input)); | ||
} | ||
|
||
return self.inferBatch(input_mats); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
* Copyright (C) 2025 Intel Corporation | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include "py_utils.hpp" | ||
|
||
namespace vision::nanobind::utils { | ||
|
||
cv::Mat wrap_np_mat(const nb::ndarray<>& input) { | ||
if (input.ndim() != 3 || input.shape(2) != 3 || input.dtype() != nb::dtype<uint8_t>()) { | ||
throw std::runtime_error("Input image should have HWC_8U layout"); | ||
} | ||
|
||
int height = input.shape(0); | ||
int width = input.shape(1); | ||
|
||
return cv::Mat(height, width, CV_8UC3, input.data()); | ||
} | ||
|
||
ov::Any py_object_to_any(const nb::object& py_obj, const std::string& property_name) { | ||
if (nb::isinstance<nb::str>(py_obj)) { | ||
return ov::Any(std::string(static_cast<nb::str>(py_obj).c_str())); | ||
} else if (nb::isinstance<nb::float_>(py_obj)) { | ||
return ov::Any(static_cast<double>(static_cast<nb::float_>(py_obj))); | ||
} else if (nb::isinstance<nb::int_>(py_obj)) { | ||
return ov::Any(static_cast<int>(static_cast<nb::int_>(py_obj))); | ||
} else { | ||
OPENVINO_THROW("Property \"" + property_name + "\" has unsupported type."); | ||
} | ||
} | ||
|
||
} // namespace vision::nanobind::utils |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* | ||
* Copyright (C) 2025 Intel Corporation | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#pragma once | ||
#include <nanobind/ndarray.h> | ||
|
||
#include <opencv2/core/core.hpp> | ||
#include <openvino/openvino.hpp> | ||
|
||
namespace nb = nanobind; | ||
|
||
namespace vision::nanobind::utils { | ||
cv::Mat wrap_np_mat(const nb::ndarray<>& input); | ||
ov::Any py_object_to_any(const nb::object& py_obj, const std::string& property_name); | ||
} // namespace vision::nanobind::utils |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* | ||
* Copyright (C) 2025 Intel Corporation | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <nanobind/nanobind.h> | ||
|
||
namespace nb = nanobind; | ||
|
||
void init_classification(nb::module_& m); | ||
void init_base_modules(nb::module_& m); | ||
|
||
NB_MODULE(py_model_api, m) { | ||
m.doc() = "Nanobind binding for OpenVINO Vision API library"; | ||
init_base_modules(m); | ||
init_classification(m); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters