美文网首页
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