OpenCV-Python bindings是如何生成的(2)
OpenCV-Python bindings生成流程
通過上篇文章和opencv python模塊中的CMakeLists.txt文件,可以了解到opencv-python bindings生成的整個(gè)流程:
生成headers.txt文件
將每個(gè)模塊的頭文件添加到list中,通過一些關(guān)鍵詞過濾掉一些不需要擴(kuò)展的頭文件,file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs}")將過濾后的list寫入文件;
headers.txt保存需要轉(zhuǎn)換的頭文件路徑,英文;隔開,注意文件末尾沒有換行符
生成cv2.cpp中需要的頭文件
set(cv2_generated_hdrs"${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_include.h""${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_funcs.h""${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_types.h""${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_type_reg.h""${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_ns_reg.h")file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs}") add_custom_command(OUTPUT ${cv2_generated_hdrs}COMMAND ${PYTHON_EXECUTABLE} "${PYTHON_SOURCE_DIR}/src2/gen2.py" ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/headers.txt"DEPENDS ${PYTHON_SOURCE_DIR}/src2/gen2.pyDEPENDS ${PYTHON_SOURCE_DIR}/src2/hdr_parser.pyDEPENDS ${CMAKE_CURRENT_BINARY_DIR}/headers.txtDEPENDS ${opencv_hdrs})通過調(diào)用gen2.py來實(shí)現(xiàn)的,第一個(gè)參數(shù)是生成頭文件后保存的路徑,第二個(gè)參數(shù)是headers.txt文件路徑
將cv2.cpp編譯成動(dòng)態(tài)庫(kù)
OpenCV-Python bindings實(shí)踐操作
紙上得來終覺淺,絕知此事要躬行。整個(gè)事情的來龍去脈都已經(jīng)講清楚,單到底怎么應(yīng)用到自己的項(xiàng)目中呢。比如將自己圖像檢測(cè)功能實(shí)現(xiàn)完成,老大要求將它寫成Web服務(wù),畢竟B/S模式非常流程。C++寫Web?開國(guó)際玩笑吧,現(xiàn)在python非常流行的天下。那么接下來看看怎么講c++功能函數(shù)類轉(zhuǎn)換成python的擴(kuò)展庫(kù)吧。
網(wǎng)上查查資料,還真有相關(guān)的blog:
- How to convert your OpenCV C++ code into a Python module
- github code https://github.com/spmallick/learnopencv/tree/master/pymodule
博客寫的很好,但是提供的源碼千般嘗試始終報(bào)錯(cuò),于是乎決定自己從CMakeLists.txt看起,從gen2.py腳本看起,慢慢查實(shí)。
mkdir ovex cd ovex mkdir src cp ../opencv-3.1.0/modules/python/src2/{pycompat.hpp,cv2.cpp,gen2.py,hdr_parser.py} ./ cp ../learnopencv-master/pymodule/src/* src/ cp ../learnopencv-master/pymodule/headers.txt ./準(zhǔn)備使用opencv-3.1.0源碼中的pycompat.hpp,cv2.cpp,gen2.py,hdr_parser.py文件,使用上面博客中的opencv c++源文件,慢慢來
gen2.py ./ headers.txt命令,第一步就報(bào)錯(cuò)了IOError: [Errno 2] No such file or directory: 'src/bvmodule.hpp\n'
看到文件名后面居然有個(gè)換行符,哎,拿到windows下刪掉換行符。
去掉headers.txt中的換行符在去執(zhí)行上面的命令,報(bào)出另外一個(gè)錯(cuò)誤
Traceback (most recent call last):File "./gen2.py", line 943, in <module>generator.gen(srcfiles, dstdir)File "./gen2.py", line 855, in genself.code_include.write( '#include "{0}"\n'.format(hdr[hdr.rindex('opencv2/'):]) ) ValueError: substring not foundhdr.rindex('opencv2/')取頭文件中opencv/的位置,hdr[hdr.rindex('opencv2/'):])取頭文件中opencv/之后的所有字符串。看樣子腳本是opencv定制,應(yīng)用需要改動(dòng)腳本某些地方,通過不斷嘗試,幾經(jīng)修改,終于大功告成。gen2.py ./ headers.txt命令在當(dāng)前目錄下生成pyopencv_generated_funcs.h pyopencv_generated_include.h pyopencv_generated_ns_reg.h pyopencv_generated_type_reg.h pyopencv_generated_types.h文件。gen2.py修改如下
調(diào)整博客提供的編譯命令,編譯動(dòng)態(tài)庫(kù)
g++ -shared -rdynamic -g -O3 -Wall -fPIC \ -I . -I../ -I/usr/local/python2.7.14/lib/python2.7/site-packages/numpy/core/include \ cv2.cpp src/bvmodule.cpp \ -DNDEBUG \ `PKG_CONFIG_PATH=/usr/local/opencv_with_contrib3.1.0/lib/pkgconfig pkg-config --cflags --libs opencv` \ `/usr/local/python2.7.14/bin/python2.7-config --includes --ldflags` \ -L`/usr/local/python2.7.14/bin/python2.7-config --exec-prefix`/lib \ -o bv.so出錯(cuò)
cv2.cpp:124: 錯(cuò)誤:‘Stitcher’未聲明 cv2.cpp:124: 錯(cuò)誤:expected initializer before ‘Status’ cv2.cpp:474: 錯(cuò)誤:ISO C++ 不允許聲明無類型的‘Status’ cv2.cpp:474: 錯(cuò)誤:expected ‘,’ or ‘...’ before ‘&’ token cv2.cpp:474: 錯(cuò)誤:‘PyObject* pyopencv_from(int)’的模板標(biāo)識(shí)符‘pyopencv_from<>’不匹配任何模板聲明 cv2.cpp:1257: 警告:‘int convert_to_char(PyObject*, char*, const char*)’定義后未使用類型未聲明,用不到的話就刪掉吧
再次執(zhí)行編譯命令,期待的so動(dòng)態(tài)庫(kù)在當(dāng)前目錄生成了。那就試他一試吧,
這個(gè)錯(cuò)誤的出現(xiàn)不得不促使我去了解一下C/C++為python做擴(kuò)展的整個(gè)流程,Extending and Embedding the Python Interpreter,注意python2與python3是有差異的。
很容易發(fā)現(xiàn),模塊需要一個(gè)對(duì)應(yīng)初始化函數(shù)來初始化模塊,比如PyInit_bv,那么在opencv中這個(gè)初始化函數(shù)在哪定義的呢?直接點(diǎn)在當(dāng)前目錄下執(zhí)行g(shù)rep -n --color=auto "cv2" -R *,在cv2.cpp中找到我們想要的函數(shù)了,接下來就是修改了
模塊的名稱是通過MODULESTR來定義的,python2以及python3中模塊初始化函數(shù)的聲明與定義。
再次編譯成功通過,測(cè)試OK
總結(jié)
以上是生活随笔為你收集整理的OpenCV-Python bindings是如何生成的(2)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring配置讲解
- 下一篇: CentOS下升级python版本