美文网首页
python 调用 c++dll, 包含类以及opencv Ma

python 调用 c++dll, 包含类以及opencv Ma

作者: 去大海边吹海风 | 来源:发表于2018-06-12 14:08 被阅读0次

    前言

    由于这个尝试花了一些时间,所以记录下来。由于我是尝试的很多理论地方不大懂,我把我尝试成功的部门记录下来,希望对大家有所帮助。

    我的环境是windows10 + vs2015

    创建 vs dll project

    python所有不同的调用方式都需要先建一个dll project。

    • 新建一个c++工程,选择DLL、导出符号和空项目(如下图);


      IMG20180612_131008.png
    • c++ 默认的解决平台是32位的,如果python是64位的,需要把c++ 解决平台修改为64位;

    python 调用 c++普通函数

    为了写文档,尝试了以下链接中的简单例子,可行。
    https://blog.csdn.net/sloanqin/article/details/51505478

    python 调用 struct

    最开始尝试struct是以下链接中的例子,可行。
    https://blog.csdn.net/iceboy314159/article/details/53192175

    python 调用 class

    pro.h 文件

    #include <opencv2/opencv.hpp>
    
    #ifndef _pro_header_2014_  
    #define _pro_header_2014_  
    
    #ifdef EXPORT_PRO_DLL  
    #define PRO_API __declspec(dllexport)  
    #else  
    #define PRO_API __declspec(dllimport)  
    #endif  
    
    class Foo
    {
        public:
            Foo(cv::Mat);
            void bar();
            int* foobar(cv::Mat);
        private:
            cv::Mat val;
    };
    
    extern "C"
    {
        PRO_API Foo* Foo_new(int rows, int cols, unsigned char* imgdata);
        PRO_API void Foo_bar(Foo* foo); 
        PRO_API int* Foo_foobar(Foo* foo, int rows, int cols, unsigned char* imgdata);
    }
    #endif // !_pro_header_2014_  
    
    

    pro.cpp 文件

    #define EXPORT_PRO_DLL
    
    #include "pro.h"
    #include "string.h"
    #include<iostream>
    
    using namespace std;
    
    Foo::Foo(cv::Mat n)
    {
        val = n;
    }
    void Foo::bar()
    {
        std::cout << "Value is " << val << std::endl;
    }
    int* Foo::foobar(cv::Mat n)
    {
        int *data = new int[2];
        data[0] = 1;
        data[1] = 2;
        return data;
    }
    
     
    PRO_API Foo* Foo_new(int rows,int cols, unsigned char* imgdata) { 
        cv::Mat img(rows, cols, CV_8UC3, (void *)imgdata);
        return new Foo(img);
    }
    PRO_API void Foo_bar(Foo* foo) { foo->bar(); }
    PRO_API int* Foo_foobar(Foo* foo, int rows, int cols, unsigned char* imgdata) {
        cv::Mat img(rows, cols, CV_8UC3, (void *)imgdata);
        return foo->foobar(img);
    }
    

    python code, 其中的图像读入,需要根据你自己的修改

    from ctypes import *
    
    class Foo(object):
        def __init__(self, img):
            lib.Foo_new.argtypes = [c_int,c_int,POINTER(c_ubyte)]
            lib.Foo_new.restype = c_void_p
            lib.Foo_bar.argtypes = [c_void_p]
            lib.Foo_bar.restype = c_void_p
            lib.Foo_foobar.argtypes = [c_void_p,c_int,c_int,POINTER(c_ubyte)]
            lib.Foo_foobar.restype = POINTER(c_int)
            (rows, cols) = (img.shape[0], img.shape[1])
            self.obj = lib.Foo_new(rows, cols,img.ctypes.data_as(POINTER(c_ubyte)))
        def bar(self):
            lib.Foo_bar(self.obj)
    
        def foobar(self, img):
            (rows, cols) = (img.shape[0], img.shape[1])
            return lib.Foo_foobar(self.obj, rows, cols,img.ctypes.data_as(POINTER(c_ubyte)))
    
    if __name__ == '__main__':
        root_path = 'E:/tracking/data/Girl'
        imglist = scan_image(os.path.join(root_path, 'img'))
        for imgname in imglist:
            img = cv2.imread(os.path.join(root_path, 'img', imgname))
            f = Foo(img)
            f.bar()
            rect = f.foobar(img)
            print(rect[0],rect[1])
    

    后记

    • 以上代码包含了Mat的处理和数组的处理,其中rect应该是返回cv::Rect类型,由于不会处理,所以转换成了int 数组类型,如果你有更优雅的方法,请赐教。
    • argtypes ,restype 分别是参数类型和返回值类型的定义,在类中是必不可少的,而且必须对应。比如c_float写成 c_int,结果就会不一样或者报错。

    参考文章

    class 调用:
    http://www.auctoris.co.uk/2017/04/29/calling-c-classes-from-python-with-ctypes/
    Mat 处理方式:
    https://stackoverflow.com/questions/19031836/get-background-model-from-backgroundsubtractormog2-in-python

    相关文章

      网友评论

          本文标题:python 调用 c++dll, 包含类以及opencv Ma

          本文链接:https://www.haomeiwen.com/subject/gmmleftx.html