Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何通过共享内存向python发送cv::Mat? 我有一个C++应用程序,它通过共享内存将数据发送到Python函数。 这在Python中使用ctypes非常有效,例如double和float。现在,我需要向函数添加一个cv::Mat_Python_C++_Opencv_Shared Memory - Fatal编程技术网

如何通过共享内存向python发送cv::Mat? 我有一个C++应用程序,它通过共享内存将数据发送到Python函数。 这在Python中使用ctypes非常有效,例如double和float。现在,我需要向函数添加一个cv::Mat

如何通过共享内存向python发送cv::Mat? 我有一个C++应用程序,它通过共享内存将数据发送到Python函数。 这在Python中使用ctypes非常有效,例如double和float。现在,我需要向函数添加一个cv::Mat,python,c++,opencv,shared-memory,Python,C++,Opencv,Shared Memory,我目前的代码是: //h //主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)

我目前的代码是:

//h

//主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端?我将它作为一个代码> uChar */COD>从C++发送,我理解,我需要它是一个<代码> NoMPy < /CuffelSub,以获得Python中的<代码> CV2.Mat < /C>。从“宽度、高度、通道、帧数据”到opencv python
cv2.Mat
的正确方法是什么

我之所以使用共享内存,是因为速度是一个因素,我已经使用Python API方法进行了测试,它对于我的需要来说太慢了。

总体思路(在OpenCV Python绑定中使用)是创建一个numpy
ndarray
,它与
Mat
对象共享数据缓冲区,并将其传递给Python函数

注意:在这一点上,我将仅限于连续矩阵的例子

我们可以利用这个班

  • 我们需要为numpy数组确定合适的
    dtype
    。这是一个简单的1对1映射,我们可以使用
    开关来实现:

    py::dtype determine_np_dtype(int depth)
    {
        switch (depth) {
        case CV_8U: return py::dtype::of<uint8_t>();
        case CV_8S: return py::dtype::of<int8_t>();
        case CV_16U: return py::dtype::of<uint16_t>();
        case CV_16S: return py::dtype::of<int16_t>();
        case CV_32S: return py::dtype::of<int32_t>();
        case CV_32F: return py::dtype::of<float>();
        case CV_64F: return py::dtype::of<double>();
        default:
            throw std::invalid_argument("Unsupported data type.");
        }
    }
    
  • 提供将共享缓冲区的生存期延长到numpy阵列的生存期的方法。我们可以围绕源代码的浅拷贝
    Mat
    ,创建一个
    pybind11::capsule
    ——由于对象的实现方式,这有效地增加了所需时间的引用计数

    py::capsule make_capsule(cv::Mat& m)
    {
        return py::capsule(new cv::Mat(m)
            , [](void *v) { delete reinterpret_cast<cv::Mat*>(v); }
            );
    }
    
    假设我们有一个Python函数,比如

    def foo(arr):
        print(arr.shape)
    
    在pybind对象中捕获
    fun
    。那么,从C++中调用这个函数,使用<代码>垫>代码>作为源,我们会做这样的事情:

    cv::Mat img; // Initialize this somehow
    
    auto result = fun(mat_to_nparray(img));
    

    示例程序

    #include <pybind11/pybind11.h>
    #include <pybind11/embed.h>
    #include <pybind11/numpy.h>
    #include <pybind11/stl.h>
    
    #include <opencv2/opencv.hpp>
    
    #include <iostream>
    
    namespace py = pybind11;
    
    // The 4 functions from above go here...
    
    int main()
    {
        // Start the interpreter and keep it alive
        py::scoped_interpreter guard{};
    
        try {
            auto locals = py::dict{};
    
            py::exec(R"(
                import numpy as np
    
                def test_cpp_to_py(arr):
                    return (arr[0,0,0], 2.0, 30)
            )");
    
            auto test_cpp_to_py = py::globals()["test_cpp_to_py"];
    
    
            for (int i = 0; i < 10; i++) {
                int64 t0 = cv::getTickCount();
    
                cv::Mat img(cv::Mat::zeros(1024, 1024, CV_8UC3) + cv::Scalar(1, 1, 1));
    
                int64 t1 = cv::getTickCount();
    
                auto result = test_cpp_to_py(mat_to_nparray(img));
    
                int64 t2 = cv::getTickCount();
    
                double delta0 = (t1 - t0) / cv::getTickFrequency() * 1000;
                double delta1 = (t2 - t1) / cv::getTickFrequency() * 1000;
    
                std::cout << "* " << delta0 << " ms | " << delta1 << " ms" << std::endl;
            }        
        } catch (py::error_already_set& e) {
            std::cerr << e.what() << "\n";
        }
    
        return 0;
    }
    

    考虑到这一切都在一个进程中,共享内存似乎是多余的。OpenCV Python绑定使用Python API来映射CV::MAT在C++侧和Python端的NUMPY数组——主要是簿记,底层缓冲区被共享。我很好奇您的Python API方法是什么样子的——很可能是实现问题导致了它的性能低下。谢谢您的回复。在C++和Python之间高速传递CV::MAT数据是可能的吗?我在任何地方都找不到一个示例。请给我一些时间,找出一个基于pybind11的实现甚至还有一些github回购协议与转换器。OpenCV的实现也有代码,只是有点难以理解。谢谢!这将是一个很好的概念证明:|在我写一个答案之前,还需要更多的研究、清理和概括。非常好的答案@谢谢。仍然应该包括非连续的
    Mat
    s(ROI)。我得到以下错误,错误:'array'不是'py'@Fisa的成员。你需要发布一个关于这个的新问题。非常好的解决方案!很有魅力!!
    py::capsule make_capsule(cv::Mat& m)
    {
        return py::capsule(new cv::Mat(m)
            , [](void *v) { delete reinterpret_cast<cv::Mat*>(v); }
            );
    }
    
    py::array mat_to_nparray(cv::Mat& m)
    {
        if (!m.isContinuous()) {
            throw std::invalid_argument("Only continuous Mats supported.");
        }
    
        return py::array(determine_np_dtype(m.depth())
            , determine_shape(m)
            , m.data
            , make_capsule(m));
    }
    
    def foo(arr):
        print(arr.shape)
    
    cv::Mat img; // Initialize this somehow
    
    auto result = fun(mat_to_nparray(img));
    
    #include <pybind11/pybind11.h>
    #include <pybind11/embed.h>
    #include <pybind11/numpy.h>
    #include <pybind11/stl.h>
    
    #include <opencv2/opencv.hpp>
    
    #include <iostream>
    
    namespace py = pybind11;
    
    // The 4 functions from above go here...
    
    int main()
    {
        // Start the interpreter and keep it alive
        py::scoped_interpreter guard{};
    
        try {
            auto locals = py::dict{};
    
            py::exec(R"(
                import numpy as np
    
                def test_cpp_to_py(arr):
                    return (arr[0,0,0], 2.0, 30)
            )");
    
            auto test_cpp_to_py = py::globals()["test_cpp_to_py"];
    
    
            for (int i = 0; i < 10; i++) {
                int64 t0 = cv::getTickCount();
    
                cv::Mat img(cv::Mat::zeros(1024, 1024, CV_8UC3) + cv::Scalar(1, 1, 1));
    
                int64 t1 = cv::getTickCount();
    
                auto result = test_cpp_to_py(mat_to_nparray(img));
    
                int64 t2 = cv::getTickCount();
    
                double delta0 = (t1 - t0) / cv::getTickFrequency() * 1000;
                double delta1 = (t2 - t1) / cv::getTickFrequency() * 1000;
    
                std::cout << "* " << delta0 << " ms | " << delta1 << " ms" << std::endl;
            }        
        } catch (py::error_already_set& e) {
            std::cerr << e.what() << "\n";
        }
    
        return 0;
    }
    
    * 4.56413 ms | 0.225657 ms
    * 3.95923 ms | 0.0736127 ms
    * 3.80335 ms | 0.0438603 ms
    * 3.99262 ms | 0.0577587 ms
    * 3.82262 ms | 0.0572 ms
    * 3.72373 ms | 0.0394603 ms
    * 3.74014 ms | 0.0405079 ms
    * 3.80621 ms | 0.054546 ms
    * 3.72177 ms | 0.0386222 ms
    * 3.70683 ms | 0.0373651 ms