相关文章推荐
开朗的路灯  ·  我国最美的“天路”其实在重庆巫山,10多公里 ...·  10 月前    · 
帅呆的黄瓜  ·  玉林龙潭产业园区:总投资24亿元,一批重大项 ...·  1 年前    · 
爱健身的打火机  ·  岚图汽车的2022:万事俱备,只差销量?_腾讯新闻·  1 年前    · 
刚毅的香蕉  ·  腾势D9 ...·  1 年前    · 
无聊的甜瓜  ·  看别人的18岁!小鲜肉是这样养成的 - 知乎·  1 年前    · 
Code  ›  [和小菜鸡一起玩OpenCV] Windows下NumPy ndarray与C++ cv::Mat的互相转换_numpy 转 cv::mat_海边的小菜鸡的博客
https://blog.csdn.net/weixin_42771166/article/details/95453064
微醺的红茶
1 年前
  • 前言
  • Boost库
    • 简介
    • 版本
    • 编译Boost.python
  • PBCVT (Python-Boost-OpenCV Converter)
    • 使用CMake生成
    • VS编译生成
    • Python调用
    • 编写自己的模块

    当我们想要从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模块的相关内容,其他模块的融入有待后续探究。

    目录前言Boost库简介版本编译Boost.pythonPBCVT (Python-Boost-OpenCV Converter)使用CMake生成VS编译生成Python调用编写自己的模块小结前言当我们想要从Python调用C++中的OpenCV方法时,通常需要将Python中的ndarray类型转换成C++中的cv::Mat。本文使用的方法是Boost.python + github上Al... class NDArrayConverter :转换器类 NDArrayConverter::NDArrayConverter() :构造函数 cv::Mat NDArrayConverter::toMat(const PyObject* o) :将NumPy ndarray转换为cv::Mat 。 o是表示ndarray的Python表示形式的对象。 返回cv::Mat ,它是o的OpenCV表示形式。 PyObject* NDArrayConverter::toNDArray(const cv::Mat& mat) :将cv::Mat转换为NumPy ndarray。 mat是要转换的cv :: Mat。 返回PyObject* ,它是ndarray的Python表示形式。 examples.cp Mat frame byte[] data = new byte[channels * width * height];//新建个byte二维数组 frame.get(0, 0, data);//获取mat数据到(byte)data NDArray nd1= new NDArray(data);//直接创建一个NDarray读取data NDArray nd = np.frombuffe
    最近在做项目需要调用C++中的OpenCV源码,必须要将numpy类型的数组传到C++中才行,在网上找了一大圈方法,特别是这个大佬的代码: https://github.com/Algomorph/pyboostcvconverter 刚开始用这位大佬的代码,得经过重重编译才能使用,起初一直编译不成功,要么就编译成功了调用失败,折腾了三天,终于成功调用它的实例代码了,但是当我想改C++代码中的函数来实现自己的需求时,又失败了,在反复折磨下,我放弃了。 后面自己还是慢慢摸索别的方法,终于!!!歪打正着让我
    PyObject *PyFunction::matToNdarray(Mat mat,int NPY_TYPE = NPY_FLOAT32)//Mat转Ndarray if (!mat.isContinuous()) { mat = mat.clone(); }//判断是否是连续的MAT,如果是ROI则不连续,需要将内存进行拷贝 vector<npy_intp> dims_vector; for (int i = 0;i < mat.dims;++i) { dims_vect
    Python OpenCV存储图像使用的是Numpy存储,所以可以将Numpy当做图像类型操作,操作之前还需进行类型转换,转换到int8类型 import cv2 import numpy as np # 使用numpy方式创建一个二维数组 img = np.ones((100,100)) # 转换成int8类型 img = np.int8(img) # 颜色空间转换,单通道转换成多通道, 可选...
    Numpy的函数入门:numpy.random.randint;numpy.squeeze;numpy数组转化为cv图片numpy的函数numpy.random.randint(low, high=None, size=None, dtype='l')numpy.squeeze()numpy数组转化为cv图片 numpy的函数 numpy.random.randint(low, high=Non...
    // 创建OpenCL内存对象 cl_mem cl_A = clCreateBuffer(context, CL_MEM_READ_ONLY, A.total() * A.elemSize(), NULL, &err); // 将cv::Mat A的数据复制到OpenCL内存对象中 err = clEnqueueWriteBuffer(command_queue, cl_A, CL_TRUE, , A.total() * A.elemSize(), A.data, , NULL, NULL); // 将OpenCL内存对象添加到OpenCL内核参数中 err = clSetKernelArg(kernel, , sizeof(cl_mem), (void *)&cl_A); // 执行OpenCL内核 err = clEnqueueNDRangeKernel(command_queue, kernel, 2, NULL, global_work_size, local_work_size, , NULL, NULL);
 
推荐文章
开朗的路灯  ·  我国最美的“天路”其实在重庆巫山,10多公里的山路成绝美仙境_神女
10 月前
帅呆的黄瓜  ·  玉林龙潭产业园区:总投资24亿元,一批重大项目开竣工 - 政务要闻 - 广西龙港新区玉林龙潭产业园区网站 - ltcyy.yulin.gov.cn
1 年前
爱健身的打火机  ·  岚图汽车的2022:万事俱备,只差销量?_腾讯新闻
1 年前
刚毅的香蕉  ·  腾势D9 DM-i新车型发布,纯电续航达98公里惊艳!
1 年前
无聊的甜瓜  ·  看别人的18岁!小鲜肉是这样养成的 - 知乎
1 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号