Fork me on GitHub

基于pybind11实现Python调用c++编写的CV算法--上(Windows+VS)

C++ 是一种编译型(compiled)语言,设计重点是性能、效率和使用灵活性,偏向于系统编程、嵌入式、资源受限的软件和系统。

Python是一种解释型(interpreted)语言,同样也支持不同的编程范式。Python 内置了常用数据结构(str, tuple, list, dict),简洁的语法、丰富的内置库(os,sys,urllib,...)和三方库(numpy, tf, torch ...),功能强大。最为重要的是和能够和多种服务(flask…)和tensorflow、pytorch等无缝联合,从而方便将你的算法开放出去。

一方面,我们需要编译型语言(C++)性能;一方面,也需要解释型语言(Python)的灵活。这时,pybind11 可以用作 C++ 和 Python 之间沟通的桥梁。

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

由于在Windows上和在Linux上使用会有较大不同,所以我这里将分为两个部分来说明问题,本文为上篇,具体说明Windows+VS实现

1、vs的最简单调用

新创建项目,做以下修改:

 

 
 
这几个都是标准配置【当然还有更简便方法】,正常生成
#include "pch.h"
#include <iostream>
#include <pybind11/pybind11.h>
namespace py = pybind11;
PYBIND11_MODULE(example, m) {
    m.doc() = "pybind11 example module";
    // Add bindings here
    m.def("foo", []() {
        return "Hello, World!";
    });
}
 
其中:
The PYBIND11_MODULE() macro creates a function that will be called when an import statement is issued from within Python. The module name (example) is given as the first macro argument (it should not be in quotes). The second argument (m) defines a variable of type py::module which is the main interface for creating bindings. The method module::def() generates binding code that exposes the add() function to Python.
 
生成结果中,只有pyd是需要的.

 

 

当你的python调用和pyd的文件在同一个目录下面就可以进行调用。
 

 

 

 

这里特别需要注意,就是.pyd文件名和GOPyWarper这个函数名字一定要一样,否则报

错误。

2、vs添加OpenCV的调用

配置中,需要添加OpeCV部分。分别是附加包含目录和附加依赖项。

 

 

PYBIND11_MODULE(example, m) {
 
    m.doc() = "pybind11 example module";
 
    // Add bindings here
    m.def("foo", []() {
        Mat src = imread("e:/template/lena.jpg");
        Mat gray;
        cvtColor(srcgrayCOLOR_BGR2GRAY);
        imshow("gray"gray);
        waitKey(0);//必须要设置,否则卡死
        return "Hello, OpenCV!";
    });
}
这种调用是没有问题的,关键的问题在于numpy数组和Mat的相互转换。只有这样,才能够将Mat和Python高质量融合。
 
// python调用C++.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <pybind11/pybind11.h>
using namespace cv;
using namespace std;
namespace py = pybind11;
PYBIND11_MODULE(example, m) {
    m.doc() = "pybind11 example module";
    // Add bindings here
    m.def("foo", [](string strPath) {
        Mat src = imread(strPath);
        Mat gray;
        cvtColor(src, gray, COLOR_BGR2GRAY);
        imshow("gray", gray);
        waitKey(0);//必须设置,否则卡死
        return "Hello, OpenCV!";
    });
}
 
3、图片Mat作为输入和list作为输出
对于实际项目而言来说,输入的是图片,输出的vector(numpy),这里就涉及到格式转换问题,目前找到解决方案。
src = cv2.imread('',1
var1 = GOPyWarper.test_rgb_to_gray(src)
cv2.imshow('gray',var1)
 
 
给出了3通道和1通道的numpy和Mat的转换,基本上是够用的,其它转换可以在内部进行。
然后在接口中有进一步封装,这个都是非常好理解的。
在输出这一块,有非常容易的方法,参考:这种方法虽然丑陋,但是有效。
py::list test_pyramid_image(py::array_t<unsigned char>& input) {
    py::list out;
    for (int i = 0; i < 100; i++)
    {
        out.append<py::int_>(i);
    }
    return out;
}
 
4、融合实现GOFindPip算法
输入图片,输出圆心数组(x、y排列),实现功能。
py::list GO_FindPips(py::array_t<unsigned char>& input) {
    //输出结果
    py::list out;
……
转换为release模式,能力有数量级的提升。
 
总的来看,在Windoes上的部署,由于VS提供了许多方便,所以比较流畅。
========================参考======

pybind11—HOG特征提取以及python接口封装

pybind11—目标跟踪demo(深度学习人脸检测跟踪)

pybind11—目标跟踪demo(KCF,python version)

pybind11—opencv图像处理(numpy数据交换)

pybind11—C++ STL

pybind11—函数,返回值,数据转换

pybind11—类(继承,重载,枚举)

pybind11使用

 

 pybind11—类,结构体

191123 使用 Pybind11 和 OpenCV 创建 Python 库

 

 

 

目前方向:图像处理,人工智能
posted @ 2020-04-29 18:58  jsxyhelu  阅读(1413)  评论(0编辑  收藏  举报