使用pybind11生成C++的Python binding示例

27 篇文章 8 订阅
15 篇文章 0 订阅

前言

C++作为一种编译型语言,在其设计之初就偏重于性能、效率和灵活性,偏向应用于系统编程、嵌入式、资源受限的软件和系统。Python作为一种解释型语言,内置了如str, tuple, list, dict等常用数据结构,支持自动垃圾回收,拥有简洁的语法、丰富的内置库和第三方库,被越来越广泛地使用在各种场景中。但Python在高便捷性的同时无可避免的缺乏高性能。

在部分应用场景中,我们需要在Python的灵活性上架构应用,底层算法希望借助C++的高性能, 那么我们可以考虑将C++开发的模块做成Python的bindings供Python调用。

在这里插入图片描述

而pybind11则是C++和Python两种语言之间的一座桥梁。Pybind11是一个轻量级只包含头文件的库,用于C++和Python之间的接口转换,可以为C++代码创建Python bindings。Pybind11通过C++编译时的自省来推断类型信息,来最大程度地减少传统拓展 Python 模块时繁杂的样板代码, 已实现STL数据结构、智能指针、类、函数重载、实例方法等到Python的映射转换,其中函数可以接收和返回自定义数据类型的值、指针或引用。

步骤

以基于OpenCV和CUDA实现的GPU版本导向滤波算法为例,演示Pybind11的应用。

代码地址:https://github.com/TracelessLe/pybind11_guidedfilter_cuda

  1. 创建工程目录pybind11_guidedfilter_cuda和C++代码
    在这里插入图片描述
    其中核心代码guidedfilter.cppguidedfilter.h来自Github用户acstacey的项目“GLFCV - Light field disparity estimation using a guided filter cost volume”。

    部分代码一瞥:
    在这里插入图片描述
    guidedfilter.cpp前面加入下述代码

    #include <pybind11/pybind11.h>
    #include "ndarray_converter.h"
    namespace py = pybind11;
    

    在末尾加上下述代码:

    PYBIND11_MODULE(gfcuda, m)
    {
        NDArrayConverter::init_numpy();
    
        m.def("guidedFilter", &guidedFilter, "cv::cuda::guidedFilter", py::arg("guide"), py::arg("src"), py::arg("radius"), py::arg("eps"), py::arg("dDepth"));
    
    }
    

    目的是通过pybind11针对此cpp生成一个名为gfcuda的python binding,通过Python下的gfcuda.guidedFilter()的方法指向的C++函数"cv::cuda::guidedFilter"

  2. 拷贝Pybind11工程到工程目录pybind11_guidedfilter_cuda
    在这里插入图片描述
    Pybind11 CSDN资源链接:https://download.csdn.net/download/TracelessLe/13204469
    Pybind11 GitHub链接:https://github.com/pybind/pybind11
    将下载下来的包进行解压,解压后的pybind11文件夹拷贝到工程目录pybind11_guidedfilter_cuda下。

  3. 拷贝ndarray_converter.cppndarray_converter.h【此项目需要】
    由于涉及到numpy数组转换,拷贝相应.cpp和.h文件。
    其中ndarray_converter.cppndarray_converter.h来自Github用户mfedoseeva的项目“roboy-activity-recognition”。

  4. 编写CMakeLists.txt
    CMakeLists.txt是C++项目的编译链接设置文件,在本项目中,需要用到的外部依赖有OpenCV和CUDA,所以需要根据你自己的路径去设置。另外需要注意添加pybind11_add_module(gfcuda ${SOURCES})等用于生成binding的语句。总体设置如下:

    #Change this if you need to target a specific CMake version
    cmake_minimum_required(VERSION 2.8)
    
    # Enable C++11
    set(CMAKE_CXX_STANDARD 11)
    
    # Set up project
    project(guided_filter_cuda)
    add_subdirectory(pybind11)
    
    
    SET(SOURCES
      ${CMAKE_CURRENT_SOURCE_DIR}/guidedfilter.cpp
      ${CMAKE_CURRENT_SOURCE_DIR}/ndarray_converter.cpp
      ${CMAKE_CURRENT_SOURCE_DIR}/ndarray_converter.h
    )
    
    pybind11_add_module(gfcuda ${SOURCES})
    
    # Detect and add OpenCV
    set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}" ${CMAKE_MODULE_PATH})
    find_package(OpenCV REQUIRED HINTS /usr/local/share/opencv4)
    
    find_package(CUDA 10.2 REQUIRED)
    
    # Define sources and executable
    set(EXECUTABLE_NAME "gfcuda")
    
    # Link against OpenCV
    include_directories(${OpenCV_INCLUDE_DIR})
    target_link_libraries(${EXECUTABLE_NAME} PRIVATE ${OpenCV_LIBS})
    
    # Link against CUDA
    include_directories(${CUDA_INCLUDE_DIRS})
    target_link_libraries(${EXECUTABLE_NAME} PRIVATE ${CUDA_LIBRARIES})
    

    特别注意设置OpenCV和CUDA库的路径:

    target_link_libraries(${EXECUTABLE_NAME} PRIVATE ${OpenCV_LIBS})
    
    target_link_libraries(${EXECUTABLE_NAME} PRIVATE ${CUDA_LIBRARIES})
    
  5. 编译

    cmake .
    make
    

    编译完成后会生成一个600K左右的.so文件如“gfcuda.cpython-37m-x86_64-linux-gnu.so”,将这个.so文件拷贝到你的工程目录即可通过import gfcuda使用。
    在这里插入图片描述

  6. 在Python中使用

    import cv2
    import gfcuda
    
    img = cv2.imread('cat.png')
    guide = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    final_img = gfcuda.guidedFilter(guide=guide, src=img, radius=5, eps=50*50, dDepth=-1)
    cv2.imwrite('out.png', final_img)
    

    cat.png
    cat.png
    out.png
    out.png

    示例代码test_gfcuda.py已经提供在工程目录下。

特别说明

① 感谢Github用户acstacey,项目“GLFCV - Light field disparity estimation using a guided filter cost volume”提供代码guidedfilter.cppguidedfilter.h

②感谢Github用户mfedoseeva,项目“roboy-activity-recognition”提供代码ndarray_converter.cppndarray_converter.h

③关于更多Pybind11对C++和Python的数据类型映射关系可以参考文末【参考资料】一栏。

在这里插入图片描述

参考资料

[1] pybind11 docs “pybind11— Seamless operability between C++11 and Python”
[2] GitHub - acstacey / GLFCV - Light field disparity estimation using a guided filter cost volume
[3] GitHub - mfedoseeva / roboy-activity-recognition
[4] GitHub - atilimcetin / Guided filter for OpenCV
[5] 知乎 - python调用c++利器–pybind11
[6] 知乎 - pybind11: C++ 工程如何提供 Python 接口
[7] 知乎 - 191123 使用 Pybind11 和 OpenCV 创建 Python 库
[8] GitHub - How OpenCV-Python Bindings Works?
[9] Docs » 1. OpenCV简介 » 1.7. OpenCV Python绑定
[10] Python Bindings: Calling C or C++ From Python
[11] GitHub - TracelessLe / pybind11_guidedfilter_cuda
[12] 知乎 - pybind11的最佳实践
[13] cnblogs - 基于pybind11实现Python调用c++编写的CV算法–下 (Linux+Cmake)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TracelessLe

❀点个赞加个关注再走吧❀

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值