栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何通过共享内存将cv :: Mat发送至python?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何通过共享内存将cv :: Mat发送至python?

总体思路(在OpenCV Python绑定中使用)是创建一个

ndarray
Mat
对象共享其数据缓冲区的numpy ,并将其传递给Python函数。

注意:在这一点上,我将示例限制为仅连续矩阵。

我们可以利用

pybind11::array
该类。

  • 我们需要确定适合

    dtype
    numpy数组使用的数组。这是一个简单的一对一映射,我们可以使用
    switch

    py::dtype determine_np_dtype(int depth)

    {
    switch (depth) {
    case CV_8U: return py::dtype::of();
    case CV_8S: return py::dtype::of();
    case CV_16U: return py::dtype::of();
    case CV_16S: return py::dtype::of();
    case CV_32S: return py::dtype::of();
    case CV_32F: return py::dtype::of();
    case CV_64F: return py::dtype::of();
    default:
    throw std::invalid_argument(“Unsupported data type.”);
    }
    }

  • 确定numpy数组的形状。为了使它的行为类似于OpenCV,让我们将1-channel映射

    Mat
    到2D numpy数组,将multi-channel映射
    Mat
    到3D numpy数组。

    std::vector<std::size_t> determine_shape(cv::Mat& m)

    {
    if (m.channels() == 1) {
    return {
    static_cast(m.rows)
    , static_cast(m.cols)
    };
    }

    return {    static_cast<size_t>(m.rows)    , static_cast<size_t>(m.cols)    , static_cast<size_t>(m.channels())};

    }

  • 提供将共享缓冲区的生存期延长到numpy数组的生存期的方法。我们可以

    pybind11::capsule
    围绕源创建一个浅表副本
    Mat
    -由于对象的实现方式,这可以在所需的时间内有效地增加其引用计数。

    py::capsule make_capsule(cv::Mat& m)

    {
    return py::capsule(new cv::Mat(m)
    , { delete reinterpret_cast(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));}

假设我们有一个Python函数,例如

def foo(arr):    print(arr.shape)

捕获在pybind对象中

fun
。然后使用a
Mat
作为源从C ++调用此函数,我们将执行以下操作:

cv::Mat img; // Initialize this somehowauto 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


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/645294.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号