Closed Cenbylin closed 4 years ago
I'm glad this repos can help you. For KeyPoint did you really need to convert KeyPoint or did you just need Point2f ?
I need to convert the whole KeyPoint object, which was obtained via feature extractor in opencv-python. The current solution is to unpack these objects (cv2.KeyPoint) into tuple (x, y, size, angle, response, octave), and in c++ we construct back to cv::KeyPoint. Do you have more straightaway method?
I would propose the same approach. If you don't need to interprete Keypoint in python but you just use python to pass object from c++ function to another. I think there is a way to store C++ object without interpretation.
If you really want to do a proper type convertion. You have to define a python class that mimic the KeyPoint structure and implement a custom type convertion : https://pybind11.readthedocs.io/en/stable/advanced/cast/custom.html
You are right. That would be easier if cv2.KeyPoint provide some interface to obtain the original c++ object. But I am afraid it didn't. Thanks for your idea and helpful document.
sorry I think I misunderstand you, you want to convert object from the opencv python binding to the opencv c++. from my previous version, I think we just have to implement custom convertion between the two existing type cv2.KeyPoint and cv::KeyPoint
Yes, that's exactly what I call "more straightaway method" 😃. I don't know how to implement such a custom convertor. The reason why I unpack to a tuple in Python, is because tuple is build-in conversion. This process is too slow in python.
A custom convertor, could be much quicker than current solution, although it is still slower than getting the original c++ Object (If we can).
I have used pybind11 for a very short time. I don't know how to access member value of "PyObject".
I haven't use them. There is pybind11 function : py::hasattr
and py::getattr
to access member
Great! That is what I want. Searching these keywords, I know how to implement the converter now. Thanks!
I try to implement this converter, and it works.
#include <Python.h>
#include <opencv2/core/core.hpp>
#include <pybind11/pybind11.h>
namespace py = pybind11;
namespace pybind11 { namespace detail {
template <> struct type_caster<cv::KeyPoint> {
public:
PYBIND11_TYPE_CASTER(cv::KeyPoint, _("cv2.KeyPoint"));
bool load(handle src, bool) {
py::tuple pt = reinterpret_borrow<py::tuple>(src.attr("pt"));
auto x = pt[0].cast<float>();
auto y = pt[1].cast<float>();
auto size = src.attr("size").cast<float>();
auto angle = src.attr("angle").cast<float>();
auto response = src.attr("response").cast<float>();
auto octave = src.attr("octave").cast<int>();
auto class_id = src.attr("class_id").cast<int>();
// (float x, float y, float _size, float _angle, float _response, int _octave, int _class_id)
value = cv::KeyPoint(x, y, size, angle, response, octave, class_id);
return true;
}
static handle cast(const cv::KeyPoint &kp, return_value_policy, handle defval) {
py::object classKP = py::module::import("cv2.KeyPoint");
py::object cvKP = classKP(kp.pt.x, kp.pt.y, kp.size, kp.angle, kp.response, kp.octave, kp.class_id);
// equal to: return handle(cvKP.ptr());
return {cvKP.ptr()};
}
};
}} // namespace pybind11::detail
nice
This repo is really helpful to me.