【发布时间】:2020-07-11 22:30:08
【问题描述】:
我有一个 c++ 应用程序,它通过共享内存将数据发送到 python 函数。
这在 Python 中使用 ctypes 非常有用,例如双精度和浮点数。现在,我需要在函数中添加一个cv::Mat。
我目前的代码是:
//h
#include <iostream>
#include <opencv2\core.hpp>
#include <opencv2\highgui.hpp>
struct TransferData
{
double score;
float other;
int num;
int w;
int h;
int channels;
uchar* data;
};
#define C_OFF 1000
void fill(TransferData* data, int run, uchar* frame, int w, int h, int channels)
{
data->score = C_OFF + 1.0;
data->other = C_OFF + 2.0;
data->num = C_OFF + 3;
data->w = w;
data->h = h;
data->channels = channels;
data->data = frame;
}
//.cpp
namespace py = pybind11;
using namespace boost::interprocess;
void main()
{
//python setup
Py_SetProgramName(L"PYTHON");
py::scoped_interpreter guard{};
py::module py_test = py::module::import("Transfer_py");
// Create Data
windows_shared_memory shmem(create_only, "TransferDataSHMEM",
read_write, sizeof(TransferData));
mapped_region region(shmem, read_write);
std::memset(region.get_address(), 0, sizeof(TransferData));
TransferData* data = reinterpret_cast<TransferData*>(region.get_address());
//loop
for (int i = 0; i < 10; i++)
{
int64 t0 = cv::getTickCount();
std::cout << "C++ Program - Filling Data" << std::endl;
cv::Mat frame = cv::imread("input.jpg");
fill(data, i, frame.data, frame.cols, frame.rows, frame.channels());
//run the python function
//process
py::object result = py_test.attr("datathrough")();
int64 t1 = cv::getTickCount();
double secs = (t1 - t0) / cv::getTickFrequency();
std::cout << "took " << secs * 1000 << " ms" << std::endl;
}
std::cin.get();
}
//Python //传输数据类
import ctypes
class TransferData(ctypes.Structure):
_fields_ = [
('score', ctypes.c_double),
('other', ctypes.c_float),
('num', ctypes.c_int),
('w', ctypes.c_int),
('h', ctypes.c_int),
('frame', ctypes.c_void_p),
('channels', ctypes.c_int)
]
PY_OFF = 2000
def fill(data):
data.score = PY_OFF + 1.0
data.other = PY_OFF + 2.0
data.num = PY_OFF + 3
//主要Python函数
import TransferData
import sys
import mmap
import ctypes
def datathrough():
shmem = mmap.mmap(-1, ctypes.sizeof(TransferData.TransferData), "TransferDataSHMEM")
data = TransferData.TransferData.from_buffer(shmem)
print('Python Program - Getting Data')
print('Python Program - Filling Data')
TransferData.fill(data)
如何将cv::Mat 帧数据添加到 Python 端?我从 c++ 将它作为uchar* 发送,据我所知,我需要它是一个numpy 数组才能在Python 中获得cv2.Mat。从 'width, height, channels, frameData' 到 opencv python cv2.Mat 的正确方法是什么?
我使用共享内存是因为速度是一个因素,我已经使用 Python API 方法进行了测试,但它对于我的需求来说太慢了。
【问题讨论】:
-
鉴于这一切都在一个进程中,共享内存似乎相当多余。 OpenCV Python 绑定使用 Python API 在 C++ 端的 cv::Mat 和 Python 端的 numpy 数组之间进行映射——主要是记账,共享底层缓冲区。我很好奇你的 Python API 方法是什么样子的——更可能是一个导致它表现不佳的实现问题。
-
感谢您的回复。是否可以在 c++ 和 Python 之间高速传递 cv::Mat 数据?我在任何地方都找不到示例。
-
给我一些时间来找出一个基于 pybind11 的实现。 | google.com/search?q=cv::Mat+to+numpy+site:stackoverflow.com 甚至还有几个带有转换器的 github 存储库。 OpenCV的实现也有代码,就是有点难摸。
-
谢谢!那太好了
-
小概念证明:pastebin.com/N312Twqz |在我写答案之前仍然需要更多的研究、清理和概括。
标签: python c++ opencv shared-memory