OpenCV C++ Python混合编译中的矩阵传參

本文主要简化该博文的代码,解决了混合编译中矩阵传输问题(C++ Mat -----> Python numpy array),经过测试任意维度和数据类型的Mat均可使用此方法。python安装 opencv源码安装这里就不做讲解了,网上方法多着是。

值得注意以下几点:

1、本次操作在Ubuntu 16.04下进行。
2、在Ubuntu下也有图形化界面的cmake,使用sudo apt install cmake-qt-gui安装,使用这个配置opencv更加直观方便。
3、当配置安装路径不是默认的/usr/local时,需要注意要将编译生成路径下的/lib/python3.5文件夹拷贝到/usr/local/lib下。例如:我的opencv安装路径在/usr/local/opencv,并且我编译了python3.5,我需要将/usr/local/opencv/lib/python3.5下的文件拷贝到/usr/local/lib/python3.5下,否则编译的opencv在python中不可被调用
4、pip install安装后的文件放在~/.local/lib/python3.5下,sudo pip install在/usr/local/lib下
5、需要运行sudo apt install python3-dev 安装python的库,否则会报找不到Python.h错误。
6、需要运行sudo apt install python-numpy安装numpy库,否者会报找不到numpy/arrayobject.h错误。

混合编译指令:

终端端指令:

g++ -I/usr/include/python3.5 pythonwithcpp.cpp -L/usr/lib/python3.5/config-3.5m-x86_64-linux-gnu -lpython3.

CLion CMakeLists.txt(使用其他IDE的配置方法会有所不同)

#工程名:test
cmake_minimum_required(VERSION 3.14)
project(test)

set(CMAKE_CXX_STANDARD 14)
set(Python_ADDITIONAL_VERSIONS 3.5)
add_executable(test main.cpp)

find_package(PythonLibs 3 REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
target_link_libraries(test ${PYTHON_LIBRARIES})
find_package(OpenCV REQUIRED)
target_link_libraries(test ${OpenCV_LIBS})

代码功能描述:

本代码实现了一个使用C++ opencv打开摄像头读取图像,将图像传输给python opencv(numpy array类型)并显示,然后将图像返回,C++ opencv接收返回值,并显示图像。简单来说就是C++ —> Python —> C++。

main.cpp
#include <iostream>
#include <python3.5/Python.h>
#include <numpy/arrayobject.h>
#include <opencv2/opencv.hpp>

int main(int argc, char* argv[])
{
    //初始化python
    Py_Initialize();
    import_array();     //numpy初始化,会报迷之警告,大家忽略它吧
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('./')");				//将当前路径加入,否者会出现找不到模块,这两句话非常重要
    PyObject *py_Module = PyImport_ImportModule("TestModule");          //引入模块
    PyObject *py_main = PyObject_GetAttrString(py_Module,"main");       //获取main函数

    npy_intp Dims[3] = {480, 640, 3}; //给定维度信息

    cv::VideoCapture cap(1);
    cv::Mat frame;

    while(1)
    {
        cap>>frame;

        /*生成包含这个多维数组的PyObject对象,使用PyArray_SimpleNewFromData函数,
         * 第一个参数2表示维度,第二个为维度数组Dims,第三个参数指出数组的类型,第四个参数为数组*/
        /*关键:直接将矩阵的数据指针传入即可 numpy操作即可转换程对Mat操作。经测试任意维度的任意类型数据均适用*/
        PyObject *PyArray  = PyArray_SimpleNewFromData(3, Dims, NPY_UBYTE, frame.data);
        PyObject *ArgArray = PyTuple_New(1);
        PyTuple_SetItem(ArgArray, 0, PyArray); //同样定义大小与Python函数参数个数一致的PyTuple对象
        PyArrayObject *py_return = (PyArrayObject *)PyEval_CallObject(py_main, ArgArray);
        /*关键: 反馈回来的数据直接将矩阵数据指针指向ArrayObject的数据即可*/
        cv::Mat img(cv::Size(640,480),CV_8UC3);
        img.data = (u_char*)py_return->data;            //直接将图像的数据指针指向numpy返回的数据
        cv::imshow("c++",img);
        cv::waitKey(1);
    }
    Py_Finalize();    //释放python
    return 0;
}
TestModule.py
import cv2

def main(img):
    cv2.imshow('py', img)
    cv2.waitKey(1)
    return img

if __name__ == "__main__":
    cap = cv2.VideoCapture(1)
    while True:
        _, img = cap.read()
        main(img)

最后也抛出一个问题,就是在返回参素的时候直接用指针指向返回的数据,这种操作安全吗?会不会被python释放掉那块内存而导致指针非法呢?虽然这个代码我跑了10多分钟都没出现问题。希望懂的大佬能解答一下。谢谢!!!!!

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值