Bootstrap

【01】OpenCV模块架构介绍+示例程序演示

本系列文章是基于Windows下,结合Visual Studio2017和OpenCV4.7进行编写,使用C++代码进行演示。

1.OpenCV模块架构

  打开OpenCV文件夹(文件夹名称“OpenCV”为自己创建,此文件夹中保存OpenCV4.7解压文件),目录为"…\OpenCV\build\include\opencv2"。在OpenCV4之前"include"文件夹下有两个文件夹,分别为“opencv”和“opencv2”,在OpenCV4中将二者整合成了"opencv2"一个文件夹。打开“opencv2”可以看到如下模块架构。

下面按顺序粗略介绍一下各模块的功能:
calib3d:此模块名称由calbration(校准)和3D两部分缩写而成。顾名思义,该模块主要包含相机标定与立体视觉等功能,例如物体位姿估计、三位重建、摄像头标定等。
core:核心功能模块。这个模块主要包含OpenCV库的基础结构以及基础操作,例如OpenCV基础数据结构、绘图函数、数组操作相关函数、动态数据结构等。
dnn:深度学习模块。主要包括构建和修改神经网络、加载序列化网络模型等。该模块功能仅用于前向传递计算(即测试网络),原则上不支持网络训练。
features2d:该模块名称由features(特征)和2D两部分组成。其功能主要为处理图像特征点,例如特征检测、描述与匹配等。
flann:该模块全称为Fast Library for Approximate Nearest Neighbors(近似最近邻快速库)。模块是高位的近似近邻快速搜索算法库,主要包括快速近邻搜索与聚类等。
gapi:该模块是OpenCV4.0版本以后新加的,旨在使常规的图像处理更快和可移植。与其他模块相比,这个模块主要充当框架,而不是一些特定的CV算法。
highgui:高级GUI设计模块。包括创建和操作显示图像的窗口、处理鼠标事件以及键盘指令、提供图形交互可视化界面等。
imgcodes:图像文件读取与保存模块,主要用于图像文件读取与保存。
imgproc:该模块名称由image(图像)和process(处理)两部分缩写而成,图像处理模块。主要包括图像滤波、几何变换、直方图、特征检测与目标检测等功能。
ml:模块全称Machine Learing,机器学习模块。主要用于统计分类、回归、数据聚类等。
objdetect:目标检测模块。主要用于图像目标检测,例如检测Haar特征。
photo:计算摄影模块。主要包括图像修复和去噪等。
stiching:图像拼接模块。主要包含特征点寻找与匹配图像、估计旋转、自动校准、接缝估计等图像拼接的相关内容。
video:视频分析模块。主要包括运动估计、背景分离、对象跟踪等视频处理相关内容。
videoio:视频输入/输出模块。主要用于读取和写入视频或者图像序列。

  详细的模块介绍可根据OPenCV官网文档介绍进行查看,打开网址可以看到如下所示内容,每个模块的功能及API介绍都可以进行看到。新版本模块介绍可能为空,可以借鉴之前旧版本进行查看。
在这里插入图片描述

2.示例程序效果展示

  OPenCV提供了很多示例代码,在路径“…\OpenCV\sources\samples”中,C++示例程序在"cpp"文件夹中,本小节将介绍5个常见的示例程序。
在这里插入图片描述

2.0创建工程

  首先创建工程(此处假定你的环境已经配置好了):【文件】->【新建】->【工程】,设置项目名称及所在目录,最后点击【确定】。
在这里插入图片描述
  将【Debug】设置为“x64”模式。
在这里插入图片描述
  【视图】->【视图管理器】或者直接点击Visual Studio界面左下角的【属性管理器】。在Debug|x64中有一个名为“Microsoft.Cpp.x64.user”的配置选择(此处由于我之前已经配置过OpenCV,所以存在一个三角符号,我是通过“添加新项目表”进行设置,其实可以直接设置。这里有两个“OpenCV_test”是电脑卡了,重启项目后恢复为1个),右击“Microsoft.Cpp.x64.user”->【属性】->进入属性页。
在这里插入图片描述
  一共需要修改三个地方。
1、【VC++目录】->【包含目录】->添加OpenCV的头文件所在路径“:…\OpenCV\build\include”及“…\OpenCV\build\include\opencv2”。OpenCV文件夹前面的路径需要根据自己下载OpenCV源码进行具体修改。点击【包含目录】那一栏会出现三角形图标,点击倒三角图标进行添加即可,下面同理
2、【VC++目录】->【库目录】->添加OpenCV库文件所在路径“…\OpenCV\build\x64\vc16\lib”。同样地也需要根据自己实际下载位置进行修改,版本不同可能文件目录名称有所不同,请注意甄别
在这里插入图片描述
3、【链接器】->【输入】->【附加依赖项】。打开库目录路径可以看到有两个lib文件,后面不含“d”的是Release模式下使用的,含“d”的是Debug模式下使用。添加opencv_world470d.lib到【附加依赖项】,其中此文件中的470为版本号,我是用的OpenCV4.7.0。最后点击【确定】即可设置完毕。
在这里插入图片描述
在这里插入图片描述

2.1边缘检测示例edge.cpp

  回到项目界面,也就是【解决方案资源管理器】,可以从左下角直接返回,可以看到自己刚刚创建的项目。在这里插入图片描述  右击【源文件】->【添加】->【现有项】->选择OpenCV示例程序“edge.cpp”加载到项目中(当然也可以创建新的项复制粘贴,这样可以保证原示例程序不受影响)。
在这里插入图片描述
  “edge.cpp”是Canny边缘检测示例程序,该程序会生成两种不同算法的边缘提取UI界面,每个界面上方都有一个滑动条,通过拖动滑动条可实现不同条件的边缘提取结果。将源代码文件“edge.cpp”加载到项目中后,可以看到
有一个help()函数,OpenCV示例程序中几乎都含有此函数,下面是“edge.cpp”中的help()函数。

static void help(const char** argv)
{
    printf("\nThis sample demonstrates Canny edge detection\n"
           "Call:\n"
           "    %s [image_name -- Default is fruits.jpg]\n\n", argv[0]);
}

  help()函数说明了该示例程序的功能是演示Canny算子边缘检测,调用时需要传入图像参数,默认传入“fruits.jpg”图片文件,但是默认情况下是无法找到“fruits.jpg”文件的,因为“fruits.jpg”图片路径是相对于OpenCV安装目录,不是工程目录。“fruits.jpg”图片文件在OpenCV安装路径“…\OpenCV\sources\samples\data”中。如果直接执行该程序会报异常:

0x00007FFD848596C9(位于 OpenCV_test.exe 中)有未经处理的异常: Microsoft C++ 异常: cv::Exception,位于内存位置 0x000000221DBDEBD0 处。

  在main()函数中用到了命令行解析器CommandLineParser parser(argc, argv, keys),如果想传入参数可以修改【属性管理器】->右击“Debug | x64”配置文件->【属性】->【调试】->将图片所在目录复制到【命令参数】中->最后点击【确定】。
在这里插入图片描述
  按【F5】或点击【本地Windows调试器】会出现以下结果。
在这里插入图片描述
  在传入图片参数时也可以在mian函数中直接传入图片所在路径“…/OpenCV/sources/samples/data/fruits.jpg”,文件具体路径需要根据自己安装OpenCV的路径进行修改。添加路径时要将“\”改成“\”或者“/”,因为转义字符有歧义。

 image = imread("D:/vscode/OpenCV/sources/samples/data/fruits.jpg", IMREAD_COLOR);

2.2K聚类示例kmeans.cpp

  用同样的方式将“…\OpenCV\sources\samples\cpp”中的【现有项】“kmeans.cpp”添到项目中。kmeans示例是利用可视化的界面实现K聚类算法,通过随机生成一些散点(生成随机点的过程是伪随机过程,即用给定种子可以形成相同的随机序列,可以更好地观察聚类效果),利用K聚类算法将散点判定为不同的群体,并确定每个群体的中心点位置。同样的观察“kmeans.cpp”中的help()函数:

 static void help()
 {
     cout << "\nthis program demonstrates kmeans clustering.\n"
             "it generates an image with random points, then assigns a random number of cluster\n"
             "centers and uses kmeans to move those cluster centers to their representitive location\n"
             "call\n"
             "./kmeans\n" << endl;
 }

  上面的help()函数除了介绍程序的功能外,"./kmeans\n"也说明该程序运行不需要额外的参数输入,直接运行程序即可得到结果。运行结果除了随机点的分类结果以外,还给出了这些随机点的紧凑系数,按【空格】键会再次生成随机点并完成分类,直到按【Q】键退出程序。按4次【空格】键运行的结果如下所(在窗口中报了很多加载动态库的信息,解决方法也是众说纷纭,归根到底就是不影响正常使用):
在这里插入图片描述
  由于是随机生成的点,虽然自己哪次生成的都一样,但是人与人之间有所差别。如果与以上结果不同,不要奇怪。

2.3二维码识别示例qrcode.cpp

  二维码识别示例“qrcode.cpp”在文件夹“…\OpenCV\sources\samples\cpp”中,这个源文件没有help()函数,但是在文件开始说明了程序的使用方法。

    const string keys =
        "{h help ? |        | print help messages }"
        "{i in     |        | input image path (also switches to image detection mode) }"
        "{detect   | false  | detect QR code only (skip decoding) }"
        "{m multi  |        | use detect for multiple qr-codes }"
        "{o out    | qr_code.png | path to result file }"
        "{save_detections | false  | save all QR detections (video mode only) }"
        "{save_all | false  | save all processed frames  (video mode only) }"
    ;
    CommandLineParser cmd_parser(argc, argv, keys);

    cmd_parser.about("This program detects the QR-codes from camera or images using the OpenCV library.");

这段代码表明程序可以识别摄像头拍到的或者图片中的二维码。
输入“h”,显示帮助信息;
当输入“i”这个参数时,后面需要加上图片路径,便识别图片中的二维码,否则自动切换到摄像头识别二维码模式。

在这里插入图片描述
  随便使用一张二维码,用摄像头对准二维码,会出现解码信息。为了方便观察,我在检测到了图像并解码打印完信息后,加了一句system("pause"),在输出窗口会显示“按任意键继续…”。如果你的二维码信息中包含中文可能会乱码.

2.4相机使用示例videocapture_starter.cpp

  “videocapture_starter.cpp”示例程序在“…\OpenCV\sources\samples\cpp”中,用于获取摄像头拍摄的实时图像的某一帧,按【空格】键进行保存图片。还可加载视频文件,截取视频中的某一帧图像以图片形式保存。在保存完图片后,还可将图片以视频形式进行展示。将该示例程序添加到项目中后,直接运行会发现出现以下问题:

“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\ntdll.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\kernel32.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\KernelBase.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\ucrtbased.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\msvcp140d.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\vcruntime140d.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“D:\vscode\OpenCV\build\x64\vc16\bin\opencv_world470d.dll”。已加载符号。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\gdi32.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\gdi32full.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\msvcp_win.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\ucrtbase.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\user32.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\win32u.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\ole32.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\combase.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\rpcrt4.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\bcryptprimitives.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\advapi32.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\msvcrt.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\sechost.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\ws2_32.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\oleaut32.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\comdlg32.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\SHCore.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\shlwapi.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\shell32.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\cfgmgr32.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_5.82.17763.1577_none_6d08746659f7cfc5\comctl32.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\windows.storage.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\profapi.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\powrprof.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\kernel.appcore.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\cryptsp.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\mfplat.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\concrt140d.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\mf.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\mfreadwrite.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\vcruntime140_1d.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\mfcore.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\crypt32.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\msasn1.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\bcrypt.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\ksuser.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\cryptbase.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\imm32.dll”。无法查找或打开 PDB 文件。
“OpenCV_test.exe”(Win32): 已加载“C:\Windows\System32\RTWorkQ.dll”。无法查找或打开 PDB 文件。

  解决此问题的方法是【工具】->【选项】->【调试】->【常规】->勾选【启用源服务器支持】;【工具】->【选项】->【调试】->【符号】->勾选【Microsoft符号服务器】,就会解决以上问题。第一次运行较慢,耐心等待就好。经过以上操作,程序还是会自动退出,是因为【命令参数】不能为空,请继续往下看。

help()函数中有如下介绍:

    void help(char** av) {
        cout << "The program captures frames from a video file, image sequence (01.jpg, 02.jpg ... 10.jpg) or camera connected to your computer." << endl
             << "Usage:\n" << av[0] << " <video file, image sequence or device number>" << endl
             << "q,Q,esc -- quit" << endl
             << "space   -- save frame" << endl << endl
             << "\tTo capture from a camera pass the device number. To find the device number, try ls /dev/video*" << endl
             << "\texample: " << av[0] << " 0" << endl
             << "\tYou may also pass a video file instead of a device number" << endl
             << "\texample: " << av[0] << " video.avi" << endl
             << "\tYou can also pass the path to an image sequence and OpenCV will treat the sequence just like a video." << endl
             << "\texample: " << av[0] << " right%%02d.jpg" << endl;
    }

以上代码介绍了3种功能:
1.使用摄像头模式:由于计算机可能安装了多个摄像头,因此使用摄像头时要输入摄像头的编号,默认情况安装的第一个摄像头编号为0。执行程序时默认使用该模式。在【调试】->【OpenCV_test属性…】->【调试】->【命令参数】中,需要至少传入一个字符,如果不为视频或图片序列,则默认打开摄像头,按【空格】键进行保存图像,按【q】或【Q】或【Esc】键进行退出。图像保存到相对于项目文件夹下“…\OpenCV_test\OpenCV_test”,需要根据自己创建的项目文件夹所在路径进行寻找
在这里插入图片描述
生成的图片如下所示:
在这里插入图片描述
2.读取视频模式:该模式要求输入需要读取视频的名称(将视频放在路径“…\OpenCV_test\OpenCV_test”下,可以直接传入名字,需要根据自己项目路径情况进行修改)。在【调试】->【OpenCV_test属性…】->【调试】->【命令参数】->输入视频名称。视频随便找的,不要误会哈。
在这里插入图片描述

3.将序列图像生成类似视频模式:该模式要求输入一系列图片,这些图片需要保存在同一路径下,并且命名符合“前缀+数字+文件格式”的形式。在调用时使用“前缀%3d+文件格式”的形式(由于程序默认保存为filename%3d.jpg,所以应该是filename%3d.jpg输入到命令参数)输入到【调试】->【OpenCV_test属性…】->【调试】->【命令参数】中。但是你会发现,程序并没有打开你保存的图片,而是打开了默认的摄像头,这是因为在命令行中百分号%为特殊字符,使用时需要将其进行转义,否则会乱码。这里将“%”转换成ASCII表中的十六进制编码进行输入(百分号“%”在ASCII表中为0x25,所以为%25,相应的,如果为空格“ ”其ASCII码为0x20,则为%20),输入“filename%2503d.jpg”即可成功运行。由于运行速度较快,可以imshow()函数后加入system("pause")或延时。在这里插入图片描述

2.5视频物体跟踪示例camshiftdemo.cpp

  “camshiftdemo.cpp”示例程序也在“…\OpenCV\sources\samples\cpp”中,该示例程序利用摄像头跟踪选定物体。程序通过启动摄像头拍摄数据,在图片的显示界面中通过鼠标选择跟踪区域,实现对选择区域中物体的跟踪,并且会生成选中区域的直方图。
其中help()函数如下所示:

static void help(const char** argv)
{
    cout << "\nThis is a demo that shows mean-shift based tracking\n"
            "You select a color objects such as your face and it tracks it.\n"
            "This reads from video camera (0 by default, or the camera number the user enters\n"
            "Usage: \n\t";
    cout << argv[0] << " [camera number]\n";
    cout << hot_keys;
}

  以上代码说明程序在运行时用户输入摄像头序号可以启用该序号摄像头进行拍摄,如果不输入任何参数,则默认启动需要为0的摄像头。这里直接运行程序,在选取目标时,推荐选取物体颜色较为突出的区域。这里我选择棕色的杯子 ,并不需要全部选出,选出物体上较为突出的颜色即可。第一张图为选取的区域,后面是物体跟踪的效果。
在这里插入图片描述

;