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上使用會有較大不同,所以我這里將分為兩個部分來說明問題,本文為下篇,具體說明Linux+Cmake實現。
我認為在Linux上使用python調用c++函數更有現實價值,畢竟許多新的服務、深度運算等都是運行在linux上的。具體步驟可以參考如下。
下載pybind11git clone https://github.com/pybind/pybind11.git
安裝pytestpip install pytest
編譯安裝。這個地方我建議你首先將下載下來的pybind11備份一份
cd pybind11
mkdir build
cd build
cmake ..
cmake
--
build .
--
config Release
--
target check
$ c
++
-
O3
-
Wall
-
shared
-
std
=
c
++
11
-
fPIC
`
python3
-
m pybind11
--
includes
`
example.cpp
-
o example
`
python3
-
config
--
extension
-
suffix
`
cmake_minimum_required(VERSION
2.
8.
12)
project(example)
add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)
cmake .
make
import example
example.add(
3,
4)
[out]
:
7
project(example)
cmake_minimum_required(VERSION 2.8.12)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)
target_link_libraries(example PRIVATE ${OpenCV_LIBS})
project(example)
cmake_minimum_required(VERSION
2.
8.
12)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_subdirectory(pybind11)
SET(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}
/example.cpp
)
pybind11_add_module(example ${SOURCES})
target_link_libraries(example
PRIVATE
${OpenCV_LIBS})
簡單分析一下這段Cmake,除了必須的項目名稱等以外,就是簡單地去尋找OpenCV等的地址,而后將lib輸入進去。
pybind11_add_module相當於建立項目,使用Set方法方便批量處理。
其中注意兩點:
1、target_link_libraries(example PRIVATE ${OpenCV_LIBS}) 放最后
2、xample PRIVATE 不可缺少,否則報這個錯
成功調用結果,
注意絕對地址。
project(example)
cmake_minimum_required(VERSION
2.
8.
12)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_subdirectory(pybind11)
SET(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}
/example.cpp
${CMAKE_CURRENT_SOURCE_DIR}
/mat_warper.h
${CMAKE_CURRENT_SOURCE_DIR}
/mat_warper.cpp
)
pybind11_add_module(example ${SOURCES})
target_link_libraries(example PRIVATE ${OpenCV_LIBS})


tar
-xvf GOPyWarper0429.tar
mkdir build
cd build
cmake ..
make
cp GOPyWarper.cpython
-
36m
-x86_64
-linux
-gnu.so ../demo
cd ../demo
python3 main.py
import cv2
import GOPyWarper
import numpy as np
#獲取圖片,彩色3通道。
#中文和空格不支持
src
= cv2.imread(
'pip.jpg',
1)
#GO_FindPips
#輸入mat,輸出為list(point1,point2,……),其中point代表一個找到的圓心。.
varCircles
= GOPyWarper.GO_FindPips(src)
#print(varCircles)
#GO_Resize
#輸入mat,輸出為規則化后文件大小
varResize
= GOPyWarper.GO_Resize(src)
#繪圖
dst
=cv2.resize(src,((
int)(varResize[
0]),(
int)(varResize[
1])),interpolation
=cv2.INTER_CUBIC)
for i
in varCircles[
:]
:
cv2.circle(dst,(i[
0],i[
1]),
5,(
0,
255,
0),
-
1)
cv2.imshow(
"dst",dst)
cv2.waitKey(
0)
helu@helu
-virtual
-machine
:
~
/sandbox$ tar
-cvf GOPyWarper0430.tar GOPyWarper0430
......
helu@helu
-virtual
-machine
:
~
/sandbox$ cd GOPyWarper0430
helu@helu
-virtual
-machine
:
~
/sandbox
/GOPyWarper0430$ mkdir build
helu@helu
-virtual
-machine
:
~
/sandbox
/GOPyWarper0430$ cd build
helu@helu
-virtual
-machine
:
~
/sandbox
/GOPyWarper0430
/build$ cmake ..
......
helu@helu
-virtual
-machine
:
~
/sandbox
/GOPyWarper0430
/build$ make
Scanning dependencies of target GOPyWarper
[
20
%] Building CXX object CMakeFiles
/GOPyWarper.dir
/src
/GOPyWarper.cpp.o
[
40
%] Building CXX object CMakeFiles
/GOPyWarper.dir
/src
/mat_warper.cpp.o
[
60
%] Building CXX object CMakeFiles
/GOPyWarper.dir
/src
/GOCVHelper_2019_11_29.cpp.o
[
80
%] Building CXX object CMakeFiles
/GOPyWarper.dir
/src
/GOFindPips.cpp.o
[
100
%] Linking CXX shared module GOPyWarper.cpython
-
36m
-x86_64
-linux
-gnu.so
[
100
%] Built target GOPyWarper
helu@helu
-virtual
-machine
:
~
/sandbox
/GOPyWarper0430
/build$
cp GOPyWarper.cpython
-
36m
-x86_64
-linux
-gnu.so ..
/demo
/
helu@helu
-virtual
-machine
:
~
/sandbox
/GOPyWarper0430
/build$ cd ..
/demo
/
helu@helu
-virtual
-machine
:
~
/sandbox
/GOPyWarper0430
/demo$ python3 main.py
helu@helu
-virtual
-machine
:
~
/workstation
/GOPyWarper0430$ cd build
/
helu@helu
-virtual
-machine
:
~
/workstation
/GOPyWarper0430
/build$ cmake ..
-- Found OpenCV
:
/usr
/local (found version
"4.3.0")
-- Found PythonInterp
:
/usr
/bin
/python3.
8 (found version
"3.8.2")
-- Found PythonLibs
:
/usr
/lib
/x86_64
-linux
-gnu
/libpython3.
8.so
-- pybind11 v2.
5.dev1
-- Performing Test HAS_FLTO
-- Performing Test HAS_FLTO
- Success
-- LTO enabled
-- Configuring
done
-- Generating
done
-- Build files have been written to
:
/home
/helu
/workstation
/GOPyWarper0430
/build
helu@helu
-virtual
-machine
:
~
/workstation
/GOPyWarper0430
/build$ make
Scanning dependencies of target GOPyWarper
[
20
%] Building CXX object CMakeFiles
/GOPyWarper.dir
/src
/GOPyWarper.cpp.o
[
40
%] Building CXX object CMakeFiles
/GOPyWarper.dir
/src
/mat_warper.cpp.o
[
60
%] Building CXX object CMakeFiles
/GOPyWarper.dir
/src
/GOCVHelper_2019_11_29.cpp.o
[
80
%] Building CXX object CMakeFiles
/GOPyWarper.dir
/src
/GOFindPips.cpp.o
[
100
%] Linking CXX shared module GOPyWarper.cpython
-
38
-x86_64
-linux
-gnu.so
[
100
%] Built target GOPyWarper
helu@helu
-virtual
-machine
:
~
/workstation
/GOPyWarper0430
/build$
GaussBlur | windows實體機 c++原生 | ubuntu虛擬機 opencv_python | ubuntu虛擬機 pbind11 |
1次 | 32 | 34 | 40 |
重復100次 | 2819 | 3740 | 3891 |
int main() {
string path
=
"e:/template/lena.jpg";
cv
:
:Mat src
= cv
:
:imread(path);
Mat dst;
//開始計時
double dstart
= (
double)cv
:
:getTickCount();
for (
int i
=
0;i
<
=
100;i
++)
{
cv
:
:GaussianBlur(src, dst, cv
:
:Size(
101,
101),
1.
0,
1.
0);
printf(
"%d times %f ms\n", i,
1000
* (getTickCount()
- dstart)
/ getTickFrequency());
}
cv
:
:waitKey(
0);
return
0;
}
import cv2
import GOPyWarper
import numpy as np
src
= cv2.imread(
'/home/helu/images/lena.jpg',
1)
dstart
= cv2.getTickCount()
for i
in
range(
100)
:
blur
= cv2.GaussianBlur(src,(
101,
101),
1.
0,
None,
1.
0,borderType
=
4)
print(
1000
* ( cv2.getTickCount()
- dstart)
/cv2.getTickFrequency())
import cv2
import GOPyWarper
import numpy as np
#獲取圖片,彩色3通道。
#中文和空格不支持
src
= cv2.imread(
'/home/helu/images/lena.jpg',
1)
dstart
= cv2.getTickCount()
for i
in
range(
100)
:
blur
= GOPyWarper.test_gaussblur(src)
print(
1000
* ( cv2.getTickCount()
- dstart)
/cv2.getTickFrequency())