基於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 庫

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM