暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

OpenCV配置攻略(二): 安装包里都有什么(上)

麟十一 2021-09-08
1976

 第 25 篇  |  LINSHIYI 


这是“OpenCV配置攻略”的第二篇,主要来讲一讲OpenCV安装包中各个文件的内容。本文共分为4部分,第一部分简要介绍sources、build和opencv_contrib三个文件夹的内容和关系,并给出下载地址,第二部分解析sources源代码文件夹,第三部分分析build文件夹,最后一部分介绍opencv_contrib文件夹。

全文大约一万一千字,涉及开源许可证、EditorConfig、CMake、Travis CI、静态库动态库等多个概念。由于内容比较长,我将文章拆成了上下两篇,第一、第二部分,还有第三部分的前两小节在上篇,第三部分第三小节和第四部分在下篇。

不同版本的OpenCV安装包中内容可能略有不同,但是文件架构和核心文件都是相同的。本文以OpenCV3.4.10的安装包为例,并用OpenCV2.4.10作为补充,确保内容覆盖全面。

第一篇文在这里OpenCV配置攻略(一):OpenCV, VC++和VS,主要介绍了Visual Studio,Visual C++和OpenCV的概念,还有Visual Studio和OpenCV的安装教程,建议作为先导篇阅读


简介与下载

1.1 简介

本文一共涉及3个文件夹,sources、build和opencv_contrib,其中sourcesopencv_contrib属于OpenCV源代码文件夹,里面存放了算法的具体实现。build文件夹由sources编译而来,主要包含了头文件和算法预编译生成的库文件。官方未提供opencv_contrib编译生成的库文件,用户如果想要使用opencv_contrib中的算法,需要自行编译。

sources和opencv_contrib虽然都属于源代码,但是其中包含的算法是不同的。从OpenCV3.0.0开始,一些比较新的没有经过充分测试的算法模块会被放在opencv_contrib中作为额外模块单独发布,等到这些算法更加成熟的时候,再考虑移入OpenCV主仓库(即sources)中发布。

下图是opencv_contrib在GitHub页面中的简介(
https://github.com/opencv/opencv_contrib)


opencv_contrib简介


有关头文件、库文件的概念在后文都会介绍,这里只做一个概括性陈述。


1.2 下载


OpenCV官网GitHub中都可以下载安装包。官网地址: https://opencv.org/releases/,GitHub地址: https://github.com/opencv/opencv/releases


图1 官网下载页面



图2 GitHub下载选项


用户可根据自己的操作系统选择相应的安装包,例如在图1点击“Windows”选项,或者点击图2倒数第三个链接,都可以下载适用于Windows系统的、后缀为.exe的压缩包。这个压缩包解压后会是一个名为“opencv”的文件夹,里面包含build和sources两个子文件夹。

如果想要自己编译文件,可以在图1点击Sources”选项,或者点击图2倒数两个链接下载源代码压缩包,压缩包解压后就是sources文件夹。

opencv_contrib
的下载链接为https://github.com/opencv/opencv_contrib/releases下载时需要注意:opencv_contrib和OpenCV安装包的版本要相同

opencv_contrib下载页面


1.3 关系和结构


OpenCV3.4.10举例,三个文件夹的关系和内容结构如下图所示。绿色的是opencv_contrib文件夹sources同时存在于Windows安装包源代码压缩包中


OpenCV3.4.10文件结构示例


sources文件夹


2.1 LICENSE, README.md


LICENSE,README.md

README.md是一个文本文件,一般用来介绍算法或者给用户提供使用说明。这里的README.md列出了一些官方链接,例如OpenCV官网首页、问答社区、在线文档等。

LICENSE也是一个文本文件,存放的是OpenCV开源许可证。开源许可证(Open Source License)也被称为开源许可协议,它包括开源项目的版权声明、使用条件、免责声明等内容。官网(https://opensource.org/licenses)定义如下:


Open source licenses are licenses that comply with the Open Source Definition — in brief, they allow software to be freely used, modified, and shared.


申请了开源许可证的项目,相当于版权人允许其他人免费使用,修改和分享自己的代码或软件,而不会构成侵权。目前比较流行的开源许可证有以下几种:


比较流行的许可证(来自官网截图)


不同许可证的使用条件不同,比如Apache License 2.0要求用户在项目中保留原作者声明,对修改的部分提供说明文档,GPL-2.0要求用户将“修改源码后再发布的产品”也进行开源等。如果不知道选择哪种许可证,可以在这个网站中找找灵感(https://choosealicense.com/)

OpenCV的开源许可证为BSD 3-Clause License,也就是上图第二个许可证。它给予了使用者非常大的自由,只需要满足下列3条要求

BSD 3-Clause License 要求(来自官网截图)

简单理解:1.如果以源代码的形式进行产品再发布,需要保留BSD 3-Clause License;2.如果以二进制的形式(如库文件)进行产品再发布,需要在文档或其他材料中提供BSD 3-Clause License;3.在未获得书面许可的情况下,不能使用版权持有者(Copyright Holder)或项目贡献者(Contributors)的名字进行宣传或生产活动。

2.2 .editorconfig

.editorconfig

(1)概念

在团队项目中,开发人员编程习惯、使用的操作系统/编辑器的不同可能会导致项目代码风格不统一的问题:有的人习惯用2个空格作为缩进,有的人会用4个空格,还有的人喜欢直接按Tab键;Windows系统默认换行符为'\r\n',macOS默认'\r',Unix默认'\n'等等。

代码风格的不统一不仅会影响项目整体的
可读性和可维护性,还有可能使程序因符号冲突而无法正常运行。所以在多人开发的项目中,保持代码风格的统一是一件十分必要的事情。

EditorConfig LOGO


EditorConfig是一款可以在队开发中统一代码风格的工具。它的定义如下(https://editorconfig.org/):

EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs.


The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles.


EditorConfig由一个定义代码风格的文件格式(File Format)和一系列编辑器插件组成,名为.editorconfig的文件就是EditorConfig的文件格式,它是一个可以直接编辑的文本文件。


EditorConfig的使用方法非常简单,只有两步第一步创建一个名为.editorconfig的文件放在项目目录下,开发者可以设置一个或多个.editorconfig文件,也可以选择放在根目录或者需要定义其代码样式的文件同目录下。


第二步是使用编辑器编写代码。如果使用的是自带EditorConfig插件的编辑器,那么开发者就不需要再做什么了,EditorConfig插件会按照.editorconfig中定义的格式来自动调整代码格式;如果使用的不是自带插件的编译器,开发者需要手动安装插件,然后编写代码。


VS Code中的EditorConfig插件


VS Code属于非自带EditorConfig插件的编辑器,下面是自带插件的编辑器列表,具体的插件支持情况在官网中都可以找到(https://editorconfig.org/):


自动支持EditorConfig的编辑器


(2)配置和使用方法

假如我们想要统一项目中所有Python文件的代码风格,第一步可以在根目录下创建一个名为.editorconfig文件,并写入语句:


1# top-most EditorConfig file
2root = true
3#匹配后缀为.py的文件,设置编码格式和缩进风格
4[*.py]
5charset = utf-8
6indent_style = space
7indent_size = 4


先从第4行看起,[*.py]用来匹配Python文件,5-7行定义了Python文件的代码风格,包括字符集使用utf-8和以4个空格作为缩进

第2行root=true,理解这一句需要先了解编辑器中EditorConfig插件的查找顺序(https://editorconfig.org/):

When opening a file, EditorConfig plugins look for a file named .editorconfig in the directory of the opened file and in every parent directory. 


A search for .editorconfig files will stop if the root filepath is reached or an EditorConfig file with root=true is found.


EditorConfig插件会从正在编辑的文件目录开始,逐级向上查找名为.editorconfig的文件,直至到达根目录。如果想让插件提前停止查找,就需要在希望停止查找的目录下建立.editorconfig文件并写入root=true语句。

如果我们在项目中使用了多个.editorconfig来控制不同文件/代码的风格,那么root=true的使用就十分必要。而且EditorConfig是从上到下读取文件中的规则,并应用最新发现的规则,也就是说,离文件最近的规则会被优先应用

大多数情况下,
.editorconfig只有一份,被存放在根目录,控制所有文件/代码的格式。

(3)例子

我们可以在
VS Code中看一下EditorConfig具体怎么使用:

按照VS Code默认格式编写


我创建了一个名为test的文件夹,里面是一个Python文件test.py,和一个文件格式.editorconfig


首先按照VS Code默认代码风格写一段代码,可以发现编辑器默认缩进是4个空格(Spaces: 4),字符集是UTF-8,换行符是LF(Line Feed),即'\n'。换行符还有CR和CRLF两种,CR表示回车(Carriage Return),即'\r',CRLF是Windows下的默认换行符'\r\n'。


之后编辑.editorconfig,从小图标可以看出来这个文件其实是一个配置文件。由于文件夹里只有两个文件,这里就没有写root=true,直接设置缩进格式为1个Tab(制表位):


编辑.editorconfig


保存.editorconfig之后,返回test.py,继续写代码的时候会发现缩进格式已经变成了1个Tab(Tab Size: 1):


编写新代码


也就是说,保存.editorconfig之后进行的新操作,都会遵循.editorconfig中设置的格式,但是已有的代码格式并不会受影响(我现在还没找到让已有代码变成.editorconfig格式的方法),所以一般来说.editorconfig会在项目建立之初就设定好


2.3 CONTRIBUTING.md


CONTRIBUTING.md

CONTRIBUTING.md中的内容很简单,就是OpenCV贡献指南(Contributing Guidelines)的网址https://github.com/opencv/opencv/wiki/How_to_contribute

如果用户想要向OpenCV项目贡献自己的代码,例如修复已有bug、实现新算法等,就可以参考网址中的教程提交代码和相关说明。


2.4 CMakeLists.txt, cmake/


CMakeLists.txt, cmake/


这一小节是sources的重点,也是编译源代码需要的内容之一。不过在介绍最重要的CMake之前,还要先铺垫几个概念


(1) GNU

我们经常提到的“Linux操作系统”其实是误称,它应该叫
“GNU/Linux操作系统”。因为Linux仅是一个内核(Kernel),GNU才是操作系统(Operating System),他们之间的关系可以这样理解,操作系统是一系列程序的集合,内核是其中一个非常重要的程序(https://www.gnu.org/home.en.html):

The program in a Unix-like system that allocates machine resources and talks to the hardware is called the “kernel”. GNU is typically used with a kernel called Linux. This combination is the GNU/Linux operating system.


在20世纪80年代,包括Unix在内的几乎所有软件都是专有软件(或者叫闭源软件),为了开发出用户可以自由使用的开源软件,从1984年1月开始,Richard Stallman开始编写一套类Unix的操作系统,叫做GNU(GNU's Not Unix)。


GNU LOGO


到了1990年,Richard Stallman团队已经开发出了除内核以外的所有主要组件:编译器、编辑器、图形界面、应用库、游戏等等。由于GNU的内核Hurd迟迟没有开发出来,所以GNU先采用了由Linus Torvalds在1991年开发出的类Unix内核(也就是Linux)作为操作系统的内核,从1992年开始,GNU/Linux开始受到广泛关注。


GNU's own kernel, The Hurd, was started in 1990 (before Linux was started). Volunteers continue developing the Hurd because it is an interesting technical project.


随着时间的推移,Hurd也完成了研发,并作为GNU的内核进行发布。我在官网看到GNU最新推出的操作系统版本是Debian GNU/Hurd 2021,发布于今年(2021年)8月14日。

说完GNU的历史发展,回到定义上来
,GNU是一个带有自由软件(Free Software)的操作系统,这里的自由软件指的是用户可自由运行、拷贝、修改、改进的软件。我们常听到的Rgtk+GCCmake都属于GNU软件。更多软件详情见https://www.gnu.org/software/software.en.html

(2) GCC

第(1)节的内容是为了引出GCC和GNU make两个概念,先来简单介绍一下GCC(https://gcc.gnu.org/onlinedocs/gcc-11.2.0/gcc.pdf):


GCC stands for “GNU Compiler Collection”. GCC is an integrated distribution of compilers for several major programming languages. These languages currently include C, C++, Objective-C, Objective-C++, Fortran, Ada, D, Go, and BRIG (HSAIL).

GCC(GNU Compiler Collection)中文可以翻译为GNU编译套件,它在GNU/Linux下使用地较多,不过用户也可以在Windows、macOS等系统下安装GCC。想了解GCC在不同系统下的安装教程,可以参考这个链接https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html

GCC LOGO

GCC是编译套件,而gcc和g++是"GNU C Compiler"和"GNU C++ Compiler"的简称,这三者是不一样的概念。当我们编译C程序时,建议使用gcc命令,在编译C++程序时,建议使用g++命令,混用这两个命令可能会出现程序报错的情况。


现在来假设一个场景,假如我们需要在GNU/Linux下进行C++的开发,当项目中只有1个源文件(a.cpp)的时候,我们可以直接使用g++ -o main.exe a.cpp 命令对源文件进行编译,并生成名为main.exe的可执行程序。


当项目中有2个源文件(a.cpp, b.cpp)的时候,我们可以一次性编译两个源文件(见#1),也可以先分别编译两个文件,之后再将他们链接在一起(见#2。如果某个源文件链接了其他的库,那么相应的库文件路径也需要追加在命令行中(见#3):


1#1. 一个源文件
2g++ -o main.exe a.cpp b.cpp
3#2. 两个源文件
4g++ -c a.cpp
5g++ -c b.cpp
6g++ -o main.exe a.o b.o
7#3. 两个源文件,链接OpenCV库
8g++ -o main.exe a.cpp b.cpp `pkg-config --cflags --libs opencv-3-4-10`


现实中一个大的项目往往拥有十几个甚至几百个文件,并且会链接各种各样的C++标准库或第三方库,在这种情况下,手动编译所有文件显然不再合适,我们需要一个更加方便的工具,帮助我们实现自动化编译GNU make就是这样一款工具。


(3) GNU make和makefile

GNU make是GNU操作系统提供的一个自由软件,它也常常被简称为make,官网定义如下(https://www.gnu.org/software/make/):


GNU Make is a tool which controls the generation of executables and other non-source files of a program from the program's source files.

那么GNU make是如何实现自动化编译的呢?答案很简单,将所有需要运行的命令写入一个文档中,make从该文档中依次读取命令并执行即可,而这个包含了整个工程编译规则的文件,就叫做makefile(https://www.gnu.org/software/make/manual/make.html#Introduction)


To prepare to use make, you must write a file called the makefile that describes the relationships among files in your program and provides commands for updating each file. 


make和makefile的优点在于,用户即使不知道具体的编译流程,也可以构建整个项目;如果源文件有了更改,make会自动判断哪些文件需要更新,如果文件之间有依赖关系,make还会自动确定更新文件的正确顺序,也就是说,当文件有改动时,make不会重新编译所有程序,它只会更新部分有改动的文件;另外,make并不局限于特定的语言,也不局限于安装包的操作,它还可以生成其他语言的文件,实现卸载、删除包的操作。

虽说是自动化编译,但是这里的自动化仅仅代表用户拿到makefile之后可以使用make一键编译makefile还是需要开发者手动编写的。有关make、makefile的更多内容见官方手册(https://www.gnu.org/software/make/manual/make.html

(4) CMake和CMakeLists.txt

再假设一个场景,开发者在GNU/Linux下创建了一个开源项目,并写好了makefile,打包上传至GitHub。如果用户同样在GNU/Linux下进行开发,就可以在该平台下轻松构建整个项目。

但如果该用户习惯于在Windows下用Visual Studio做开发,就不再需要makefile,而需要该项目的项目解决方案(.sln)、工程文件(.vcxproj)等项目文件,如果用户在其他系统下做开发,又需要不同的makefile或工程文件,而这些不同文件,都需要开发者来提供。

如果有一种工具可以根据不同的系统和编译器,生成对应的makefile或工程文件,将会大大减少开发者的工作量,并增加项目的跨平台性。这样的工具并不少,比较常用的一种叫CMake(https://cmake.org/):

CMake is an open-source, cross-platform family of tools designed to build, test and package software. CMake is used to control the software compilation process using simple platform and compiler independent configuration files, and generate native makefiles and workspaces that can be used in the compiler environment of your choice.


CMake最大的优势就是跨平台编译,它可以根据用户本地的编译环境生成相应的makefile或者工程文件。举例来说,假如用户在GNU/Linux下用CMake编译项目,会生成makefile,之后用户可以使用make命令继续构建项目;假如用户在Windows下使用Visual Studio作为开发工具,CMake会生成项目解决方案和工程文件,之后用户可以用Visual Studio打开项目解决方案继续开发。


CMake LOGO

CMake生成不同makefile和工程文件的工具叫做生成器(Generator),在命令行中使用cmake --help命令可以查看在当前平台下可用的所有生成器,先在Ubuntu下尝试一下,结果如下图所示,可以发现第一个生成器就是用来生成UNIX makefiles的:

Ubuntu下生成器列表

我在
Windows系统上下载了cmake-gui,也就是CMake的图形用户界面工具,在这里也能看到该平台下的生成器列表:
Windows下生成器列表


和make一样,CMake也只是一个工具,它也需要一个文件来告诉它具体的构建步骤:例如生成哪种makefile或工程文件、下载哪些安装包等,这个文件就是CMakeLists.txt,也可以被称为CMake的配置文件。CMake通过读取CMakeLists.txt中的命令来执行具体的编译和安装步骤(https://cmake.org/overview/)

Simple configuration files placed in each source directory (called CMakeLists.txt files) are used to generate standard build files (e.g., makefiles on Unix and projects/workspaces in Windows MSVC) which are used in the usual way.


有了CMake之后,开发者虽然无需再手动编写makefile或者创建工程文件,但是需要编写CMakeLists.txt具体的介绍和编写规则见官方文档https://cmake.org/cmake/help/v3.21/

最后总结一下CMakeLists.txt和cmake文件夹的内容和作用,CMakeLists.txt保存了CMake需要执行的命令,包括检测系统和编译器类型、根据不同编译环境下载安装包、生成对应的makefile或工程文件等。CMakeLists.txt中会调用cmake文件夹下的文件来完成不同的任务,比如调用OpenCVGenHeaders.cmake生成头文件、调用OpenCVDownload.cmake下载包等。

2.5 其他文件夹

其他文件夹


3rdparty包含了一些第三方库,比如处理图像的libjpeg、libpng,处理视频的ffmpeg等,该文件夹下的readme.txt这样描述文件内容:

This folder contains libraries and headers of a few very popular still image codecs used by imgcodecs module.


apps中存放的是级联分类器的源代码和CMakeLists.txt文件。data包括了各种测试数据,Haar、HOG和LBP级联分类器的测试数据也在这里,大多数据都是XML格式。

doc文件夹包含了OpenCV的LOGO图片、算法示例图片、算法模块的介绍、Python和JavaScript示例代码、示例文档等内容。

include中包含了所有的头文件,一般来说该文件夹下都会有opencv和opencv2两个子文件夹,我们在写C++程序时使用的#include<opencv2/opencv.hpp>语句作用就是引用include/opencv2文件夹下的opencv.hpp头文件。有关头文件的内容在3.3中会有具体介绍。

platforms中是交叉编译需要的工具,交叉编译指的是在一个操作系统中引用另一个系统使用的文件,该文件夹下有iso、android、linux等文件夹(README.txt):

This folder contains toolchains and additional files that are needed for cross compilation.


modules文件夹保存了所有算法的源代码文件,samples包含了许多算法的示例代码。

build文件夹


3.1 其他文件


其他文件


LICENSE是OpenCV的开源许可证->BSD 3-Clause License,剩下三个文件都是CMake在编译过程中自动生成的配置文件(Configuration-based Files):


CMakeLists.txt(部分)


上图是sources文件夹根目录下的CMakeLists.txt(部分内容),上图是一段生成配置文件(Configuration-based Files)的代码。CMake先根据平台和项目配置生成了头文件,之后生成了各种配置文件:为类Unix系统(pkg-config command)生成opencv.pc,为安卓系统生成OpenCV.mk,为整个项目(不是仅在Windows系统下)生成OpenCVConfig.cmakeOpenCVConfig-version.cmake


OpenCVConfig.cmake定义了一些变量,例如OpenCV_VERSION(版本号)、OpenCV_INCLUDE_DIRS(头文件目录)等,OpenCVConfig-version.cmake中定义了OpenCV的版本信息


setup_vars_opencv3.cmd是为OpenCV设置变量的脚本文件,它还在文件夹下追加了Python路径。这几个文件都是使用源代码编译的时候自动生成的配置文件,一般不会用到。


运行setup_vars_opencv3.cmd


3.2 etc/, java/, python/


etc/, java/, python/


etc文件夹中包含了训练Haar和LBP分类器时使用的XML格式数据,还有一些算法的开源许可证、README等文件。


javapython文件夹中存放的是针对Java和Python开发者调用OpenCV时需要的库文件,这是python/cv2文件夹下的内容:


python/cv2下的文件


从上图可以看到,这里提供了5种不同版本的库文件和配置文件,开发者可以根据自己的Python版本调用合适的文件。


另外,在OpenCV2.x的build文件夹中,还有名为doc的文件夹,会存放一些LOGO图片,PDF格式的使用手册等文件。



上篇结束,下篇会介绍include/, bin/, lib/的内容和opencv_contrib文件夹中的内容,欢迎继续收看



~END~

文章转载自麟十一,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论