编写基于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.
1
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
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个项目,可能还能够再去掉一些,但是没有继续尝试,这样的话每次编译,速度都比较快。
四、参考资料
1、《How to convert your OpenCV C++ code into a Python module》
https://www.learnopencv.com/how-to-convert-your-opencv-c-code-into-a-python-module/
2、《OpenCV-Python bindings是如何生成的》