[和小菜鸡一起玩OpenCV] Windows下NumPy ndarray与C++ cv::Mat的互相转换

前言

当我们想要从Python调用C++中的OpenCV方法时,通常需要将Python中的ndarray类型转换成C++中的cv::Mat。本文使用的方法是Boost.python + github上Algomorph的pyboostcvconverte,其中Boost版本为1.70.0。使用的其他软件环境为Windows x64 + CMake 3.15.0 + Visual Studio 2017 + Python 3.6.5 + OpenCV 3.4.6。

Boost库

简介

Boost库是C++的一系列扩展库,根据Boost官网介绍,其中一部分库已经被纳入C++ 11标准,而他们的目标是使更多的Boost库出现在C++ 17标准中,总之是相当厉害。本文中主要用到的是Boost.python,其主要提供了Python的接口,从而方便Python与C++的混合编程。关于Boost以及Boost.python安装编译的相关知识,个人推荐Henry606的这篇博文:C++与Python混合编程:Boost.python的安装与使用

版本

起初我使用的是Boost 1.68.0版本,在运行官方示例代码时,会发生错误'unwind_type': identifier not found。经过一通搜索,在微软相关文档中找到如下文字:

Note: In the Boost python library, there has been for a long time an MSVC-specific workaround for a template forward declaration in unwind_type.hpp. Under /permissive- mode starting with Visual Studio 2017 version 15.8 (_MSC_VER=1915), the MSVC compiler does argument-dependent name lookup (ADL) correctly and is consistent with other compilers, making this workaround guard unnecessary. To avoid error C3861: ‘unwind_type’: identifier not found, see PR 229 in the Boost repo to update the header file. We’ve already patched the vcpkg Boost package, so if you get or upgrade your Boost sources from vcpkg then you don’t need to apply the patch separately.

总之从Visual Studio 2017 version 15.8 起就会出这个错,若要避免就从vcpkg更新Boost源文件。因而在本文中,我使用了Boost 1.70.0版本,这也引发了之后要做一系列配置修改,具体内容在之后详细说明。

编译Boost.python

首先进入Boost源码的目录,执行其下的bootstrap.bat脚本。接着使用b2.exe对我们需要的库进行编译。注意, 由于之后要用到包含头文件的include目录,这里编译要使用Install模式而非通常教程中的Stage模式。由于我想使用的是annaconda下的python,需要额外写一个user-config.jam来指定python路径。user-config.jam的具体内容如下:

using python : 3.6
 : D:/Anaconda3/python.exe
 : D:/Anaconda3/include 
 : D:/Anaconda3/libs
 : <toolset>msvc ;

在本机所使用的编译命令如下:

b2 toolset=msvc-14.1 release debug runtime-link=shared link=static --build-type=complete --abbreviate-paths address-model=64 install -j4 --with-python --user-config=user-config.jam

结果是生成C:\Boost文件夹,其下有存有头文件的include文件夹以及存有库和cmake文件的lib文件夹。到此Boost.python算是安装编译完成了。

PBCVT (Python-Boost-OpenCV Converter)

使用CMake生成

在从github下载了pyboostcvconverte源码之后就要用CMake生成项目。我使用的是cmake-gui, 在本机的源代码地址为D:/pyboostcvconverter-master, 存放结果的目录为D:/pyboostcvconverter-master/build。点击Configure,不出意外报错了,错误说是无法找到Boost。为什么呢?我们来看一看CMakeList.txt里面是怎么去找Boost的。根据cmake的报错信息定位后可以发现CMakeList.txt里面有这么一句话:

find_package(Boost COMPONENTS python${PYTHON3_VERSION_MAJOR}${PYTHON3_VERSION_MINOR} QUIET)

cmake的find_package命令有两种模式,分别是Module和Config模式。前者是默认的查找模式,cmake已经为众多主流的库写了cmake查找脚本,在cmake安装目录下的/share/cmake-3.15/Modules可以找到它们。其中就有FindBoost.cmake,打开后找到如下说明:

If Boost was built using the boost-cmake project or from Boost 1.70.0 on
it provides a package configuration file for use with find_package’s config mode.

其解释了我们为何无法找到Boost库,从1.70.0版本起,需要使用find_package命令的config mode来找。具体又该如何写呢?我们可以从C:/Boost/lib/cmake/Boost-1.70.0/BoostConfig.cmake中找到答案。我们需要做的就是给出BoostConfig.cmake的路径,因此修改CMakeList.txt中查找Boost命令为:

find_package(Boost REQUIRED COMPONENTS python${PYTHON3_VERSION_MAJOR}${PYTHON3_VERSION_MINOR} PATHS C:/Boost/lib/cmake/Boost-1.70.0 QUIET)

下面附上我在本机CMake相关变量的赋值,各位按照各自电脑上的路径进行配置即可。
在这里插入图片描述
另外,在我这会报错说找不到boost_python36-config.cmake。对于这个问题来到C:/Boost/lib/cmake/boost_python-1.70.0/下直接修改相关文件名即可。
Configure成功之后按下Generate,cmake就完成了它的使命。

VS编译生成

在Generate之后点击Open Project在VS中打开。打开pbcvt的属性界面,配置项目的相关依赖路径。在VC++ Directories中添加Boost相关的路径;
在Include Directories添加

C:\Boost\include\boost-1_70

在Library Directories添加

C:\Boost\lib

在C/C++,General下的Additional Include Directories中添加如下路径:

D:\pyboostcvconverter-master\include
D:\anaconda3\include
D:\anaconda3\Lib\site-packages\numpy\core\include
D:\opencv\build\include
D:\opencv\build\include\opencv

选择Release模式,x64平台,设置完成后对Install进行Build。

Python调用

编译完成后找到pbcvt.cp36-win_amd64.pyd并将其放到python.exe所在目录下,运行python,输入如下测试代码:

D:\anaconda3>python
Python 3.6.5 |Anaconda, Inc.| (default, Mar 29 2018, 13:32:41) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy
>>> import pbcvt
>>> a = numpy.array([[1., 2., 3.]])
>>> b = numpy.array([[1.],
...                  [2.],
...                  [3.]])
>>> print(pbcvt.dot(a, b)) # should print [[14.]]
[[14.]]
>>> print(pbcvt.dot2(a, b)) # should also print [[14.]]
[[14.]]

运行成功!

编写自己的模块

回到VS中,打开pbcvt找到python_module.cpp,可以看到示例中dot和dot2定义,自己要写的话仿照这两个例子即可。

小结

通过以上方法可以实现NumPy ndarray与C++ cv::Mat的互相转换,但是貌似只是加入了cv::core模块的相关内容,其他模块的融入有待后续探究。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值