C/C++代码封装为Python模块(含OpenCV-Mat转换)

本文介绍如何在Ubuntu环境下,使用C/C++与Python进行混合编程,通过封装C/C++函数供Python调用,实现图像处理功能。具体步骤包括准备Ubuntu、Python、boost、OpenCV等环境,配置cmake,编辑并封装C/C++代码,最终通过Python调用这些函数。
部署运行你感兴趣的模型镜像

准备资料

Ubuntu16.04或者其他版本

Python2.x或者Python3.x

boost_1_69_0或者其他版本 // https://www.boost.org/users/history/version_1_69_0.html

OpenCV3.4.3或者其他版本 // https://www.opencv.org/releases.html

pyboostcvconverter(大佬写的python boost opencv的转换器) // https://github.com/Algomorph/pyboostcvconverter

配置环境

安装Python

sudo apt install python3-dev build-essential

安装C++ boost

cd boost_1_69_0

./bootstrap.sh --with-python=python3.5 # python3.6->3.6

./b2

sudo ./b2 install

cmake pyboostcvconverter

在pyboostcvconverter目录下新建build文件夹

运行cmake-gui

where is source code: pyboostcvconverter根目录

where to build the binaries: pyboostcvconverter根目录刚新建的build目录

Configure && Generate

到此,cmake完成。就可以开始转换封装了。

开始封装

在pyboostcvconverter/src目录下有4个文件:

pyboost_cv2_converter.cpp  pyboost_cv3_converter.cpp  pyboost_cv4_converter.cpp  python_module.cpp

到此就可以修改python_module.cpp来增加自己的C/C++代码(这边增加两个C++函数封装供python调用)代码如下:

cv::Mat to_gray(cv::Mat srcMat); // 转灰度

cv::Mat to_binary(cv::Mat srcMat, int t, int max);// 二值化

#define PY_ARRAY_UNIQUE_SYMBOL pbcvt_ARRAY_API

#include <boost/python.hpp>
#include <pyboostcvconverter/pyboostcvconverter.hpp>
#include <opencv2/opencv.hpp>

namespace pbcvt {

    using namespace boost::python;

/**
 * @brief Example function. Basic inner matrix product using explicit matrix conversion.
 * @param left left-hand matrix operand (NdArray required)
 * @param right right-hand matrix operand (NdArray required)
 * @return an NdArray representing the dot-product of the left and right operands
 */
    PyObject *dot(PyObject *left, PyObject *right) {

        cv::Mat leftMat, rightMat;
        leftMat = pbcvt::fromNDArrayToMat(left);
        rightMat = pbcvt::fromNDArrayToMat(right);
        auto c1 = leftMat.cols, r2 = rightMat.rows;
        // Check that the 2-D matrices can be legally multiplied.
        if (c1 != r2) {
            PyErr_SetString(PyExc_TypeError,
                            "Incompatible sizes for matrix multiplication.");
            throw_error_already_set();
        }
        cv::Mat result = leftMat * rightMat;
        PyObject *ret = pbcvt::fromMatToNDArray(result);
        return ret;
    }
/**
 * @brief Example function. Simply makes a new CV_16UC3 matrix and returns it as a numpy array.
 * @return The resulting numpy array.
 */

	PyObject* makeCV_16UC3Matrix(){
		cv::Mat image = cv::Mat::zeros(240,320, CV_16UC3);
		PyObject* py_image = pbcvt::fromMatToNDArray(image);
		return py_image;
	}

//
/**
 * @brief Example function. Basic inner matrix product using implicit matrix conversion.
 * @details This example uses Mat directly, but we won't need to worry about the conversion in the body of the function.
 * @param leftMat left-hand matrix operand
 * @param rightMat right-hand matrix operand
 * @return an NdArray representing the dot-product of the left and right operands
 */
    cv::Mat dot2(cv::Mat leftMat, cv::Mat rightMat) {
        auto c1 = leftMat.cols, r2 = rightMat.rows;
        if (c1 != r2) {
            PyErr_SetString(PyExc_TypeError,
                            "Incompatible sizes for matrix multiplication.");
            throw_error_already_set();
        }
        cv::Mat result = leftMat * rightMat;

        return result;
    }

    /**
     * \brief Example function. Increments all elements of the given matrix by one.
     * @details This example uses Mat directly, but we won't need to worry about the conversion anywhere at all,
     * it is handled automatically by boost.
     * \param matrix (numpy array) to increment
     * \return
     */
    cv::Mat increment_elements_by_one(cv::Mat matrix){
        matrix += 1.0;
        return matrix;
    }


// Edit by kaychan 2019-03-05
	cv::Mat to_gray(cv::Mat srcMat) { // 在此添加你的C/C++代码

		cv::Mat gray;
		cv::cvtColor(srcMat, gray, COLOR_BGR2GRAY);
		return gray;
	}


	cv::Mat to_binary(cv::Mat srcMat, int t, int max) {

		cv::Mat thresh;
		cv::threshold(srcMat, thresh, t, max, 0);
		return thresh;
	}

#if (PY_VERSION_HEX >= 0x03000000)

    static void *init_ar() {
#else
        static void init_ar(){
#endif
        Py_Initialize();

        import_array();
        return NUMPY_IMPORT_ARRAY_RETVAL;
    }

    BOOST_PYTHON_MODULE (pbcvt) {
        //using namespace XM;
        init_ar();

        //initialize converters
        to_python_converter<cv::Mat,pbcvt::matToNDArrayBoostConverter>();
        matFromNDArrayBoostConverter();

        //expose module-level functions
        def("dot", dot);
        def("dot2", dot2);
		def("makeCV_16UC3Matrix", makeCV_16UC3Matrix);

		//from PEP8 (https://www.python.org/dev/peps/pep-0008/?#prescriptive-naming-conventions)
        //"Function names should be lowercase, with words separated by underscores as necessary to improve readability."
        def("increment_elements_by_one", increment_elements_by_one);
	def("to_gray", to_gray); 	// 在此声明你的C/C++代码
	def("to_binary", to_binary);
    }

} //end namespace pbcvt

代码编写完成后,回到pyboostcvconverter目录,运行:

cmake .

make

这时候就会在当前目录下生成pbcvt.cpython-36m-x86_64-linux-gnu.so,就可以使用python import这个模块,然后使用python调用C/C++函数。

开始调用

到此可以使用python调用刚才编写的C/C++代码了,如下图:

可以看到,to_gray,to_binary函数已经调用成功了。到此,可以根据自己的需求进行封装调用了···

更多

在Windows下cmake pyboostcvconverter:

打开cmd运行bootstrap.bat

b2 --with-python

b2 install

打开cmake添加entry:add entry:BOOST_ROOT=your_boost_root

到此就可以利用VS编译了。

 

您可能感兴趣的与本文相关的镜像

AutoGPT

AutoGPT

AI应用

AutoGPT于2023年3月30日由游戏公司Significant Gravitas Ltd.的创始人Toran Bruce Richards发布,AutoGPT是一个AI agent(智能体),也是开源的应用程序,结合了GPT-4和GPT-3.5技术,给定自然语言的目标,它将尝试通过将其分解成子任务,并在自动循环中使用互联网和其他工具来实现这一目标

C++项目中使用OpenCV-Python库,实际上是指在C++代码中调用OpenCVPython接口,或者将Python代码嵌入到C++程序中,以实现图像处理、计算机视觉等任务。OpenCV-PythonOpenCVPython绑定,而OpenCV本身是一个C++库,因此它提供了与Python的互操作性,允许开发者在C++Python之间进行数据交换[^2]。 ### 在C++中调用OpenCV-Python的方式 #### 1. 使用`pybind11`嵌入Python解释器 `pybind11` 是一个轻量级的C++11库,用于在C++中调用Python代码。通过它,可以在C++程序中调用Python函数、传递参数、处理返回值等。 以下是一个使用 `pybind11` 调用OpenCV-Python代码的示例: ```cpp #include <pybind11/embed.h> // 包 pybind11 嵌入头文件 #include <iostream> namespace py = pybind11; int main() { py::scoped_interpreter guard{}; // 初始化嵌入式Python解释器 // 导入cv2模块 py::module_ cv2 = py::module_::import("cv2"); // 读取图像 py::object img = cv2.attr("imread")("example.jpg"); // 检查图像是否为空 if (img.attr("any")().cast<bool>()) { std::cout << "Image loaded successfully." << std::endl; // 显示图像 cv2.attr("imshow")("Image", img); cv2.attr("waitKey")(0); } else { std::cerr << "Failed to load image." << std::endl; } return 0; } ``` 编译时需要链接Python解释器和OpenCV库: ```bash g++ -O3 -Wall -shared -std=c++11 -fPIC `python3-config --includes` main.cpp -o example `python3-config --libs` -lopencv_core -lopencv_highgui ``` #### 2. 使用OpenCVC++接口与Python数据交互 OpenCVC++接口可以直接与Python的`numpy`数组进行互操作。例如,可以将Python中的`numpy.ndarray`传递给C++函数,反之亦然。OpenCV的`cv::Mat`结构与`numpy`数组在内存布局上是兼容的,因此可以通过指针传递数据[^3]。 ##### 示例:从Python传递图像到C++Python端: ```python import numpy as np import cv2 img = cv2.imread('example.jpg') # 调用C++函数处理图像 result = cpp_process_image(img) # 假设cpp_process_image是C++封装的函数 ``` 在C++端(使用`pybind11`): ```cpp #include <pybind11/pybind11.h> #include <pybind11/numpy.h> #include <opencv2/opencv.hpp> namespace py = pybind11; cv::Mat numpy_to_mat(py::array_t<unsigned char> array) { py::buffer_info info = array.request(); cv::Mat mat(info.shape[0], info.shape[1], CV_8UC3, info.ptr); return mat; } PYBIND11_MODULE(example, m) { m.def("process_image", &numpy_to_mat, "Process image from Python"); } ``` --- ### 注意事项 - 在使用`pybind11`时,必须确保Python环境和OpenCV-Python库已正确安装,并且C++编译器能够找到Python的头文件和库[^1]。 - OpenCVC++接口和Python接口在功能上是同步的,因此大多数图像处理操作都可以在两者之间无缝切换。 - 如果需要高性能处理,建议尽量在C++层完成图像处理,仅在必要时与Python交互,以减少跨语言调用的开销。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值