編寫基於OpenCV的圖像處理程序,其中很重要的一道門檻就是編譯OpenCV,應該說如果你對其中的內容如果不是很熟悉的話,即使是最簡單粗暴的“兩次configure,一次generate”都可能會出現各種錯誤;對於我來說,之前也是停留在能夠編譯、會解決一些問題階段,直到前一段時間我需要研究《基於pybind11實現Python調用c++編寫的CV算法--下(Linux+Cmake)》的過程中,
因為這個方面的資料非常難找,
沒有辦法必須對cmake有深入認識,才進行了系統研究。
這個時候,當我重新Cmake的時候,發現很多有趣的東西。這里一起來分享我的發現,相信對於大家理解這方面內容會有幫助。
一、基本情況
下載下來的源代碼解壓以后是這個樣子的
你會看到那個非常明顯的CMakeLists.txt。實際上,所有的Cmake文件都叫這個名字。打開以后,會發現里面沒什么東西:
其實這里都是各種各樣奇怪的宏,如果我們在opencv的文件夾下搜索"CMakeLists.txt",會發現有很多。
因為CmakeList都是級聯存在的。我們可以使用CMkae_gui直接打開根目錄,它會將這里級聯的內容解析出來。
那么所謂的
“兩次configure,一次generate”,就是這里的1、2、3、4,第一次Configure是讓cmake_gui把這里級聯的內容都出來,然后你打勾進行選擇,第二次Configure是把你選擇的東西寫進去,然后
generate,然后OpenProject直接打開IDE,可以編譯了,這個有經驗的都知道。
二、發現的奇怪東西
以前我也是無腦的直接編譯生成的,但是由於有了pybind的經驗,我就想看看OpenCV這個這么巨大的CmakeLists里面都是有些什么東西,一看就發現了一些奇怪的東西。
1、BUIILD_opencv_apps
一般意義上來說,都會理解apps是手機上的app,但是這個翻開來看以后是這樣的:
基本上可以確定是示例程序之類,我覺得應該可以去掉,肯定是和手機沒關系。
2、BUIILD_opencv_python3 和
BUIILD_opencv_python_bindings_generator 和
BUIILD_opencv_pythons_tests
這三個都是關於python的,我比較關心
python_bindings_generator
,我認為這個東西會不會和前一段時間研究的pybind11有關系?有重復,查詢相關資料,進一步明確。
Steps for building the Python module
We are now ready to go over the steps for building our Python module.
- Step 1: Put your c++ source code and header files inside the src directory.
- Step 2: Include your header file in headers.txt
- Step 3: Make a build directory.
Step 4: Use gen2.py to generate the Python binding files. You need to specify the prefix (pybv), the location of the temporary files (build) and the location of the header files (headers.txt).
1 python3 gen2.py pybv build headers.txt
This should generate a whole bunch of header files with prefix pybv_*.h. If you are curious, feel free to inspect the generated files.
- Step 5: Compile the module
1 g++ -shared -rdynamic -g -O3 -Wall -fPIC \
2 bv.cpp src/bvmodule.cpp \
3 -DMODULE_STR=bv -DMODULE_PREFIX=pybv \
4 -DNDEBUG -DPY_MAJOR_VERSION=3 \
5 `pkg-config --cflags --libs opencv` \
6 `python3-config --includes --ldflags` \
7 -I . -I/usr/local/lib/python3.5/dist-packages/numpy/core/include \
8 -o build/bv.so
In Line 2 we specify the source files. In Line 3, we set the module name using MODULE_STR and MODULE_PREFIX (pybv) used in the previous step. In Line 4 we specify the Python version. In Line 5 we include OpenCV library and the header files and in Line 6 we include Python 3 related header files and some standard libraries. In my machine, numpy was not in the included path and so I had to add an extra Line 7 for numpy. Your location for numpy may be different. Finally, in Line 8 we specify the location of the output module (build/bv.so).
可以證明,在python中的cv2的確是采用翻譯的方式,將其封裝為python代碼的的,這個也是完全沒有問題的,如果是我來設計肯定也是這樣。但是,這里OpenCV是站在代碼庫的立場上面,逐條翻譯;而對於應用來說,采用打包翻譯(三明治方法)效果更好,因此這里我認為
BUIILD_opencv_python_bindings_generator的方法過於繁瑣,相比較而言pybind11的方法更方便部署。
3、thunder
thunder不是迅雷嗎?難道OpenCV和它還有關系。懷着探究心態,不斷挖掘,發現原來是這個東西:
很有可能進一步使這個東西
因為我給OpenCV投過代碼,我知道它的代碼審核、自動生成等是比較嚴格的。
三、我篩選的OpenCV_Cmake
我記得上學的時候,老師經常會說“可以對Linux進行裁剪”,感覺這個是很高大上的一件事情,但是當然是不知道如何“
裁剪”。實際上,OpenCV作為老牌開源項目,它這里這么多的BUILD選項,就是給你一個
“
裁剪”的接口。你可以根據需要進行選擇。
對於我來說,我最近一次編譯Cmake是在寫
《
構建自己的專用OpenCV----一個由applyColorMap()引發的探索(上)》的時候發生的,因為我需要修改OpenCV的代碼,實現一個它自己沒有的
applyColorMap色彩,所以需要編譯OpenCV。
由於我知道
applyColorMap屬於imgproc,是比較基礎的庫,因此這里很多東西都沒必要選擇。這個時候,我對OpenCV的
“
裁剪”是這樣的
其中,我勇敢地去掉了
BUILD_EXAMPLES、BUILD_opencv_dnn、BUILD_opencv_gapi、BUILD_opencv_java_*、BUILD_opencv_python_*、BUILD_opencv_video*等這些我很明確用不着的東西,對於BUILD_opencv_apps之類搞不清楚的東西進行了保留,特別是添加了BUILD_opencv_world,這樣可以生成一個dll,免得添加麻煩。
最后的結果是29個項目,可能還能夠再去掉一些,但是沒有繼續嘗試,這樣的話每次編譯,速度都比較快。
四、參考資料