SWIG 扩展Opencv python调用C++
osx:10.12 g++ 7.1 swig 3.0.12 opencv 3.2.0
SWIG是Simplified Wrapper and Interface Generator的缩写。是Python中调用C代码的另一种方法。在这个方法中,开发人员必须编写一个额外的接口文件来作为SWIG(终端工具)的入口
SWIG在官网上有很详细的例子这里就只针对opencv进行讲述
安装SWIG
brew install swig
这里用一个小例子来先简单介绍SWIG
//example.hpp
#ifndef example_hpp
#define example_hpp
#include <iostream>
#include <vector>
class Test{
public:
Test(){
for(int i=0;i<10;i++) v.push_back(i);
}
void see();
private:
std::vector<int> v;
};
#endif
//example.cpp
#include "example.hpp"
#include <stdio.h>
using namespace std;
void Test::see(){
for(int i=0;i<(this->v).size();i++)
printf("%d ",v[i]);
}
如何将这个类以及这个类的方法放在python里面调用呢
1.编写转换规则 example.i(接口文件)
%module example
%include "std_vector.i"
%{
#include "example.hpp"
%}
%include "example.hpp"
第一行 %module后面的名字是被封装的模块名称,Python通过这个名称来加载程序。
第二行是文件所以依赖的头文件,vector本是STL里面的,但是SWIG已经有对应的"std_vector.i"写好了,所以可以直接%include "std_vector.i"
,如果在python里面需要用到vector的话,在转换规则里面还要添加模版类型,具体参考SWIG的DOC http://www.swig.org/Doc1.3/Library.html
大括号里面所添加的内容,一般包含此文件需要的一些函数声明和头文件。
最后一行是声明了要封装的函数和变量,因为函数声明写在了头文件里面,如果全部封装的话可以直接%include 头文件名
2.封装代码,生成中间文件
swig -python -c++ example.i
这样会生成两个文件
example.cxx
,example.py
example.cxx :编译c++时用
example.py:python import包时使用
3.使用distutils工具或命令编译
"""
setup.py
"""
from distutils.core import setup,Extension
setup(name = "example",
version = "1.0",
ext_modules = [Extension("_example", ["example_wrap.cxx", "example.cpp"],
extra_compile_args = ['-std=c++11'])],
py_modules=['example'])
sudo python setup.py install
注意模块名称那里一定前面要加下划线
这会将生成的_example.so 和 example.py 送到python对应的package文件夹里
额外的参数和额外的库都跟着需要更改
4.Python引用
In [1]: from example import *
In [2]: x = Test()
In [3]: x.see()
0 1 2 3 4 5 6 7 8 9
注意的问题:
c++中声明的方法必须实现
GCC版本要和Python的底层版本一样
在编写接口文件的时候,需要将依赖的头文件都添加进来,而opencv里面的文件繁多,在Github上面有人已经写好了opencv.i
安装方法:
没什么安装方法。。。下载文件直接将lib里面的文件复制到你Code的文件夹下面就好了。
使用方法在主页上有介绍
需要注意的是在写接口文件的时候,如果需要自己定义vector在python里面的接口,会出现redefinition的问题,因为作者写的借口文件里面已经实现过了vector的接口,不需要写,其他的STL类没有试过,出现redefinition时估计也是一样的问题。
作者没有写文档,在调用接口的时候需要去查作者的test,比如opencv里面的
cv::Mat ,在封装成python之后需要调用作者的module_name.Mat.from_array(img)
转换成cv::Mat
参考文档:
http://blog.csdn.net/jiangpeng59/article/details/73554835
http://cering.github.io/2015/12/08/使用SWIG实现Python调用C-C-代码/
https://github.com/renatoGarcia/opencv-swig