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

Ubuntu下安装OpenCV(三): CMake编译(下)

麟十一 2021-11-08
1316

 第 26 篇  |  LINSHIYI 



这是Ubuntu下安装OpenCV系列的第三篇:CMake编译(下)。本文以OpenCV3.4.10Ubuntu18.04为例,使用Debug模式对OpenCV核心算法和额外算法进行CMake编译,并生成适用于Unix/Linux系统的Makefile等编译文件。


CMake编译这一步有2篇文,共3个部分。第一部分介绍CMake命令行中的各个参数;第二部分分析某些文件/压缩包下载失败的原因,并给出多种解决方法;第三部分展示编译结果


这是CMake编译的下篇,包含第二部分的(3)-(4)小节和第三部分的内容。


目录--2.CMake编译


上图是这个系列的目录索引,之前的文章都在这里:

 OpenCV配置攻略(一):OpenCV, VC++和VS
 OpenCV配置攻略(二): 安装包里都有什么(上) 本文主要介绍CMake编译这一步,推荐提前阅读2.4节(3)-(4)中有关CMake和make的部分
 OpenCV配置攻略(二): 安装包里都有什么(下) 
 Ubuntu下安装OpenCV(一): 准备工作 
 Ubuntu下安装OpenCV(二): CMake编译(上) 


CMake编译(接上篇)



4.2 有关下载失败的问题


(3)手动下载文件的两种方法


下面提供两种方法来手动下载这4种文件/压缩包,第一种是根据下载日志中记录的下载链接进行下载,第二种是从GitHub上OpenCV提供的第三方库(3rdparty)仓库中进行下载。


2种手动下载的方法


方法1:日志链接下载

 

第一种方法的下载网址在上一篇文中我们已经见过了,就是下载日志CMakeDownloadLog.txt中的参数"${DL_URL}" :


ippicv下载日志中的"${DL_URL}"


这个参数在#do_${mode}语句和#cmake_download语句中都存在,用户选择哪一个都可以。


vgg_generated_64.i下日志中的"${DL_URL}"


打开CMakeDownloadLog.txt,找到下载失败的文件/压缩包对应的日志语句,将下载链接复制到浏览器中就可以进行手动下载了。


不过,这种方法有一个缺点,那就是无法批量下载。对于vgg_*.i和boostdesc_*.i这一系列文件来说,用户只能将这些文件的链接挨个复制到浏览器中进行下载,操作会比较麻烦。


方法2:GitHub仓库下载

 

第二种方法刚好可以解决这个问题。在Github上的opencv/opencv_3rdparty仓库(https://github.com/opencv/opencv_3rdparty)中,包含了OpenCV第三方库所需的各种文件,例如ippicv压缩包、vgg_*.i系列文件、dnn目标探测模型、opencv_ffmpeg.dll等等,大部分下载失败的文件都可以在这里找到:


opencv/opencv_3rdparty


用户只要选择需要的分支,就可以下载对应的第三方文件了。


vgg_*.i系列文件的分支叫做contrib_xfeatures2d_vgg_20160317,用户也可以通过输入下面的链接进入该分支https://github.com/opencv/opencv_3rdparty/tree/contrib_xfeatures2d_vgg_20160317


contrib_xfeatures2d_vgg_20160317


从上图可以看到,vgg_*.i系列共有4个文件,我们可以直接把整个压缩包下载下来

 

boostdesc_*.i的分支叫做contrib_xfeatures2d_boostdesc_20161012,共有7文件,分支链接https://github.com/opencv/opencv_3rdparty/tree/contrib_xfeatures2d_boostdesc_20161012


contrib_xfeatures2d_boostdesc_20161012


face_landmark_model.dat数据集在contrib_face_alignment_20170818分支下,链接为 https://github.com/opencv/opencv_3rdparty/tree/contrib_face_alignment_20170818


contrib_face_alignment_20170818


第二种方法的好处在于可以打包下载文件但是,使用这种方法下载ippicv压缩包会比较麻烦

由于CMake在下载ippicv压缩包时会根据不同的操作系统自动选择不同日期、不同版本的压缩包,所以我们在下载ippicv之前需要先查看下载日志CMakeDownloadLog.txt,在#do_unpack语句中找到正确的压缩包名称
 

查看适用于系统的ippicv压缩包名称


从上图可以看到,适用于我的系统的ippicv压缩包名为ippicv_2020_lnx_intel64_20191018_general.tgz 


确定了名称,我们可以前往opencv/opencv_3rdparty的分支中进行查找,先选择正确日期的分支,即ippicv/master_20191018


选择正确的ippicv分支


进入分支后,点击"ippicv",进入文件夹下


进入ippicv文件夹下


在ippicv文件夹下我们可以看到针对不同系统的压缩包,如macOS、Windows、Linux等。我们需要根据日志中的文件名称,选择正确的压缩包,我选择的是第二个压缩包,点击该文件


选择正确的压缩包进行下载


最后点击"Download"就可以进行下载了:

 

点击Download进行下载


如果嫌刚才的操作太麻烦的话,我们也可以ippicv/master_20191018分支中的文件全部打包下载,之后再从中挑出合适的ippicv压缩包。


这4类文件除了face_landmark数据集稍大一些,其余的体积都不大,很快就可以下载完成:


下载中


不过使用这种方法也有一个缺点,就是有时我们可能打不开GitHub。对于这个问题,我一般采取的措施就是过一会儿再试,或者翻个墙试试,总之只要能打开GitHub网站,这些包就都可以成功下载。

 

刚刚提到的两种方法本质上是相同的,用户可以根据自己的需要选择合适的方法,比如使用第一种方法下载压缩包使用第二种方法下载vgg_*.i系列文件等。

 

(4) 解决问题的3种办法


3种办法


在手动下载完成之后,我们还需要将文件/压缩包放置在正确的文件夹下。根据第(2)小节中介绍过的CMake下载逻辑,我整理了3种方法。

 

第一种方法

第一种方法的中心思想是将网络下载替换为本地下载。我们需要将文件的下载网址修改为刚刚下载好的文件的本地地址


下面以ippicv压缩包vgg_generated_48.i为例,解释具体的操作步骤:

 

1. 存放手动下载完成的文件

 

我在源代码文件夹下新建了一个文件夹download_data,用来存放我手动下载的文件,下图中我将ippicv压缩包和vgg_*.i系列文件都放在了该文件夹下。


存放下载文件

对于是否创建文件夹、文件夹创建的位置都没有具体要求,我在这里将下载文件都存放在一处是为了方便查找。


2. 找到负责执行下载任务的文件

 

负责执行下载任务的文件大多数以.cmake作为后缀,CMake在编译时会通过读取这些文件中的内容来执行下载任务:


负责下载的文件


上图中<opencv_sources>指的是核心算法文件夹路径,<opencv_contrib>指的是额外算法文件夹路径。如果用户下载失败的包不是这4类文件中的一个,那么就需要检查CMake编译时输出的警告信息来寻找负责下载的文件:


从警告信息中查找负责下载的文件

 

3. 修改文件内容

 

下面来修改文件内容,更具体地说是修改文件中的下载链接,先看ippicv.cmake,URL变量后面以https开头的网址就是ippicv压缩包的下载链接:


ippicv下载链接


接下来将该链接修改为我们手动下载的ippicv压缩包路径。输入命令sudo gedit <file name>编辑文件,我将下载链接替换成了file:/home/用户名/downloads/opencv-3.4.10/download_data/


这里有三个需要注意的点,第一是双引号必须保留,第二是路径前需要加上file:来代表文件协议,第三是路径需要写入绝对路径且不能出现中文


根据文件所在路径替换掉下载链接


使用同样的方法修改download_vgg.cmake

 

根据文件所在路径替换掉下载链接


多说一句,上面两张图中负责下载的函数叫ocv_download(),这个函数我们之前见过,它在OpenCVDownload.cmake(也就是我们画逻辑图的那个文件)中被定义:


ocv_download()


4. CMake编译

 

修改完两个文件之后,我们执行CMake编译,就会发现ippicv压缩包和vgg_*.i系列的文件都已经成功“下载”了。


方法1--逻辑图


这是第一种方法的逻辑图,“是否存在下载目录”中是和否都是紫色,旨在说明.cache/文件是否存在都不影响结果。被水印遮住的文字是“新建目录并解压缩”。下面根据具体的下载日志来解释第一种方法的下载逻辑


方法1--ippicv下载日志


先来看ippicv压缩包的下载日志,绿线标出的参数 "${DL_URL}"已经从https开头的链接变成了我们写入的本地文件路径。下载日志的内容也发生了变化:

 

第二行#do_unpack说明执行的是压缩包任务-->程序检查下载目录下是否存该压缩包-->不存在-->下载压缩包(#cmake_download,#try)-->由于下载网址就是本地文件路径,网络下载关闭(#Closing connection)-->本地文件“下载”成功-->对压缩包进行HASH值校验(#check_md5)-->校验正确-->检查目标目录下是否已存在该文件/压缩包-->不存在-->新建文件夹(#mkdir)-->将压缩包解压至新建文件夹下(#unpack)

 

再来看vgg_generated_48.i文件的日志,参数"${DL_URL}"同样变成了我们设置的文件路径。下载日志内容变为:#do_copy代表执行文件下载任务-->程序先在目标目录下查找文件-->未找到(#missing)-->在下载目录下查找文件-->未找到-->下载文件(#cmake_download,#try)-->非网络下载(#Closing connection)-->本地文件“下载”成功-->校验HASH签名(#check_md5)-->签名正确-->将该文件复制在目标目录下(#copy)。 


方法1--vgg_generated_48.i下载日志


使用这种方法需要注意路径千万不要写错,少了分隔符、忘记写file:、或者路径拼写错误都会造成CMake找不到该文件,而且在不同系统下,文件协议的写法也有所不同,比如在Windows下需要写file:///而不是file:。


第二种方法

 

第二种方法的中心思想是将下载好的文件更换文件名后,放在下载目录下,让CMake在检查下载目录时可以找到正确的文件,从而跳过下载这一步


4种文件在下载目录下的路径


上表是4种文件在下载目录下的路径,<opencv_source>指核心算法源代码目录的路径。下面以ippicv压缩包face_landmark数据集为例介绍具体步骤:

 

1. 执行CMake编译

 

在下载目录下,所有文件名称都会带着MD5 HASH前缀,所以我们需要给之前手动下载的文件也添加相应前缀。那么如何知道各文件正确的MD5 HASH值呢?最简单的办法就是让CMake先生成一个名称中带有MD5 HASH值的预下载文件,然后我们直接复制文件名即可

 

所以第二种方法需要先执行CMake编译,待程序执行到下载文件这一步的时候,使用Ctrl+C键停止编译并打开下载目录,我们就能看到带有MD5 HASH前缀的预下载文件了。

 

2. 替换预下载文件

 

停止CMake编译之后,我们进入具体的下载目录下使用预下载文件的名称来命名我们下载好的文件,顺便替换掉预下载文件


替换预下载文件--ippicv压缩包


上图是ippicv压缩包的操作过程,先用cp命令将之前手动下载的压缩包复制到.cache/ippicv文件夹下,通过文件名对比可以发现,我们下载的压缩包是不带MD5 HASH值的。之后使用mv命令给我们的压缩包重命名,并覆盖掉原先的压缩包。不习惯用命令行的话也可以直接在文件夹内进行复制粘贴和替换操作

 

cp <源文件目录> <目标文件目录>是将源文件复制到目标目录下的命令,上图命令中我用一个英文句号"."代表当前目录,也就是.cache/ippicv文件夹

 

mv命令可以用来移动文件,也可以给文件重命名。我这里使用的是mv <源文件名> <目标文件名>语句来给源文件重命名。由于重命名后的文件与原先的预下载文件具有相同的名称,所以会覆盖掉原先的文件。

 

face_landmark数据集执行同样的操作,这个文件的下载目录是.cache/data:


替换预下载文件--face数据


另外,由于Linux有自动补全的功能,用户在输入命令的时候不需要一个一个敲入字母。比如上图sudo mv命令的最后一个参数,我们只需要敲下750或者只敲一个数字7,接着按下Tab键,完整的文件名就会被自动补全了。

 

3. 继续执行CMake编译

 

替换好文件之后,返回构建文件夹中继续执行CMake编译即可。第二种方法的逻辑线如下图所示:


方法2--逻辑图


被水印遮住的字为“新建目录并解压缩”。接下来通过解读下载日志来解释第二种方法的下载逻辑

 

方法2--ippicv下载日志


先是ippicv压缩包#do_unpack代表压缩包任务-->程序检查下载目录-->发现存在相应文件-->文件签名校验(#check_md5)-->签名正确-->检查目标目录下是否存在相应文件-->不存在-->新建文件夹(#mkdir)-->压缩包解压(#unpack)


方法2--face数据


对于face_landmark_model.dat文件来说,#do_copy代表文件任务-->程序先检查目标目录下是否已经存在该文件-->未发现文件(#missing)-->检查下载目录下是否存在该文件-->存在文件-->校验签名(#check_md5)-->签名正确-->将该文件复制到目标目录下(#copy)

 

总体来说,这个方法不麻烦但也不简单,我们需要先进行CMake编译来获取下载目录中带有MD5 HASH值的文件名,之后给我们下载好的文件重命名,替换掉下载目录下的原文件并继续编译


对于单个文件来说修改文件名不难,但是对于vgg_*.i和boost_*.i这一系列文件来说,一个一个修改文件名会比较麻烦。


第三种方法

 

第三种方法只适用于文件,对压缩包不适用。中心思想是直接将文件放在目标目录下,让CMake在检查目标目录时就可以找到正确的文件,然后跳过后面所有的步骤。个人认为这种方法最适合vgg_*.i和boost_*.i系列文件,所以下文以这两类文件举例。

 

1. 找到目标目录


4种文件的目标目录


这是4种文件的目标目录,都在构建文件夹<build_directory>下。虽然此方法不适用于压缩包,但是我在这里还是标注了一下ippicv压缩包解压后所在的目录,方便读者查看。

 

当我们没有使用CMake编译时,一些文件夹如xfeatures2d、testdata等还没有生成,我们可以自己创建,当然也可以先进行CMake编译,等到大部分文件都生成之后,暂停编译,再进入目标目录下。

 

先进行CMake编译的好处在于我们可以通过查看下载日志CMakeDownloadLog.txt来确定文件/压缩包的目标目录,如果我们有其他文件下载失败了,下载日志可以告诉我们该文件的目标目录和下载目录的具体位置

 

2. 复制文件至目标目录下

 

我是从GitHub上直接打包下载的vgg_*.i和boostdesc_*.i系列文件,所以下载下来是两个压缩包,名字分别为opencv_3rdparty-contrib_xfeatures2d_boostdesc_20161012.zipopencv_3rdparty-contrib_xfeatures2d_vgg_20160317.zip

 

接下来使用sudo unzip <file name>命令将这两个压缩包解压在目标目录下:


解压两个压缩包


解压之后是两个文件夹,我们可以发现在目标目录下已经存在了一个叫boostdesc_bgm.i的文件,这是因为我之前进行过一次CMake编译,在CMake下载过程中成功地下载了这个文件,但是其他文件都下载失败,所以目标目录下只存在这一个下载成功的文件。

 

接下来分别进入这两个文件夹下,将vgg_*.i和boostdesc_*.i系列的文件都移动到父目录,也就是目标目录中去


将文件移动至目标目录下


我这里使用的还是mv命令,由于这一系列文件的前几个字母都是相同的,所以我们可以直接输入boostdesc_*指代所有带有boostdesc_前缀的文件,最后的两个英文句号指代父目录

 

对vgg_generated_*.i文件做同样的操作,之后执行sudo rm -rf <folder name>删去两个文件夹(不删除也可以)。


移动vgg文件、删除两个文件夹


3. CMake编译

 

复制好文件之后,就可以进行CMake编译了,第三步的逻辑线非常简单:

 

方法3--逻辑图


我们拿boostdesc_lbgm.ivgg_generated_48.i为例来解读下载日志


方法3--两个文件的下载日志


两个文件的日志格式相同:#do_copy代表执行文件任务-->之后程序进入下载目录下寻找文件-->找到文件-->校验签名(#check_md5)-->签名正确(#match_md5)-->任务完成
 
至于该方法为什么不适用于压缩包,简单解释就是CMake对待文件任务和压缩包任务时执行的逻辑不同,通过上文的逻辑图可以发现,当CMake执行压缩包任务时,如果在目标目录下存在压缩包或解压后的文件,程序会将目标目录移除并重新创建一个,所以,即使我们将正确的文件放在了目标目录下,也会被删除:

方法3--ippicv压缩包下载日志


上图的逻辑是:执行压缩包任务(#do_unpack)-->程序检查下载目录-->存在压缩包-->签名校验(#check_md5)-->签名正确-->检查目标目录下是否存在文件-->存在-->删除目标目录(#remove_unpack)-->新建目标目录(#mkdir)-->压缩包解压至目标目录下(#unpack)


4.3 CMake的结果


当我们解决了下载失败的问题之后,再进行CMake编译,就会发现输出的信息中不会再有CMake警告了:


ippicv压缩包成功解压


3种文件成功“下载”

 

使用CMake编译完成后会输出OpenCV的配置信息汇总,包括了额外模块的位置、操作系统版本、CMake生成器类型、编译模式等内容:


OpenCV配置信息汇总


在输出信息的最后可以看到Configuring doneGenerating doneBuild files have been written to: <build_directory>三行输出,这代表该项目的构建文件已经生成完毕,所有新生成的文件都保存在了构建目录下:


CMake编译完成&编译生成的文件


上图使用ls命令查看构建目录debug中的内容,可以发现一个叫Makefile的文件,这就是下一步make编译时需要读取的配置文件:


Makefile




下一篇是make编译,包括make多线程编译make install安装两个步骤,内容应该会很简单



~END~


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

评论