Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,18 @@ void init_classification(nb::module_& m) {
[](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());
.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));
}
for (const auto& input : inputs) {
input_mats.push_back(pyutils::wrap_np_mat(input));
}

return self.inferBatch(input_mats);
return self.inferBatch(input_mats);
})
.def_prop_ro_static("__model__", [](nb::object) {
return ClassificationModel::ModelType;
});
}
76 changes: 76 additions & 0 deletions src/cpp/py_bindings/py_instance_segmentation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* 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/instance_segmentation.h"
#include "models/results.h"
#include "py_utils.hpp"

namespace pyutils = vision::nanobind::utils;

void init_instance_segmentation(nb::module_& m) {
nb::class_<MaskRCNNModel, ImageModel>(m, "MaskRCNNModel")
.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 MaskRCNNModel::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__",
[](MaskRCNNModel& self, const nb::ndarray<>& input) {
return self.infer(pyutils::wrap_np_mat(input));
})
.def("infer_batch",
[](MaskRCNNModel& 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);
})
.def("postprocess",
[](MaskRCNNModel& self, InferenceResult& infResult) {
return self.postprocess(infResult);
})
.def_prop_ro_static("__model__", [](nb::object) {
return MaskRCNNModel::ModelType;
});

nb::class_<InstanceSegmentationResult, ResultBase>(m, "InstanceSegmentationResult")
.def(nb::init<int64_t, std::shared_ptr<MetaData>>(), nb::arg("frameId") = -1, nb::arg("metaData") = nullptr)
.def_prop_ro(
"feature_vector",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Iseg result also contains a saliency map as a vector of cv::Mat. Perhaps, it's not that easy to expose but there is a chance a vector of nb::ndarray<uint8_t... would work here

[](InstanceSegmentationResult& 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);
}
69 changes: 69 additions & 0 deletions src/cpp/py_bindings/py_keypoint_detection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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/keypoint_detection.h"
#include "models/results.h"
#include "py_utils.hpp"

namespace pyutils = vision::nanobind::utils;

void init_keypoint_detection(nb::module_& m) {
nb::class_<KeypointDetectionModel, ImageModel>(m, "KeypointDetectionModel")
.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 KeypointDetectionModel::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__",
[](KeypointDetectionModel& self, const nb::ndarray<>& input) {
return self.infer(pyutils::wrap_np_mat(input));
})
.def("infer_batch",
[](KeypointDetectionModel& 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);
})
.def("postprocess",
[](KeypointDetectionModel& self, InferenceResult& infResult) {
return self.postprocess(infResult);
})
.def_prop_ro_static("__model__", [](nb::object) {
return KeypointDetectionModel::ModelType;
});

nb::class_<KeypointDetectionResult, ResultBase>(m, "KeypointDetectionResult")
.def(nb::init<int64_t, std::shared_ptr<MetaData>>(), nb::arg("frameId") = -1, nb::arg("metaData") = nullptr)
.def_ro("poses", &KeypointDetectionResult::poses);

nb::class_<DetectedKeypoints>(m, "DetectedKeypoints")
.def(nb::init<>())
.def_ro("keypoints", &DetectedKeypoints::keypoints)
.def_ro("scores", &DetectedKeypoints::scores);
}
73 changes: 73 additions & 0 deletions src/cpp/py_bindings/py_segmentation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* 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/results.h"
#include "models/segmentation_model.h"
#include "py_utils.hpp"

namespace pyutils = vision::nanobind::utils;

void init_segmentation(nb::module_& m) {
nb::class_<SegmentationModel, ImageModel>(m, "SegmentationModel")
.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 SegmentationModel::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__",
[](SegmentationModel& self, const nb::ndarray<>& input) {
return self.infer(pyutils::wrap_np_mat(input));
})
.def("infer_batch",
[](SegmentationModel& 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);
})
.def("postprocess",
[](SegmentationModel& self, InferenceResult& infResult) {
return self.postprocess(infResult);
})
.def_prop_ro_static("__model__", [](nb::object) {
return SegmentationModel::ModelType;
});

nb::class_<ImageResult, ResultBase>(m, "ImageResult")
.def(nb::init<int64_t, std::shared_ptr<MetaData>>(), nb::arg("frameId") = -1, nb::arg("metaData") = nullptr)
.def_prop_ro(
"resultImage",
[](ImageResult& r) {
return nb::ndarray<uint8_t, nb::numpy, nb::c_contig>(r.resultImage.data,
{static_cast<size_t>(r.resultImage.rows),
static_cast<size_t>(r.resultImage.cols),
static_cast<size_t>(r.resultImage.channels())});
},
nb::rv_policy::reference_internal);
}
8 changes: 7 additions & 1 deletion src/cpp/py_bindings/py_vision_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@

namespace nb = nanobind;

void init_classification(nb::module_& m);
void init_base_modules(nb::module_& m);
void init_classification(nb::module_& m);
void init_segmentation(nb::module_& m);
void init_instance_segmentation(nb::module_& m);
void init_keypoint_detection(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);
init_keypoint_detection(m);
init_segmentation(m);
init_instance_segmentation(m);
}
Loading