《OpenCV3和Qt5计算机视觉应用开发》学习笔记第11章

在前面学习了使用Qt Creator和Qt测试框架来调试和测试应用程序之后,我们已经步入应用程序开发的最后一个阶段,这就是为最终用户部署应用程序。取决于目标平台,该过程本身有很多种情况,而且可以有很多不同的形式,但是它们都有一个共同点就是应用程序要以某种方式进行打包,使其能以一种简单的方式在目标平台上执行,而不需要考虑应用程序的依赖项。请记住,并不是所有目标平台(无论是Windows、macOS还是Linux)上都有Qt和OpenCV库。因此,如果仅仅向用户提供应用程序的可执行文件,那么很可能根本不能执行。


本章将完全解决这个问题,即学习以正确的方式创建一个应用程序包(通常是包含所有所需文件的文件夹),使它可以在除我们自己以及开发环境之外的计算机上执行,而不需要用户准备任何所需库。为了能够理解本章介绍的一些概念,需要首先了解一下在创建应用程序可执行文件时后台会发生的一些基本情况。我们将讨论构建过程的三个主要阶段,即应用程序可执行文件(或库)的预处理、编译以及链接。然后,将学习完成链接的两种不同方式,即动态链接和静态链接。我们将讨论这两种链接方式有何不同,以及它们如何影响部署,还会讨论在Windows、macOS和Linux操作系统上如何动态或静态地构建Qt和OpenCV库。在此之后,我们将为上述所有平台创建并部署一个简单的应用程序。我们将利用这个机会了解Qt安装程序框架,并学习如何创建能够通过网站下载链接、闪存驱动器或任何其他媒体交付给最终用户的安装程序。在本章的最后,将能够为最终用户提供执行我们的应用程序所需要的文件,不多也不少。
本章将介绍以下主题:
❑ Qt和OpenCV框架的动态和静态链接
❑ 配置Qt工程项目以使用静态库
❑ 部署用Qt和OpenCV编写的应用程序
❑ 用Qt安装程序框架创建跨平台的安装程序

11.1 后台构建过程
编写应用程序时需要编辑某些C++头文件或源文件,然后在工程项目文件中添加某些模块,最终按下“run”按钮,这一切看起来都是很自然而然的事情。但是有些过程是在后台按顺序进行的,由IDE(在我们的例子中是Qt Creator)执行,这些过程使得自然流畅的开发过程成为可能。通常,在Qt Creator或任何其他的IDE中按下“run”或“Build”按钮时,有三个主要过程会导致可执行文件(例如*.exe)的创建。下面列出这三个过程:
❑ 预处理
❑ 编译
❑ 链接
这是对从源文件创建应用程序时所经历的过程和阶段的一个非常高级的分类。该分类允许对这些过程进行更简单的概述,并以更简单的方式理解它们的通用目标。但是,这些过程包括很多子过程和阶段,这不在本书的范围之内,因为我们主要感兴趣的是以某种方式影响部署流程的过程。但是,你可以通过网络或任何有关编译和链接的书籍来了解相关知识。
11.1.1 预处理
该阶段是在将源代码送入实际的编译器之前,将源代码变换为最终状态的过程。为了进一步解释该阶段,请考虑所有包含文件和各种编译器指令,最重要的是在Qt框架中那些不是标准C++语言组成部分的特定于Qt的宏和代码。在第3章中,我们学习了uic和moc,它们可以将那些用特定于Qt宏和指南编写而成的UI文件和C++代码转换为标准C++代码(更确切地说,在Qt的最新版本中,转换为C++11或更高版本)。即使这些过程并不是C++源代码上执行的标准预处理的一部分,但是当我们使用Qt框架或基于自身规则集生成代码的框架工作时,它们仍处于相同的阶段。

图11-1是对预处理阶段与使用uic、moc等特定于Qt代码的生成相结合时的描述。该过程的输出在图11-1中标记为编译器的单输入文件(Single Input File for Compiler),很显然,这个文件包含编译源代码所需的所有标记和信息。然后,该文件将送入编译器并进入编译阶段

11.1.2编译
在构建过程的第二个主要阶段,编译器获取预处理程序(或者在我们的例子中是预处理阶段)的输出,其中还包括由uic和moc生成的代码,并将其编译成机器代码。在构建过程中可以保存并重用该机器代码,因为只要不改变源文件,那么生成的机器代码也会保持不变。通过在构建应用程序时确保重用单个独立的编译对象(例如,*.obj或*.lib文件),而不是每一次构建工程项目时都要生成编译对象,该过程有助于节省大量时间。其好处在于,这是由IDE来处理的,不需要我们为此烦恼。由编译器产生的输出文件将送入链接器,由此进入链接阶段。
11.1.3链接
链接器是在构建过程中调用的最后一个程序,其目标是链接编译器产生的对象以产生可执行文件或库。该过程对于我们来说是最重要的,因为它可以对部署应用程序的方式、可执行文件的大小等产生巨大影响。为了更好地理解这一点,首先需要讨论两种可能的链接类型的区别:
❑ 动态链接
❑ 静态链接
动态链接是将编译器生成的对象链接起来的过程,方法是在生成的可执行文件或库中放入函数名称,以便特定函数的实际代码驻留在共享库(例如,*.dll文件)中,而且库的实际链接和加载在运行时完成。动态链接最明显的优点和缺点是:
❑ 应用程序在运行时将需要访问共享库,因此必须将这些共享库与应用程序的可执行文件一起部署,并确保应用程序能够访问共享库。例如,在Windows上,可以将其复制到应用程序的可执行文件所在的相同文件夹中,或者在Linux上,将其放入默认的库路径中,如/lib/。
❑ 动态链接允许在独立的共享库文件中保留应用程序的独立部分,从而获得极大的灵活性。通过这种方式,可以单独更新共享库,而不需要重新编译应用程序的所有部分。
与动态链接相反,静态链接可用于将所有需要的代码链接到生成的可执行文件中,从而创建一个静态库或可执行文件。你可能猜到了使用静态库与使用共享库具有完全相反的优点和缺点:
❑ 无须部署用于构建应用程序的静态库,因为所有的代码实际上都被复制到生成的可执行文件中了。
❑ 应用程序的可执行文件的大小将会增加,这就意味着更长的初始加载时间以及更大的部署文件。
❑ 一旦库或应用程序任意部分发生任何更改,都需要对其所有组成部分执行完整的重建过程。
在本书全部地方,特别是在为一个完整计算机视觉应用程序开发插件时,都使用了共享库和动态链接。这是因为当我们用所有默认的CMake设置构建OpenCV,并用第1章中使用的官方安装程序来安装Qt框架时,它们都是动态链接的和共享的库(在Windows上是*.dll,在macOS上是*.dylib,等等)。在接下来的章节中,将学习如何使用其源代码静态地构建Qt和OpenCV库。通过使用静态链接库,可以创建在目标系统上不需要任何共享库的应用程序。这可以大大减少部署应用程序所需的工作量。尤其是在macOS和Linux操作系统的OpenCV中,用户除了复制和运行应用程序之外,无须做任何事情,但是,用户需要执行一些操作,或者你必须写一些脚本,以确保在执行应用程序时,所有必需的依赖项都已经就绪。
11.2 构建OpenCV静态库
先从OpenCV开始,它遵循的建立静态库的操作步骤与构建动态库几乎是一样的。有关这方面的更多信息,可以参考第1章。就像在第一章中介绍过的那样,只需下载源代码、提取并使用CMake来配置构建。但这次,除了选中“BUILD_opencv_world”选项旁边的复选框之外,还要确保不选中下列每一个选项旁边的复选框以关闭这些选项:
❑ BUILD_DOCS
❑ BUILD_EXAMPLES
❑ BUILD_PERF_TESTS
❑ BUILD_TESTS
❑ BUILD_SHARED_LIBS
❑ BUILD_WITH_STATIC_CRT(只在Windows上适用)
关闭前四个参数只是为了加速构建过程,而且这完全是可选的。禁用“BUILD_SHARED_LIBS”只支持OpenCV库的静态(非共享)构建模式,最后一个参数(在Windows上)有助于避免不兼容的库文件。现在,如果使用与第1章中相同的操作步骤开始构建过程,那么这次在安装文件夹中最终得到的不是共享库(例如,Windows上的*.lib和*.dll文件),而是静态链接的OpenCV库(在Windows上,只有*.lib文件,而没有任何*.dll文件)。接下来要做的就是配置工程项目,以使用OpenCV静态库。要么用*.pri文件,要么直接将这些库添加到Qt工程项目的*.pro文件中,为了让工程项目可以使用OpenCV静态库,需要下列代码行:

win32:{
    INCLUDEPATH += "C:/path_to_opencv_install/include"
    Debug:{
        LIBS += -L"C:/path_to_opencv_install/x86/vc14/staticlib"
            -lopencv_world330d
            -llibjpegd
            -llibjasperd
            -littnotifyd
            -lIlmImfd
            -libwebpd
            -llibtiffd
            -llibprotobufd
            -llibpngd
            -lzlibd
            -lipp_iw
            -lippicvmt
    }
    
    Release:{
        LIBS += -L"C:/path_to_opencv_install/x86/vc14/staticlib"
            -lopencv_world330
            -llibjpeg
            -llibjasper
            -littnotify
            -lIlmImf
            -libwebp
            -llibtiff
            -llibprotobuf
            -llibpng
            -lzlib
            -lipp_iw
            -lippicvmt
    }
}

在上述代码中,库的顺序不是随机的,需要以其依赖项的正确顺序包含这些库。在Visual Studio 2015中,从主菜单选择“Project”,然后选择“Project Build Order…”,可以自己查看这个顺序。对于macOS用户来说,必须用“unix:macx”替换上述代码中的win32,而且库的路径必须与build文件夹中的路径匹配。至于Linux,则可以使用我们在动态库中曾经使用过的pkgconfig代码行,如下所示:

unix: !macx{
    CONFIG += link_pkgconfig
    PKGCONFIG += opencv
}

请注意,即使在Windows操作系统上静态构建OpenCV,仍然有一个库将在输出文件夹中作为动态库存在,这就是opencv_ffmpeg330.dll。无须将其包含到*.pro文件中,但是,仍然需要将它与应用程序的可执行文件一起部署,因为OpenCV本身就依赖它才能支持某些广为人知的视频格式和编码。

11.3 构建Qt静态库

默认情况下,官方Qt安装程序只提供动态Qt库。在第1章中使用下列链接提供的安装程序在我们的开发环境中安装Qt时,也是如此:
https://download.qt.io/official_releases/qt/5.15/5.15.0/
因此,简单地说,如果想要使用静态Qt库,则必须使用它们的源代码自己构建这些库。可以按照下面的步骤配置、构建和使用静态Qt库:
1.为了能够建立一组静态Qt库,需要先从Qt下载网站下载源代码。通常,所有需要的源代码已打包成一个压缩文件(*.zip、*.tar.xz,等等)。在我们的例子中(Qt5.9.1版本),可以使用下列链接下载Qt的源代码:
https://download.qt.io/official_releases/qt/5.15/5.15.0/single/
请下载“qt-everywhere-src-5.15.0.zip(或*.tar.xz)”,并继续下一步。
2.将源代码解压到你选择的一个文件夹中。我们假设解压文件夹为“Qt_Src”,并且位于“c:/dev”文件夹中(在Windows操作系统上)。因此,解压的Qt源代码的完整路径是“c:/dev/Qt_Src”。
对于macOS和Linux用户来说,路径可能类似于“Users/amin/dev/Qt_Src”,所以如果使用上述提到的操作系统之一,而不是Windows操作系统的话,就需要在引用它的所有操作步骤中替换此路径,这应该是很明显的。
.现在,在进行下一步之前,需要处理一些依赖项;macOS和Linux用户通常在这一步不需要做任何事情,因为在这些操作系统上默认情况下都存在所有必需的依赖项。但是,同样的情况并不适用于Windows用户。通常,下面这些依赖项必须在计算机上存在,然后才能从源代码建立Qt:
❑ ActivePerl(https://www.activestate.com/activeperl/downloads)。
❑ Python(https://www.python.org),你需要2.7.X版本,可以用最新的现有版本替换X,我们编写本书的时候是14。
❑ 为了方便Windows用户,在Qt源代码ZIP文件中的gnuwin32子文件夹内提供了Bison。请务必将“c:/dev/Qt_Src/gnuwin32/bin”添加到PATH环境变量中。
❑ Flex,与Bison一样,也是在gnuwin32子文件夹内提供的,需要将该子文件夹添加到PATH环境变量中。
❑ GNU gperf,与Bison和Flex一样,是在gnuwin32子文件夹内提供的,需要将该子文件夹添加到PATH环境变量中。
为了确保一切正常,请尝试运行相关命令来执行刚刚介绍过的每一个依赖项。在某些条件下,需要这样做,比如你可能忘记将其中一个依赖项添加到PATH,或者在macOS和Linux用户情况下,因为各种可能的原因依赖项被删除而不存在。如果在命令提示符(或终端)中执行下列每一个命令,并确保没有遇到未识别或未发现类型的错误,就已经足够了。
perl
python
bison
flex
gperf
4.现在,在Windows上运行“Developer Command Prompt for VS2015”,在macOS或Linux上运行“Terminal”。然后还需要运行一组连续的命令,才能从源代码配置并建立Qt。配置是这一步骤中最关键的部分,是使用configure命令来完成的。configure命令存在于Qt源文件夹的根目录中,它接受下列参数(请注意,实际的参数集是一个非常长的列表,因此这里只列出经常使用的部分):
❑ –help或–h:该参数可用来显示配置命令的帮助内容。
❑ –verbose或–v:该参数可用来在构建时显示更多的细节消息。
❑ -opensource:该参数用来建立Qt框架的开源版本。
❑ -commercial:该参数用来建立Qt框架的商业版。
❑ -confirm-license:该参数可以用来自动确认选择的Qt框架的许可证书或版本。
❑ –shared:该参数可以用来动态地建立Qt,即共享的Qt库。
❑ -static:该参数可以用来静态地建立Qt。
❑ -platform:该参数用来设置目标平台。该参数后必须跟着一个支持的平台。默认情况下,Qt支持很多平台,可以在qtbase/mkspecs文件夹中进行查看,该文件夹是解压Qt源代码后的一个子文件夹。如果省略这个参数,就会自动检测平台。
❑ -prefix:该参数后跟着一个路径,可以用来设置构造库的安装文件夹。
❑ -skip:该参数后跟着一个资源库名称,可以用来跳过一个特定的Qt模块的构建。默认情况下,也就是说如果省略这个参数,那么将建立Qt源文件夹内所有的资源库。不管出于何种原因,如果想要跳过一个模块的构建,那么可以使用“–skip”参数,将其传递给configure命令,并确保从资源库的名称中删除起始qt。例如,如果想要跳过Qt WebEngine模块的建立,该模块在Qt源代码文件夹内有一个名为qtwebengine的文件夹,则需要将“-skip webengine”传递给配置命令。
❑ -make:该参数可以用来在Qt构建中包含一个所谓的部分。这个部分可以是库的libs,测试的tests,例子的examples,等等。
❑ -nomake:该参数与-make参数相反,可以用来从Qt构建中排除一部分。在需要加速构建过程的情况下,这可能是非常有用的,因为通常不需要构建测试或示例。
这里所提供的参数列表对于建立一个具有更多或更少默认设置的Qt框架的静态版本应该是足够了。
5.现在开始配置Qt构建。首先,需要使用下列命令切换到Qt源代码的文件夹:
cd c:/dev/Qt_Src
6.然后键入下列命令启动配置:
configure -opensource -confirm-license -static -skip webengine -prefix "c:devQtStatic" -platform  win32-msvc
提供“-skip webengine”是因为在编写本书时不支持静态地建立Qt WebEngine模块。还要注意,提供了“-prefix”参数,这是我们想要在其中得到静态库的文件夹。需要留意这个参数,因为你不能在此之后再对其进行复制,并且由于构建配置,静态库只有保持在磁盘上该位置时才会起作用。在参数列表中已经描述了其余参数。
还可以将下列代码添加到配置命令,以跳过可能不需要的部分,并加速构建过程,因为它会花费很长时间:
-nomake tests -nomake examples
在macOS和Linux上,必须从configure命令中省略下列部分。这样做的原因很简单:平台会被自动检测到。当然,在Windows上也是如此,但是因为我们想要强制构建Qt库的32位版本(以支持更广泛的Windows版本),因此将继续使用这个参数:
-platform win32-msvc
取决于电脑的规格,配置过程不应该花费太长时间。在完成配置之后,应该看到与下列内容类似的输出,否则,需要再仔细检查一下之前的步骤:
Qt is now configured for building.Just run 'nmake'.
Once everything is built, you must run 'nmake install'.
Qt will be installed into 'c:devQtStatic'.
Prior to reconfiguration, make sure you remove any leftovers from the previous build.
请注意在macOS和Linux上,在上述输出中将用make替换nmake。
7.就像在配置输出中介绍的那样,需要键入构建和安装命令。
在Windows上,使用下列命令:
nmake
nmake install
在macOS和Linux上,使用下列命令:
make
make install
注意,第一条命令通常需要很长时间才能完成(取决于电脑的规格),因为Qt框架包含了很多需要构建的模块和库,所以在这一步骤需要有点耐心。在任何情况下,如果一直完全遵从所有提供的步骤,那么在构建时不会有任何问题。
值得注意的是,如果使用计算机上限制区域中的安装文件夹(-prefix参数),那么必须确保使用管理员级别(如果正在使用Windows)运行命令提示符实例,或用sudo前缀执行构建和安装命令(如果在macOS或Linux上)。
8.运行install命令之后,应该在配置期间作为前缀参数提供的文件夹中得到静态Qt库,这个文件夹也就是安装文件夹。因此,在这一步,需要将这个新构建的Qt静态库集添加为Qt Creator中的一个工具包。为此,打开“Qt Creator”,从主菜单选择“Tools”,然后选择“Options”。在左侧列表中,选择“Build&Run”,然后选择“Qt Versions”选项卡。现在,单击“Add”按钮,并浏览到“Qt build installation”文件夹,选择“qmake.exe”,在我们的例子中,应该是在“C:devQtStaticbin”文件夹内。图11-2显示在正确添加新的Qt构建版本之后“Qt Versions”选项卡的状态。

             图11-2 正确添加新的Qt构建之后“Qt Versions”选项卡的状态界面截图

9.现在,切换到“Kits”选项卡。应该能够看到在本书中一直使用以构建Qt应用程序的工具包。例如,在Windows上,它应该是“Desktop Qt 5.9.1MSVC201532bit”。选择此选项,并单击“Clone”按钮,然后选择在上一步的“Qt Versions”选项卡中设置的“Qt Version”(如果在那儿没有看到新构建的版本,可能需要单击一下“Apply”按钮,然后就会出现在组合框中了)。另外,请确保从其名称中删除“Clone of”并在末尾添加“Static”这个词,以便可以很容易地对其进行分区。图11-3显示“Kits”选项卡的状态,以及对其进行配置的方式。

                                 图11-3 “Kits”选项卡的状态及其配置方式

这就是构建并配置静态Qt工具包的过程。现在,可以用它开始Qt工程项目的创建,这与用默认的Qt工具包(这是动态工具包)的方式是完全相同的。唯一需要注意的一件事是:创建并配置Qt工程项目时,将其选作目标工具包。让我们用一个简单的例子来完成这个工作。首先,创建一个Qt Widgets应用程序,并将其命名为“StaticApp”。在“Kit Selection”页面,确保选择新构建的静态Qt工具包,并一直单击“Next”,直到进入Qt代码编辑器。图11-4描述了“Kit Selection”页面及其外观(在Window操作系统上)。

                           图11-4 Window操作系统上的“Kit Selection”页面的截图

不用做太多的更改,也不用添加任何代码,只需单击“Run”按钮,即可构建并执行这个工程项目。现在,如果浏览到这个工程项目的构建文件夹,就会注意到:可执行文件的大小比之前使用默认的动态工具包进行建立时要大得多。为了做个比较,在Windows操作系统和调试模式下,动态构建的版本应该远小于1兆字节,而静态构建的版本大约是30兆字节,这要多得多。这是因为,正如之前介绍过的那样,所有需要的Qt代码现在都被链接到可执行文件。尽管严格地说,这在技术上是不正确的,但是可以将其看成在可执行文件自身内部嵌入库(*.dll等文件)。

现在,来试试在示例工程项目中也使用静态OpenCV库。只需将需要添加的内容添加到StaticApp.pro文件中即可,另外尝试一些简单的OpenCV函数,如imread、dilate、imshow,来测试静态OpenCV库。现在,如果查看静态链接的可执行文件的大小,就会注意到文件的大小现在更大了。明显的原因是,所有需要的OpenCV代码都被链接到可执行文件自身中。

11.4 部署Qt+OpenCV应用程序
向最终用户提供一个包含能够在目标平台上运行所需的所有内容的应用程序包,并且在处理所需依赖项方面几乎不需要用户的任何努力,这是非常重要的。要实现这种立刻就可以工作的应用程序,主要依赖于创建应用程序所用的链接类型(动态或静态),还依赖于目标操作系统的具体配置。
11.4.1 使用静态链接部署
静态地部署应用程序意味着应用程序将独立运行,不必考虑几乎所有需要的依赖项,因为它们已经在可执行文件中了。在构建应用程序时,只要保证选择“Release”模式就足够了,如图11-5所示。

                                        图11-5 Qt Creator创建应用程序界面截图

在“Release”模式中建立应用程序时,可以直接将生成的可执行文件交付给用户。
如果尝试将应用程序交付给Windows用户,则在执行应用程序时,可能会遇到与图11-6类似的错误。

                                               图11-6 错误提示界面截图

出现这个错误的原因是,在Windows上,即使是静态构建Qt应用程序时,仍然需要确保在目标系统上存在Visual C++可重分发包。这是使用Microsoft Visual C++构建C++应用程序所必需的,所需的可重分发包版本与安装在计算机上的Microsoft Visual Studio相对应。在我们的例子中,这些库的安装程序的正式名称是“Visual C++Redistributables for Visual Studio 2015”,可以从以下链接下载:https://www.microsoft.com/en-us/download/details.aspx?id=48145。

常见做法是,在应用程序的安装程序内包含可重分发包安装程序,如果还没有安装它们,那么就静默安装它们。该过程发生在Windows个人计算机上使用的大多数应用程序上,只是很多时候,没有被注意到。

我们已经简要地介绍了静态链接的优点(部署的文件更少)和缺点(更大的可执行文件)。但是,如果在部署环境中讨论,就会有一些更复杂的问题需要考虑。因此,下面列出在使用静态链接来部署应用程序时的另外一些(更完整的)缺点:
❑ 构建过程需要更多时间,而且可执行文件变得越来越大。
❑ 不能将静态和共享(动态)Qt库混合,这就意味着不能借用插件的功能,无法通过从头开始构建所有的内容来扩展应用程序。
❑ 从某种意义上讲,静态链接意味着隐藏用于构建应用程序的库。遗憾的是,该选项并不是所有库都提供,从而会导致应用程序的许可权问题。这种复杂性的出现一部分是因为Qt框架使用了一些第三方库,而它们没有提供像Qt那样的许可选项集。有关许可的问题并不适合在本书中进行讨论,所以只简单地提一下就够了,打算使用Qt库的静态链接创建商业应用程序时,一定要慎重。关于Qt内第三方库使用许可的详细列表,可以随时在下面链接的Qt页面中看到:
https://doc.qt.io/qt-5/licensing.html
关于各种LGPL许可的完整参考及其在Qt模块(以及可以在网上找到的其他开源软件)中使用的版本,可以参考下列链接:https://www.gnu.org/licenses/。
还可以使用以下链接了解在选择Qt开源许可之前需要知道的内容:https://www.qt.io/qt-licensing-terms/。
静态链接,即使存在刚才所说的所有缺点,在某些情况下,仍然是一个很好的选择,前提是你可以遵守Qt框架的许可选项。例如,在Linux操作系统中,为应用程序创建一个安装程序需要的一些额外工作和处理,而静态链接可以有助于极大地减少部署应用程序所需的工作量(只复制和粘贴)。因此,最终确定是否使用静态链接取决于你以及你打算如何部署应用程序。在本章末尾,对可能的链接和部署方法都了解之后,再做出这个重要的决定就会容易得多。

11.4.2 使用动态链接部署
使用共享库(或动态链接)部署用Qt和OpenCV构建的应用程序时,需要保证应用程序的可执行文件能够访问Qt和OpenCV的运行时库,以便对其进行加载和使用。运行时库的可访问性或可见性根据操作系统的不同可以有不同的含义。例如,在Windows上,需要将运行时库复制到应用程序可执行文件所在的文件夹中,或将其添加到已记入PATH环境值的文件夹中。
Qt框架提供了命令行工具来简化Windows和macOS上的Qt应用程序的部署。如上所述,需要做的第一件事情是确保在“Release”模式下,而不是在“Debug”模式下构建应用程序。然后,如果是在Windows上,首先将可执行文件(假设将其命名为“app.exe”)从构建文件夹复制到一个单独的文件夹(我们将其称为“deploy_path”)中,并使用命令行实例执行下列命令:
cd deploy_path
QT_PATHbinwindeployqt app.exe
windeployqt工具是一个部署助手工具,它简化了将所需的Qt运行时库复制到应用程序可执行文件所在文件夹的过程。windeployqt工具接受可执行文件作为参数,然后确定用于创建它的模块,之后复制所有必需的运行时库以及所有额外的必需依赖项,例如,Qt插件、翻译等等。这将处理所有必需的Qt运行时库,但是我们仍然需要处理OpenCV运行时库。如果遵从第1章中建立OpenCV动态库的所有步骤,那么只需手动将“opencv_world330.dll”和“opencv_ffmpeg330.dll”文件从OpenCV安装文件夹(在x86vc14bin文件夹内)复制到应用程序可执行文件所在的文件夹。
本书的前几章建立OpenCV时,并没有真正地去研究打开“BUILD_opencv_world”选项的优点,但是,现在应该清楚的是,这简化了OpenCV库的部署和使用,在部署OpenCV应用程序时,只需在*.pro文件中设置LIBS的一个条目,并手动复制一个文件(不包含ffmpeg库)。还应该注意,这种方法的缺点是,需要随应用程序一起复制所有OpenCV代码(在单个库中),即使在项目中不需要或者不使用所有模块。
还要注意,在Windows上,正如在使用静态链接部署的章节中介绍过的那样,仍然需要为应用程序的最终用户提供Microsoft Visual C++可重分发文件。
在macOS操作系统上,也可以轻松地部署使用Qt框架编写的应用程序。因为这个原因,可以使用Qt提供的macdeployqt命令行工具。与windeployqt类似,它接受一个Windows的可执行文件,并将所需的库放入相同的文件夹,而macdeployqt接受一个macOS应用程序包,并通过将所有需要的Qt运行时文件作为私有框架复制到包内,来使其可以部署。下面是一个例子:
cd deploy_path
QT_PATH/bin/macdeployqt my_app_bundle
此外,还可以提供一个额外的-dmg参数,这将创建一个macOS*.dmg(磁盘镜像)文件。至于使用动态链接时OpenCV库的部署,可以使用Qt安装程序框架(将在下一节中学习)、第三方提供者或者脚本创建安装程序,用于确保所需的运行时库被复制到所需的文件夹中。这是因为如果只将运行时库(无论是OpenCV,还是其他什么)复制到应用程序可执行文件所在的相同文件夹中,这对使其在macOS上能够被应用程序中“看见”并没有帮助。同样的情况也适用于Linux操作系统,不幸的是,在这里甚至连部署Qt运行时库的工具也不存在(至少目前是这样),因此除了OpenCV库,还需要照顾Qt库,即通过使用可信的第三方供应商(可以在网上搜索)或通过使用Qt自身提供的跨平台安装程序,并与一些脚本结合,来确保执行我们的应用程序时一切就绪。

11.4.3 Qt安装程序框架
Qt安装程序框架允许为Windows、macOS以及Linux操作系统创建一个跨平台的Qt应用程序的安装程序。它允许创建标准的安装向导,在其中,用户经历连续的对话框以访问所有必需的信息,并看到应用程序的安装进度等等,类似于你可能遇到的大多数安装程序,特别是Qt框架自身的安装程序。基于Qt框架自身的Qt安装程序框架作为一个不同的包提供,并且在一台计算机上并不需要出现Qt SDK(Qt框架、Qt Creator等等)。还可以使用Qt安装程序框架为不仅仅是Qt应用程序的其他任何应用程序创建安装包。
本节将学习如何使用Qt安装程序框架创建一个基本的安装程序,由它负责在一个目标计算机上安装应用程序并复制所有必要的依赖项。结果将会是一个可执行的安装文件,可以将其放在服务器上以便下载,还可以通过U盘、CD或任何其他媒体类型中提供。这个示例工程项目将帮助你以自己的方式开始处理Qt安装程序框架的很多强大的功能。
可以使用下面的链接下载并安装Qt安装程序框架。使用这个链接或者任何其他下载源时,请务必下载最新的版本。目前的最新版本是3.0.2:
https://www.qt.io/download-qt-installer
在下载并安装Qt安装程序框架之后,可以开始创建那些Qt安装程序框架在创建安装程序时所需的文件。可以通过简单地浏览到Qt安装程序框架,并从“examples”文件夹复制“tutorial”文件夹,来完成这个工作,如果想要快速重命名并重新编辑所有文件并快速创建安装程序,那么这也是一个模板。我们将用另一种方式手动创建它们,首先,因为我们想要了解Qt安装框架所需要的文件和文件夹的结构,第二,因为这仍然十分简单而容易。下面是创建安装程序所需要的步骤:
1.假设已经完成Qt和OpenCV应用程序的开发,那么可以开始创建包含安装文件的一个新文件夹,假设这个文件名为“deploy”。
2.在“deploy”文件夹内创建一个XML文件,并将其命名为“config.xml”。这个XML文件必须包含下列内容:

<?xml version="1.0" encoding="UTF-8"?>
<Installer>
	<Name>Your application</Name>
	<Version>1.0.0</Version> 
	<Title>Your application Installer</Title>
	<Publisher>Your vendor</Publisher>
	<StartMenuDir>Super App</StartMenuDir> 
	<TargetDir>@HomeDir@/InstallationDirectory</TargetDir> 
</Installer>

务必在上述代码中用与应用程序相关的信息替换所需的XML字段,然后保存并关闭该文件。

1.现在,在“deploy”文件夹中内创建名为“packages”的文件夹。该文件夹将包含你希望用户能够安装的各个软件包,或者使它们强制或可选安装,以便用户可以查看并决定要安装的内容。

2.用Qt和OpenCV编写简单的Windows应用程序的例子中,通常只需要一个软件包就可以包含运行应用程序所需的文件,甚至可以对Microsoft Visual C++可重分发文件进行静默安装。但是对于更复杂的情况,特别是当你希望对应用程序的各个安装元素有更多的控制时,还可以选择两个或多个软件包,甚至是子包。这是通过为每个软件包使用类似于域的文件夹名称来完成的。每一个软件包文件夹都可以有一个像“com.vendor.product”这样的名称,此处用开发人员或公司以及应用程序的名称来替代vendor和product。通过将“.subproduct”添加到父包的名称中,可以识别一个包的子包(或子分量)。例如,可以在“packages”文件夹内有下列文件夹:

com.vendor.product
com.vendor.product.subproduct1
com.vendor.product.subproduct2
com.vendor.product.subproduct1..subsubproduct1
...
这样就可以按我们喜欢的方式继续处理很多产品(包)和子产品(子包)。在我们的例子中,将创建一个包含可执行文件的文件夹,因为这描述了所有的内容,可以通过简单地将其添加到“packages”文件夹中来创建额外的包。让我们将其命名为“com.amin.qtcvapp”。现在,执行这些所需步骤:
1.在创建的新软件包文件夹(com.amin.qtcvapp)内创建两个文件夹。将其重命名为data和meta。这两个文件夹必须在所有的软件包中存在。2.复制你的应用程序文件到data文件夹内。该文件夹将被提取到目标文件中(将在后续步骤中讨论软件包的目标文件夹的设置)。如果计划创建多个软件包,那么请确保正确地分离它们的数据,并以一种有意义的方法进行。当然,如果不这样做,也不会遇到任何错误,但是应用程序的用户可能会感到困惑,例如跳过一个应该在任何时候安装的软件包,最后以一个不工作的安装应用程序作为结束。
3.现在,切换到meta文件夹,并在该文件夹内创建下面的两个文件,然后为每一个文件填入所提供的代码。
package.xml文件应该包含以下内容。必须在XML字段内填入与软件包相关的值:

<?xml version="1.0" encoding="UTF-8"?>
<Package>
	<DisplayName>Your application</DisplayName>
	<Description>Install this component.</Description> 
	<Version>1.0.0</Version>
	<ReleaseData>1984-09-16</ReleaseData>
	<Default>script</Default> 
	<Script>installscript.qs</Script> 
</Package>

上面的XML文件中的脚本可能是安装程序创建过程中最重要的一部分,它指向一个名为“installerscript.qs”的Qt安装程序脚本(*.qs文件),该文件可用来进一步自定义包、目标文件夹等等。让我们在meta文件夹内创建一个同名文件(installscript.qs),并在该文件内使用下列代码:

function Component()
{
	// initializations go here
}
Component.prototype.isDefault = function()
{
	//select (true) or unselect (false) the component by default return true;
}
Component.prototype.createOperations = function()
{
	try {
		//call the base create operations function component.createOperations();
	}catch(e) {
		console.log(e);
	}
}

这是最基本的组件脚本,用来自定义我们的包(它只执行默认动作),可以选择性地对其进行扩展,以便更改目标文件夹,在开始菜单或桌面(Windows上)创建快捷方式等等。密切关注Qt安装框架文档并学习它的脚本是一个不错的想法,这样可以创建更强大的安装程序,可以将应用程序的所有必需的依赖项都放在适当的位置,并自动完成。还可以浏览Qt安装框架的examples文件夹内所有示例,并学习如何处理不同的部署案例。例如,可以尝试为Qt和OpenCV的依赖项创建单独的包,如果用户的计算机上已经有Qt运行时库,则允许用户取消对它们的选择。

1.最后一步是使用binarycreator工具创建单个独立的安装程序。只需用一个命令提示符:(或终端)实例运行下列命令:

binarycreator -p packages -c config.xml myinstaller

binarycreator位于Qt安装框架的bin文件夹内。它需要在前面已经准备好的两个参数。-p必须后跟包文件夹,而-c必须后跟配置文件(即config.xml文件)。在执行这个命令之后,将得到myinstaller(在Windows上,可以对其追加*.exe),可以执行它来安装应用程序。这个文件应该包含运行应用程序所需的所有必需文件,其余的都将被照顾。只需要为该文件提供下载链接,或者将其放在CD上提供给用户。

图11-7是在默认及最基本的安装程序中将会遇到的对话框,该安装程序包含在安装应用程序时会遇到的大多数常见对话框:

                                            图11-7 在默认以及基本安装程序中的对话框

如果转到安装文件夹,就会注意到其中包含的文件比放入软件包的data文件夹中的文件多了几个。安装程序需要这些文件来处理修改和卸载应用程序。例如,应用程序的用户可以通过执行maintenancetool可执行文件来轻松地卸载你的应用程序,这将产生另一个简单并且对用户友好的对话框来处理卸载过程如图11-8所示。

11.5 小结

应用程序是否能够方便地在目标计算机上安装和使用,会影响到用户的体验,从而可能赢得或丢失大量的用户。特别是对于那些非专业的用户来说,必须保证创建和部署的安装程序包含所有所需的依赖项,并能够在目标平台上立刻工作。本章对与此相关的很多内容进行了讨论。我们学习了构建过程,以及链接方法如何完全改变部署体验。我们学习了用现有的Qt工具简化Windows和macOS上的部署过程。请注意,这些工具包含的参数比在本章看到的要多得多,它们值得你进行深入的研究,并试试各种参数,看看这些参数产生的影响。本章的最后一节,我们学习了Qt安装框架,并且还用它创建了一个简单的安装程序。我们学习了如何使用安装程序在目标系统上创建提取程序的包,同样的方法可用于将所有依赖项放入它们所需的文件夹中。例如,在安装时,可以将OpenCV库添加到一个包中,在Linux操作系统上将其放入/usr/lib/or/usr/local/lib/,这样,应用程序就可以对其进行访问,而不会有任何问题。有了这些技巧,我们已经对开发周期的大多数现有阶段有了一定的了解,而开发人员(尤其是计算机视觉开发人员)应当熟悉这些阶段。

                                                       图11-8 卸载应用程序页面

在本书的最后一章,将介绍Qt Quick和QML。我们将学习如何用强大的Qt以及简洁的QML创建漂亮的用户界面。我们还将学习如何将C++与QML代码相结合,以便编写能够使用像OpenCV这样的第三方框架的类,这些框架在QML代码中很容易使用。本书的最后一章还将初步介绍如何使用OpenCV与极其易用和美观的Qt Quick控件相结合,开发用于移动设备(Android和iOS)的计算机视觉应用程序。

OpenCV3和Qt5计算机视觉应用开发》是一本介绍如何结合OpenCV3和Qt5进行计算机视觉应用开发的书籍。本书共分为八,内容丰富而全面。 第一是对计算机视觉和相关技术的概述,引导读者了解计算机视觉的基础知识,以及OpenCV3和Qt5的基本概念和使用方法。 第二到第五依次介绍了OpenCV3和Qt5的基础知识和使用方法。其中,在OpenCV3的节中,读者能够学习到如何使用OpenCV3进行图像处理、特征提取、目标检测等计算机视觉任务。而在Qt5节中,读者将学习到如何使用Qt5进行图形界面设计,以及如何将OpenCV3与Qt5进行桥接,实现计算机视觉应用的图形化界面。 第六介绍了如何在Qt5中导入OpenCV3库,并给出了一些在Qt中使用OpenCV进行图像处理的示例代码。读者可以通过这一学习,了解如何在Qt中调用OpenCV函数,实现各种图像处理功能。 第七是一个完整的计算机视觉应用案例,案例中介绍了一个基于OpenCV3和Qt5开发的人脸识别系统。通过阅读这一的内容,读者可以了解到如何运用OpenCV3和Qt5构建一个实际的计算机视觉应用系统,并了解到其中的原理和细节。 第八是有关Qt5的高级使用和扩展。本内容较为高级,主要介绍了如何使用Qt5进行多线程编程、网络编程和数据库操作等高级技术,并给出了一些示例代码。 总之,《OpenCV3和Qt5计算机视觉应用开发》是一本非常实用的书籍,适合计算机视觉爱好者和开发者阅读,通过学习本书,读者能够掌握使用OpenCV3和Qt5进行计算机视觉应用开发的技巧和方法。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值