Я пытаюсь понять, как можно получить изображение OpenCV из Python на C ++. Я пытаюсь отправить функцию обратного вызова из C ++ в мой модуль Python, а затем, когда я вызываю определенный метод python в моем приложении C ++, я могу получить доступ к необходимому изображению.
Прежде чем добавить более подробную информацию, я должен добавить, что в этом отношении уже есть несколько вопросов, в том числе:
- как преобразовать-opencv-image- data-from-python-to-c
- pass-image-data-from-python-to-cvmat- in-c
- writing-python-bindings-for-c-code-that- use-opencv
- c-convert-from-numpy-array-to-mat-opencv < / а>
но ни у кого из них нет ничего о Pybind11
. Фактически все они используют PyObject
(из заголовка Python.h
) с Boost.Python
и без него. Итак, моя первая попытка - узнать, как это возможно, Pybind11
зная, что он поддерживает Numpy
массивы, так что, надеюсь, это может значительно упростить задачу.
Также со стороны C++
, OpenCV
имеет две версии: 3.x и 4.x, которые, как я недавно обнаружил, 4.x соответствуют C++11
. со стороны Python я использовал OpenCV 3.x
, и я нахожусь на перекрестке того, какой из них выбрать и какие последствия это имеет, когда дело доходит до Pybind11
.
То, что я пробовал до сих пор: я сделал быстрый фиктивный обратный вызов и попытался передать простой cv::Mat&
, например:
#include <pybind11/embed.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
namespace py = pybind11;
...
void cpp_callback1(bool i, std::string id, cv::Mat img)
{
auto timenow = chrono::system_clock::to_time_t(chrono::system_clock::now());
cout <<"arg1: " << i << " arg2: " << id<<" arg3: " << typeid(img).name() <<" " << ctime(&timenow)<<endl;
}
и использовал это так:
py::list callback_lst;
callback_lst.attr("append")(py::cpp_function(cpp_callback1));
py::dict core_kwargs = py::dict("callback_list"_a = callback_lst,
"debug_show_feed"_a = true);
py::object core_obj = core_cls(**core_kwargs);
core_obj.attr("start")();
но это не удается, за исключением части Python, в которой говорится:
29/03/2020 21:56:47 : exception occured ("(): incompatible function arguments. The following argument types are supported:\n 1. (arg0: bool, arg1: str, arg2: cv::Mat) -> None\n\nInvoked with: True, '5', array([[[195, 217, 237],\n [195, 217, 237],\n [196, 218, 238],\n ...,\n [211, 241, 255],\n [211, 241, 255],\n [211, 241, 255]],\n\n [[195, 217, 237],\n [195, 217, 237],\n [195, 217, 237],\n ...,\n [211, 241, 255],\n [211, 241, 255],\n [211, 241, 255]],\n\n [[195, 217, 237],\n [195, 217, 237],\n [195, 217, 237],\n ...,\n [211, 241, 255],\n [211, 241, 255],\n [211, 241, 255]],\n\n ...,\n\n [[120, 129, 140],\n [110, 120, 130],\n [113, 122, 133],\n ...,\n [196, 209, 245],\n [195, 207, 244],\n [195, 207, 244]],\n\n [[120, 133, 142],\n [109, 121, 130],\n [114, 120, 131],\n ...,\n [195, 208, 242],\n [195, 208, 242],\n [195, 208, 242]],\n\n [[121, 134, 143],\n [106, 119, 128],\n [109, 114, 126],\n ...,\n [194, 207, 241],\n [195, 208, 242],\n [195, 208, 242]]], dtype=uint8)",)
Traceback (most recent call last):
File "C:\Users\Master\Anaconda3\Lib\site-packages\F\utils.py", line 257, in start
self._main_loop()
File "C:\Users\Master\Anaconda3\Lib\site-packages\F\utils.py", line 301, in _main_loop
self._execute_callbacks(is_valid, name, frame)
File "C:\Users\Master\Anaconda3\Lib\site-packages\F\utils.py", line 142, in _execute_callbacks
callback(*args)
TypeError: (): incompatible function arguments. The following argument types are supported:
1. (arg0: bool, arg1: str, arg2: cv::Mat) -> None
Invoked with: True, '5', array([[[195, 217, 237],
[195, 217, 237],
[196, 218, 238],
...,
[211, 241, 255],
[211, 241, 255],
[211, 241, 255]],
[[195, 217, 237],
[195, 217, 237],
[195, 217, 237],
...,
Использование py::object
или py::array_t<uint8_t>
вместо cv::Mat
не вызывает никаких ошибок, но я не могу найти способ правильно преобразовать их обратно в cv::Mat
!
Я попытался преобразовать массив numpy в cv::Mat
, как указано в комментариях, но результат - мусор:
void cpp_callback1(bool i, std::string id, py::array_t<uint8_t>& img)
{
auto im = img.unchecked<3>();
auto rows = img.shape(0);
auto cols = img.shape(1);
auto type = CV_8UC3;
//py::buffer_info buf = img.request();
cv::Mat img2(rows, cols, type, img.ptr());
cv::imshow("test", img2);
}
приводит к:
Мне кажется, шаги или что-то в этом направлении испорчены, что изображение выглядит вот так. что я здесь делаю не так? Однако я не мог использовать img.strides ()! при печати с использованием py :: print он показывает 960
или что-то в этом роде. Так что я совершенно не понимаю, как это интерпретировать!
Mat
. Затем в обратном вызове создайте заголовокMat
для буфера данных массива numpy. (имейте в виду, что это разделяет буфер, поэтому, если вам нужно, чтобыMat
имел более длительный срок службы, чем область обратного вызова, вам придется сделать глубокую копию) - person Dan Mašek   schedule 29.03.2020py::array_t<double>
? - person Rika   schedule 29.03.2020uint8_t
. - person Dan Mašek   schedule 29.03.2020shape
и получить указатель на его буфер данных. - похоже на функцию прямого доступа в pybind давайте сделаем это. - person Dan Mašek   schedule 29.03.2020