OpenCV 4.10.0
Open Source Computer Vision
加载中...
搜索中...
无匹配项
如何在“Microsoft Visual Studio”中使用 OpenCV 构建应用程序

上一篇教程: 在 Windows 中安装
下一篇教程: 图像监视:在 Visual Studio 调试器中查看内存中的图像

原作者Bernát Gábor
兼容性OpenCV >= 3.0
警告
本教程可能包含过时的信息。

此处描述的所有内容都适用于 OpenCV 的C\C++界面。我从您已经阅读并成功完成了 在 Windows 中安装 教程这一假设开始。因此,在继续之前,请确保您有包含 OpenCV 头文件和二进制文件在内的 OpenCV 目录,并按照此处所述设置环境变量 设置 OpenCV 环境变量并将其添加到系统路径中

由我们发行的 OpenCV 库在 Microsoft Windows 操作系统中是动态链接库(DLL)。这些库的优点在于仅在运行时按需加载库中的所有内容,并且无数程序可以使用同一个库文件。这意味着如果您有十个正在使用 OpenCV 库的应用程序,则不必为每个应用程序准备一个版本。当然,您需要在希望运行应用程序的所有系统上安装 OpenCV 的dll

另一种方法是使用具有lib扩展名的静态库。您可以按照 在 Windows 中安装 教程中所述使用我们的源文件来构建这些文件。使用此方法时,库将内置在您的exe文件中。因此,不存在由于某种原因导致用户删除该文件的情况。这样做的缺点是您的应用程序体积较大,并且在启动期间加载它需要更长的时间。

要使用 OpenCV 构建应用程序,您需要做两件事

  • 告诉编译器 OpenCV 库的样子。您可以通过向其显示头文件来做到这一点。
  • 告诉链接器在需要时从哪里获取 OpenCV 的函数或数据结构。

    如果您使用lib系统,则必须设置库文件所在的路径,并指定在其中一个库中查找。在构建过程中,链接器将查看这些库,并将所有已使用的函数和数据结构的定义和实现添加到可执行文件中。

    如果你使用DLL系统,你必须再次指定所有这些,但现在出于不同的原因。这是 Microsoft OS 的特定内容。链接器似乎需要知道在运行时在 DLL 的何处搜索数据结构或函数。此信息存储在lib文件中。然而,它们不是静态库。它们被称为导入库。这就是在 Windows 中制作一些DLL时也会最终得到一些lib扩展库的原因。优点是运行时只需要DLL

要将所有这些信息传递给 Visual Studio IDE,你可以全局执行(这样你的所有未来项目都将获取到这些信息),也可以本地执行(这样仅对你当前项目有效)。全局方法的优势在于你只需要执行一次;然而,可能并不希望始终使用这些信息来归类所有项目。如果是全局方法,你执行的方式取决于所使用的 Microsoft Visual Studio。有2008 之前的版本和执行此操作的2010 方法。我将在本教程的全局部分展示其主要区别。

Visual Studio 中项目的基项是解决方案。解决方案可能包含多个项目。项目是应用程序的构建模块。每个项目都将实现某项内容,而你将拥有一个可以将此项目拼图组合在一起的主项目。对于许多简单应用程序(例如许多教程将涉及的内容),你不需要将应用程序分解为模块。在这些情况下,你的主项目将是唯一存在的项目。现在通过转到“文件”->“新建”->“项目”菜单选择来在 Visual Studio 内新建一个解决方案。选择类型为Win32 控制台应用程序。输入其名称,并选择创建它的路径。然后在下一个对话框中,请确保创建一个空项目。

local 方法

各个项目都是独立构建的。因此,每个项目具有自己的规则包。IDE 需要了解的所有信息以构建您的项目都存储在这个规则包中。对于任何应用程序,至少有两种构建模式:ReleaseDebugDebug 具有许多功能,可以让您在应用程序中更轻松地查找和解决错误。相反,Release 是一个经过优化的版本,其目标是让应用程序运行得尽可能快或尽可能小。您可能会认为这些模式在构建期间还需要不同的规则。因此,对于您的每种构建模式,存在不同的规则包。这些规则包在 IDE 中称为项目属性,您可以使用属性管理器查看和修改它们。您可以通过查看 –> 属性页来打开它(对于 Visual Studio 2013 及更高版本,请转到查看 –> 其他窗口 –> 属性管理器)。展开它,您将看到现有的规则包(称为属性表)。

这些真正有用的东西是,您可以一次创建规则包,然后稍后将其添加到新项目中。一次创建,随后重复使用。我们要创建一个新的属性表,其中将包含编译器和链接器需要了解的所有规则。当然,我们需要为 Debug 和 Release 构建分别创建一个单独的属性表。按照以下图像所示,从 Debug 开始。

例如,使用OpenCV_Debug 名称。然后通过选择表格,右键单击 –> 属性。以下,我将展示如何本地设置 OpenCV 规则,因为我不使用一些自定义规则来污染项目,我认为没有必要这样做。转到 C++ 组常规项,并在“*其他包含目录*”下添加 OpenCV 包含的路径。如果您没有 *“C/C++”* 组,则应向项目添加任何 .c/.cpp 文件。

$(OPENCV_DIR)\..\..\include

在增加第三方库设置时,通常建议使用环境变量背后的功能。OpenCV 库的完整位置可能会在每台系统上发生变化。此外,你甚至可能最终因为某些原因而移动安装目录。如果你在你的属性表中给出明确的路径,那么当你把它传递给使用不同 OpenCV 安装路径的其他人时,你的项目将无法工作。此外,修复此问题需要手动修改每条明确路径。一种更优雅的解决方案是使用环境变量。从美元符号开始的括号内的所有内容都将在运行时用当前环境变量值替换。下面介绍我们在前面的教程中已经设置的环境变量设置 设置 OpenCV 环境变量并将其添加到系统路径中

接下来转到链接器 –> 常规,在 *"其他库目录"* 下添加库目录

$(OPENCV_DIR)\lib

然后,你需要指定链接器应查找的库。为此,转到链接器 –> 输入并在 *"其他依赖项"* 条目下添加所有要使用的模块的名称

库的名称如下所示

opencv_(模块名称)(使用的库版本号)d.lib

对于最新版本,完整列表将包含

opencv_calib3d300d.lib
opencv_core300d.lib
opencv_features2d300d.lib
opencv_flann300d.lib
opencv_highgui300d.lib
opencv_imgcodecs300d.lib
opencv_imgproc300d.lib
opencv_ml300d.lib
opencv_objdetect300d.lib
opencv_photo300d.lib
opencv_shape300d.lib
opencv_stitching300d.lib
opencv_superres300d.lib
opencv_ts300d.lib
opencv_video300d.lib
opencv_videoio300d.lib
opencv_videostab300d.lib

或者,你的 OpenCV 下载文件可能已构建到一个大型 .lib 文件中。可通过查看 OpenCV\build\architecture\vc14\lib 来检查。在这种情况下,你将需要添加,对于版本 3.3.0

opencv_world330.lib

结尾处的字母 d 只是表示这些是调试所需的库。现在,单击确定进行保存,然后在发布规则部分中使用一个新属性进行同样的操作。确保将库名称中的 d 字母省略,并保存属性表的保存图标位于属性表的上面。

你可以在你的项目目录中找到你的属性表。此时,一个明智的决定是将其备份到某个特殊目录中,以便在将来创建 OpenCV 项目时随时使用。请注意,对于 Visual Studio 2010,文件扩展名为 props,而对于 2008,此文件扩展名为 vsprops

下次当你新建 OpenCV 项目时,只需使用属性管理器中的“添加现有属性表...”菜单条目即可轻松添加 OpenCV 构建规则。

<em>global</em> 方法

如果您发现向每一个项目中添加属性页过于繁琐,您还可以将这些规则添加到一个*“全局属性页”*中。但是,这仅适用于附加的 include 和 library 目录。您仍然需要手动指定使用的库名称,例如:使用一个属性页。

在 Visual Studio 2008 中,可以在以下位置找到此选项:Tools –> Options –> Projects and Solutions –> VC++ Directories。

在 Visual Studio 2010 中,此选项已移至一个全局属性表中,该表会自动添加到您创建的每个项目中

该过程与本地方法中描述的过程相同。只需使用环境变量 *OPENCV_DIR* 来添加 include 目录即可。

测试它!

现在,要试用此方法,请下载我们的小型测试 源代码 或从 OpenCV 源代码的示例代码文件夹中获取它。将其添加到您的项目中并进行构建。以下是其内容

#include <opencv2/core.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
if( argc != 2)
{
cout <<" Usage: " << argv[0] << " ImageToLoadAndDisplay" << endl;
return -1;
}
Mat image;
image = imread(argv[1], IMREAD_COLOR); // Read the file
if( image.empty() ) // Check for invalid input
{
cout << "Could not open or find the image" << std::endl ;
return -1;
}
namedWindow( "Display window", WINDOW_AUTOSIZE ); // Create a window for display.
imshow( "Display window", image ); // Show our image inside it.
waitKey(0); // Wait for a keystroke in the window
return 0;
}
n 维密集阵列类
定义 mat.hpp:812
bool empty() const
如果该阵列没有元素,则返回 true。
int main(int argc, char *argv[])
定义highgui_qt.cpp:3
“黑匣子”表示与磁盘上的文件关联的文件存储。
定义core.hpp:102
STL 命名空间。

你可以在两处启动 Visual Studio 编译。或者在 IDE 中启动(键盘组合:Control-F5),或者导航到你的编译目录,并双击启动应用程序。需要注意的是,这两个不是相同的。当你从 IDE 中启动时,它的当前工作目录是项目的目录,否则,是应用程序文件当前所在的目录(所以通常是你的编译目录)。此外,在从 IDE 中启动的情况下,控制台窗口在完成后不会关闭。它将等待你按下某个键。

在你编写代码内部的打开和保存命令时,记住这一点很重要。你的资源将相对你的工作目录被保存(并且在打开时被查询!!!)。除非你为 I/O 函数提供一个完整、明确的路径作为参数。在上方的代码中,我们打开了这个 OpenCV logo。在启动应用程序前,确保你已将图片文件放在了你的当前工作目录中。修改代码中的图片文件名,以便在其他图片上尝试它。运行它,瞧

在 Visual Studio 中使用命令行参数

在我们的未来教程中,你会看到程序的主要输入方法是给出运行时参数。为此,你可以直接启动一个命令窗口(在开始菜单中输入 cmd + Enter),导航到你的可执行文件,并使用一个参数启动它。因此,例如,在我的上一个项目中,它看起来像

D
CD OpenCV\MySolutionName\Release
MySolutionName.exe exampleImage.jpg

在这里,我首先更改了我的驱动器(如果你的项目不在操作系统的本地驱动器上),导航到我的项目,并使用一个示例图片参数启动了它。在 Linux 系统上,摆弄控制台窗口很常见,而在 Microsoft Windows 中,许多人几乎从不这么做。此外,在你测试你的应用程序时,一遍又一遍地添加相同的参数,是一项繁琐的任务。幸运的是,在 Visual Studio 中,有一个菜单可以自动完成所有这些

在其中指定输入的名称,而当你从 Visual Studio 环境启动你的应用程序时,你具有自动参数传递。在下一个入门教程中,你将看到对上述源代码的深入解释:从图像开始