Windows下Python通过Swig调用含OpenCV的C++代码

想用python调C++写的opencv代码,网上的资料都是模棱两可,连github上的opencv swig接口项目也没好好写说明。

花了两天踏平若干大坑,终于调通,顺手解决了开源库的bug,写下本文方便后人。

能用python调OpenCV,那么调普通的C++ dll更不成问题了,也可以参考本文。

关于swig生成python扩展,网上的方法一般是在cmd中完成的,需写个setup.py,用python的distutils编译生成python扩展。

但其实还可以用VS完成整个过程,我懒得学setup.py的写法,最后就采用的这种。

---------------------------------------------------------

环境:win10, VS2019,python3.6

C++代码:SwigTest.h, SwigTest.cpp ,放在配置好OpenCV的创建dll的工程中(Release, x64)

目标:把C++代码编译成python扩展,实现“import SwigTest”的调用

Windows下Python通过Swig调用含OpenCV的C++代码_第1张图片

(def是空的,没它的话可以Release,但没法Debug)

一,下载

swig下载:http://www.swig.org (我下的是swigwin-4.0.2)

OpenCV-Swig下载:https://github.com/renatoGarcia/opencv-swig(这是github上一个项目,下载后解压得到opencv-swig-master文件夹。这个项目是帮你写好了C++ OpenCV的swig接口文件,但里面有个bug,被我扒源码找到了,后面会教你改)

boost下载:https://www.boost.org

二,系统环境配置

1,解压把swig.exe所在路径添加到环境变量path,这就是安装swig的全部操作了

2,添加python.h和python36.lib所在路径到系统变量。该操作必须重启VS后才能在VS中生效!

Windows下Python通过Swig调用含OpenCV的C++代码_第2张图片

3,安装boost,方法见这篇https://blog.csdn.net/bxbjk/article/details/100760154,安装时间1~2小时

三,项目配置

1,打开工程文件夹,我的是SwigTest,将..\opencv-swig-master\lib 下的 opencv.iopencv文件夹 拷进来。

开个玩笑,这里有个bug要改,改完再拷。打开..\opencv-swig-master\lib\opencv\matx.i :

Windows下Python通过Swig调用含OpenCV的C++代码_第3张图片

请找到这个位置,然后把红框框出的两根下划线删掉,否则就会出bug!

然后就可以拷了:

Windows下Python通过Swig调用含OpenCV的C++代码_第4张图片

2,在 Visual Studio 新建一个 xxx.i 的文件。我这里命名为example.i, 这是swig的接口文件

Windows下Python通过Swig调用含OpenCV的C++代码_第5张图片

由于我的SwigTest.cpp用到了vector和vector,正确的内容如下:

%module SwigTest

%include 
%include "std_vector.i"
%include "std_string.i"
%cv_instantiate_all_defaults

%template(StrVector) std::vector;

%{
#include "SwigTest.h"
%}

%include "SwigTest.h"

将来编译 example.i 时,会调用刚拷过来的 opencv.i,然后 opencv.i 会去调其他的 .i 文件。

%template那句表示在python中用 StrVector类代替C++的vector

需要强调的是:通常如果C++里用到vector了,你的 xxx.i文件里会有这么一行:

Windows下Python通过Swig调用含OpenCV的C++代码_第6张图片

但是在OpenCV-Swig项目中,vector的接口是个坑,这一行必须删掉!

否则后面编译时会出现  C2084:函数**已有主体 的报错:

Windows下Python通过Swig调用含OpenCV的C++代码_第7张图片
这是因为Opencv-Swig 里已经帮你写了vector的接口,就是在之前改bug的位置:

Windows下Python通过Swig调用含OpenCV的C++代码_第8张图片

这里实现且仅实现了以下C++数据类型的vecotr向量转换:uint8_t, short, ushort, int, float, double

所以如果你的C++代码里有vector,那么将来在python里就用 floatArray 代替:

vf = floatArray()
vf = (1.1, 3.14, 2.8)

至于vector,还是得自己写 %template

3,VS中右击SwigTest项目,做如下配置:

Windows下Python通过Swig调用含OpenCV的C++代码_第9张图片

Windows下Python通过Swig调用含OpenCV的C++代码_第10张图片

Windows下Python通过Swig调用含OpenCV的C++代码_第11张图片

4,右击example.i -> 属性,项类型选择“自定义生成工具”,单击“应用”

Windows下Python通过Swig调用含OpenCV的C++代码_第12张图片

然后在 自定义生成工具 -> 常规 -> 命令行 添加 swig.exe -c++ -python "%(FullPath)",

输出 中 添加 $(InputName)_wrap.cxx

Windows下Python通过Swig调用含OpenCV的C++代码_第13张图片

四,编译

1,右击example.i -> 编译。VS会报错,各个 .i文件找不到opencv的那些hpp,

随便打开一个mat.i看一下就知道,问题出在这儿:

Windows下Python通过Swig调用含OpenCV的C++代码_第14张图片

这时你有两个选择:

a,在红框里补充core.hpp的完整路径(斜杠方向没有影响),每个.i文件的 #include <..../*.hpp> 都要补,比如我就是:

#include 

b.直接把 ...\opencv\build\include\ 下的opencv2文件夹拷到当前工程目录。这个文件夹也就5Mb大小。

傻子都知道怎么选吧?

Windows下Python通过Swig调用含OpenCV的C++代码_第15张图片

2,然后再次右击example.i -> 编译,得到example_wrap.cxx,把它加到你的VS项目中

Windows下Python通过Swig调用含OpenCV的C++代码_第16张图片        Windows下Python通过Swig调用含OpenCV的C++代码_第17张图片

 

3,VS 生成 -> 生成解决方案,静候片刻,看到工程文件夹下得到了两个宝贝:

Windows下Python通过Swig调用含OpenCV的C++代码_第18张图片

SwigTest.py 和 _SwigTest.pyd 就是我们要的Python扩展了,大功告成。

五,Opencv-Swig使用方法

参考这个帖子:how can I wrap return type `std::vector`

Windows下Python通过Swig调用含OpenCV的C++代码_第19张图片

C++的cv::Mat转python用 np.asarray()

python的Mat转C++的cv:Mat用 SwigTest.from_array()

你可能感兴趣的:(python混合编程,python,swig,opencv)