-
Notifications
You must be signed in to change notification settings - Fork 19
Add initial version of python bindings #252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 12 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
0b51da2
Add initial version of python bindings
sovrasov 01b5770
Update python deps
sovrasov 12c4824
Update linkage flags for GCC
sovrasov 8bb9a5d
Classification bindings without config
sovrasov ae9dc94
Wrap batch inference
sovrasov b215fec
Wrap load() to enable setting correct number of infer requests
sovrasov 67fd082
Add a simple any map converter
sovrasov a39ef11
Add license
sovrasov 2c515cc
Wrap tensor results
sovrasov f9019e0
Update bindings directory structure
sovrasov ad44de2
Add cmake option to anable/disable bindings
sovrasov 0016a07
Fix linter
sovrasov d5b33c6
Update copyrights
sovrasov 0425d59
Update CI scripts
sovrasov bcaf3d7
Fix more issues in CI scripts
sovrasov 24b865f
Add missing requirements
sovrasov 9ae15b6
Dismiss pre-defined gha-specific ython paath
sovrasov aa8ada6
Force cmake to use python from venv
sovrasov 35001f8
Workaround missing nanobind with global package installation
sovrasov a4472ac
Try python 3.10
sovrasov c7aab3f
Try to reduce the amount of warning in tests
sovrasov 3a04f39
Limit ubuntu version in cpp build
sovrasov b617c3a
Ignore warnings on cpp pre-commit
sovrasov e108ee4
Update installation script
sovrasov e7f31e5
Update cpp accuracy build settings
sovrasov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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) 2024 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.