C++ 是一種編譯型(compiled)語言,設計重點是性能、效率和使用靈活性,偏向於系統編程、嵌入式、資源受限的軟件和系統。html
Python是一種解釋型(interpreted)語言,一樣也支持不一樣的編程範式。Python 內置了經常使用數據結構(str, tuple, list, dict),簡潔的語法、豐富的內置庫(os,sys,urllib,...)和三方庫(numpy, tf, torch ...),功能強大。最爲重要的是和可以和多種服務(flask…)和tensorflow、pytorch等無縫聯合,從而方便將你的算法開放出去。python
一方面,咱們須要編譯型語言(C++)性能;一方面,也須要解釋型語言(Python)的靈活。這時,pybind11 能夠用做 C++ 和 Python 之間溝通的橋樑。ios
Pybind11 是一個輕量級只包含頭文件的庫,用於 Python 和 C++ 之間接口轉換,能夠爲現有的 C++ 代碼建立 Python 接口綁定。Pybind11 經過 C++ 編譯時的自省來推斷類型信息,來最大程度地減小傳統拓展 Python 模塊時繁雜的樣板代碼, 已經實現了 STL 數據結構、智能指針、類、函數重載、實例方法等到Python的轉換,其中函數能夠接收和返回自定義數據類型的值、指針或引用。算法
因爲在Windows上和在Linux上使用會有較大不一樣,因此我這裏將分爲兩個部分來講明問題,本文爲上篇,具體說明Windows+VS實現編程
一、vs的最簡單調用flask
新建立項目,作如下修改:數組
這幾個都是標準配置【固然還有更簡便方法】,正常生成
#
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是什麼格式的文件:
1.PYD是一種PYTHON動態模塊。
2.實質上仍是dll文件,只是改了後綴爲PYD。
這裏特別須要注意,就是.pyd文件名和GOPyWarper這個函數名字必定要同樣,不然報數據結構
錯誤。app
二、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(src, gray, COLOR_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!";
});
}
三、圖片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;
}
四、融合實現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 庫