OpenCV-Python bindings是如何生成的(2)
OpenCV-Python bindings生成流程
通過上篇文章和opencv python模塊中的CMakeLists.txt文件,可以了解到opencv-python bindings生成的整個流程:
生成headers.txt文件
將每個模塊的頭文件添加到list中,通過一些關鍵詞過濾掉一些不需要擴展的頭文件,file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs}")將過濾后的list寫入文件;
headers.txt保存需要轉換的頭文件路徑,英文;隔開,注意文件末尾沒有換行符
生成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})通過調用gen2.py來實現的,第一個參數是生成頭文件后保存的路徑,第二個參數是headers.txt文件路徑
將cv2.cpp編譯成動態庫
OpenCV-Python bindings實踐操作
紙上得來終覺淺,絕知此事要躬行。整個事情的來龍去脈都已經講清楚,單到底怎么應用到自己的項目中呢。比如將自己圖像檢測功能實現完成,老大要求將它寫成Web服務,畢竟B/S模式非常流程。C++寫Web?開國際玩笑吧,現在python非常流行的天下。那么接下來看看怎么講c++功能函數類轉換成python的擴展庫吧。
網上查查資料,還真有相關的blog:
- How to convert your OpenCV C++ code into a Python module
- github code https://github.com/spmallick/learnopencv/tree/master/pymodule
博客寫的很好,但是提供的源碼千般嘗試始終報錯,于是乎決定自己從CMakeLists.txt看起,從gen2.py腳本看起,慢慢查實。
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 ./準備使用opencv-3.1.0源碼中的pycompat.hpp,cv2.cpp,gen2.py,hdr_parser.py文件,使用上面博客中的opencv c++源文件,慢慢來
gen2.py ./ headers.txt命令,第一步就報錯了IOError: [Errno 2] No such file or directory: 'src/bvmodule.hpp\n'
看到文件名后面居然有個換行符,哎,拿到windows下刪掉換行符。
去掉headers.txt中的換行符在去執行上面的命令,報出另外一個錯誤
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定制,應用需要改動腳本某些地方,通過不斷嘗試,幾經修改,終于大功告成。gen2.py ./ headers.txt命令在當前目錄下生成pyopencv_generated_funcs.h pyopencv_generated_include.h pyopencv_generated_ns_reg.h pyopencv_generated_type_reg.h pyopencv_generated_types.h文件。gen2.py修改如下
調整博客提供的編譯命令,編譯動態庫
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出錯
cv2.cpp:124: 錯誤:‘Stitcher’未聲明 cv2.cpp:124: 錯誤:expected initializer before ‘Status’ cv2.cpp:474: 錯誤:ISO C++ 不允許聲明無類型的‘Status’ cv2.cpp:474: 錯誤:expected ‘,’ or ‘...’ before ‘&’ token cv2.cpp:474: 錯誤:‘PyObject* pyopencv_from(int)’的模板標識符‘pyopencv_from<>’不匹配任何模板聲明 cv2.cpp:1257: 警告:‘int convert_to_char(PyObject*, char*, const char*)’定義后未使用類型未聲明,用不到的話就刪掉吧
再次執行編譯命令,期待的so動態庫在當前目錄生成了。那就試他一試吧,
這個錯誤的出現不得不促使我去了解一下C/C++為python做擴展的整個流程,Extending and Embedding the Python Interpreter,注意python2與python3是有差異的。
很容易發現,模塊需要一個對應初始化函數來初始化模塊,比如PyInit_bv,那么在opencv中這個初始化函數在哪定義的呢?直接點在當前目錄下執行grep -n --color=auto "cv2" -R *,在cv2.cpp中找到我們想要的函數了,接下來就是修改了
模塊的名稱是通過MODULESTR來定義的,python2以及python3中模塊初始化函數的聲明與定義。
再次編譯成功通過,測試OK
總結
以上是生活随笔為你收集整理的OpenCV-Python bindings是如何生成的(2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring配置讲解
- 下一篇: KDTree算法