cv mat的shape_pybind11—opencv图像处理(numpy数据交换)

本文介绍了如何使用PyBind11库在C++和Python之间进行OpenCV图像处理操作的绑定,包括RGB转灰度、Canny边缘检测和图像金字塔等。通过这些绑定,可以方便地在两种语言间交换和处理numpy数组与OpenCV的Mat对象。
摘要由CSDN通过智能技术生成

前言

C++ opencv中图像和矩阵的表示采用Mat类,比如imread()读取的结果就是返回一个Mat对象。对于python而言,numpy 通常用于矩阵运算, 矩阵,图像表示为numpy.ndarray类。

因此,想要将python numpy.ndarray的数据传递到C++ opencv Mat, 或者C++ Mat将数据返回到python numpy.ndarray, 核心问题——如何绑定Mat

C++

main.cpp

#include

#include

#include

#include

#include

#include

#include"mat_warper.h"

namespace py = pybind11;

py::array_t test_rgb_to_gray(py::array_t& input) {

cv::Mat img_rgb = numpy_uint8_3c_to_cv_mat(input);

cv::Mat dst;

cv::cvtColor(img_rgb, dst, cv::COLOR_RGB2GRAY);

return cv_mat_uint8_1c_to_numpy(dst);

}

py::array_t test_gray_canny(py::array_t& input) {

cv::Mat src = numpy_uint8_1c_to_cv_mat(input);

cv::Mat dst;

cv::Canny(src, dst, 30, 60);

return cv_mat_uint8_1c_to_numpy(dst);

}

/*

@return Python list

*/

py::list test_pyramid_image(py::array_t& input) {

cv::Mat src = numpy_uint8_1c_to_cv_mat(input);

std::vector<:mat> dst;

cv::buildPyramid(src, dst, 4);

py::list out;

for (int i = 0; i < dst.size(); i++)

{

out.append<:array_t char>>(cv_mat_uint8_1c_to_numpy(dst.at(i)));

}

return out;

}

PYBIND11_MODULE(cv_demo1, m) {

m.doc() = "Simple opencv demo";

m.def("test_rgb_to_gray", &test_rgb_to_gray);

m.def("test_gray_canny", &test_gray_canny);

m.def("test_pyramid_image", &test_pyramid_image);

}

mat_warper.h

#ifndef MAT_WARPER_H_

#include

#include

#include

namespace py = pybind11;

cv::Mat numpy_uint8_1c_to_cv_mat(py::array_t& input);

cv::Mat numpy_uint8_3c_to_cv_mat(py::array_t& input);

py::array_t cv_mat_uint8_1c_to_numpy(cv::Mat & input);

py::array_t cv_mat_uint8_3c_to_numpy(cv::Mat & input);

#endif // !MAT_WARPER_H_

mat_warper.cpp

#include"mat_warper.h"

#include

/*

Python->C++ Mat

*/

cv::Mat numpy_uint8_1c_to_cv_mat(py::array_t& input) {

if (input.ndim() != 2)

throw std::runtime_error("1-channel image must be 2 dims ");

py::buffer_info buf = input.request();

cv::Mat mat(buf.shape[0], buf.shape[1], CV_8UC1, (unsigned char*)buf.ptr);

return mat;

}

cv::Mat numpy_uint8_3c_to_cv_mat(py::array_t& input) {

if (input.ndim() != 3)

throw std::runtime_error("3-channel image must be 3 dims ");

py::buffer_info buf = input.request();

cv::Mat mat(buf.shape[0], buf.shape[1], CV_8UC3, (unsigned char*)buf.ptr);

return mat;

}

/*

C++ Mat ->numpy

*/

py::array_t cv_mat_uint8_1c_to_numpy(cv::Mat& input) {

py::array_t dst = py::array_t({ input.rows,input.cols }, input.data);

return dst;

}

py::array_t cv_mat_uint8_3c_to_numpy(cv::Mat& input) {

py::array_t dst = py::array_t({ input.rows,input.cols,3}, input.data);

return dst;

}

//PYBIND11_MODULE(cv_mat_warper, m) {

//

// m.doc() = "OpenCV Mat -> Numpy.ndarray warper";

//

// m.def("numpy_uint8_1c_to_cv_mat", &numpy_uint8_1c_to_cv_mat);

// m.def("numpy_uint8_1c_to_cv_mat", &numpy_uint8_1c_to_cv_mat);

//

//

//}

python中测试

python代码

import cv2

import matplotlib.pyplot as plt

import demo11.cv_demo1 as cv_demo1

import numpy as np

image_rgb = cv2.imread('F:\\le

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用pybind11来将一个cv::Mat对象返回给Python。 首先,你需要在你的C++代码中包含pybind11头文件: #include <pybind11/pybind11.h> #include <pybind11/stl.h> #include <pybind11/numpy.h> 然后,你需要在C++函数中使用pybind11::array_t<T>来返回一个numpy数组。 例如: pybind11::array_t<unsigned char> get_mat_data(const cv::Mat &mat) { // 获取Mat数据的指针 unsigned char *data = mat.data; // 获取数据的尺寸 const size_t size = mat.total() * mat.elemSize(); // 获取Mat的尺寸 const std::vector<size_t> shape = {mat.rows, mat.cols}; // 创建一个numpy数组,其中包含Mat的数据 return pybind11::array_t<unsigned char>(size, data, shape); } 最后,你可以使用pybind11::def来将这个函数绑定到Python: PYBIND11_MODULE(example, m) { m.def("get_mat_data", &get_mat_data); } 在Python中,你可以像调用普通的Python函数一样调用这个函数,并获得一个numpy数组。 import example import numpy as np mat = cv2.imread('image.jpg') data = example.get_mat_data(mat) # 将numpy数组转换回OpenCV格式 mat2 = cv2.cvtColor(np.array(data), cv2.COLOR_RGB2BGR) 希望这可以帮到你! ### 回答2: 通过pybind11cv::Mat返回给Python调用需要以下步骤: 1. 安装pybind11库:首先,你需要安装pybind11库,它是一个用于将C++代码与Python绑定的库。你可以使用pip工具进行安装:`pip install pybind11`。 2. 编写C++代码:在C++代码中,你需要包含 `<pybind11/pybind11.h>` 头文件以及 `<opencv2/opencv.hpp>` 头文件。然后,创建一个函数来将cv::Mat对象转换为Python可用的对象类型。你可以使用`pybind11::array`来表示像素数据,并使用`pybind11::dtype`来表示数据类型。具体代码示例如下: ```cpp #include <pybind11/pybind11.h> #include <pybind11/numpy.h> #include <opencv2/opencv.hpp> namespace py = pybind11; // 将cv::Mat转换为Python可用的对象类型 py::array_t<uint8_t> cvMatToNumpy(const cv::Mat& image) { // 获取图像的尺寸信息 int rows = image.rows; int cols = image.cols; int channels = image.channels(); // 创建一个numpy数组来保存图像数据 py::array_t<uint8_t> result({rows, cols, channels}); auto result_buffer = result.request(); uint8_t* ptr = static_cast<uint8_t *>(result_buffer.ptr); // 将图像数据复制到numpy数组中 std::memcpy(ptr, image.data, rows * cols * channels); return result; } // 使用PYBIND11_MODULE宏定义模块名和函数 PYBIND11_MODULE(cvMatToNumpy, m) { m.def("cvMatToNumpy", &cvMatToNumpy, "Convert cv::Mat to numpy array"); } ``` 3. 编写Python代码:在Python代码中,你可以通过导入C++代码生成的模块来调用C++的函数。具体代码示例如下: ```python import cvMatToNumpy # 加载图像 image = cvMatToNumpy.cvMatToNumpy(image) # 打印图像的形状信息 print(image.shape) # 输出:(height, width, channels) ``` 通过以上步骤,你可以将cv::Mat对象转换为Python可用的numpy数组,并在Python中使用它。 ### 回答3: 通过pybind11cv::Mat返回给Python调用,可以按照以下步骤进行操作: 1. 首先,需要在C++代码中使用pybind11库来编写一个Python扩展模块。在该模块中,使用pybind11提供的API来定义一个函数,该函数将cv::Mat作为返回类型。 2. 在C++代码中,使用cv::Mat来处理图像数据或其他数据,并将结果存储在一个cv::Mat对象中。 3. 使用pybind11提供的API,将C++cv::Mat对象转换为Python的numpy数组。可以使用cv::Mat的成员函数ptr()来获取图像数据的指针,然后使用pybind11提供的numpy::array_t来创建一个Python的numpy数组对象,并将C++图像数据复制到numpy数组中。 4. 在定义的函数中,将numpy数组返回给Python调用,使得Python代码可以对该图像数据进行进一步的处理和分析。 5. 在Python代码中,导入编写的C++扩展模块,并调用定义的函数来获取cv::Mat对象对应的numpy数组。可以将该数组传递给OpenCV中的其他函数进行图像处理或分析。 需要注意的是,使用pybind11cv::Mat返回给Python调用时,需要进行数据类型转换和内存管理操作,以确保数据正确传递和释放内存。同时,还需要确保在C++Python代码之间进行的数据传递以及内存管理的一致性和正确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值