人脸识别示例代码解析(一)——程序参数解析

上一篇我们下载安装了opencv,并且运行了第一个示例程序。接下来,我们剖析下该示例程序。

一、 示例代码来源
上一篇指出,opencv下载并解压后,目录下会产生两个目录

在这里插入图片描述

其中,”build”目录主要包含了我们程序开发和运行时所需要的头文件(.h)和库文件(.lib/.dll)。

”source”目录下,包含了项目源码、示例源码、编译相关的数据和文档。

其中”sample”目录中,提供了一定的示例的代码。

在这里插入图片描述

我们上一篇所运行的程序示例,就是这个”samples”目录下的facedetect.cpp。

该示例程序用于打开默认摄像头,捕捉图像,定位人脸,以及双眼部位。

二、 修改opencv头文件
*
如果想正常运行该程序,还需要做些修改

在这里插入图片描述

如上图所示,源文件中,需要包含一大堆的头文件,在新版的opencv中,只需包含”opencv.hpp”就可以了,原因很简单,这个头文件直接或间接包含了上述所使用到的头文件。

事实上,新版的opencv只提供了这一个头文件,所以几乎所有的opencv开发,都只需包含这一个头文件——“<opencv2/opencv.hpp>”。

在这里插入图片描述

注意:第三行加入了一句“#define _CRT_SECURE_NO_WARNINGS”,用于消除一些过期函数的错误提示。否则,会因为一些诸如“fopen”等函数报错而无法通过编译。

三、 使用opencv域名

在这里插入图片描述

使用域名很简单,就是如果你不想每次调用opencv相关函数时,都要在前面加上”cv::”,那么就把上述域名使用的声明添加上去。

四、 构造主函数,确定该程序运行时所需要的参数

程序看起来很复杂。实际上就是从程序入口“main”函数,传入一些参数,然后程序根据这些参数,确定“人脸模板”和“眼部模板”的位置,用于定位视频图像中的人脸和眼部。
所以,这个main函数,从一开始,就声明,需要传入的参数。

在这里插入图片描述

接下来,在主函数之前声明两个全局变量,字符串类型,用来接收和在函数间传递“人脸模板”路径,“眼部模板”路径。

在这里插入图片描述

最后,在主程序内部。解析参数,获取两个变量的值

在这里插入图片描述

这里用到一个重要的类,命令行解析
类:cv::CommandLineParser(这里”cv::”可省去)

(一)构造该类对象parser

在这里插入图片描述

  1. 需要传递从main中获取的argv,argc,并待后续从中提取各个“参数—值”的键值对。

  2. 需要传递参数列表及其默认值。参数列表决定了,我们从argv中需要包含哪些参数信息(比如该程序需要参数“help”,“cascade”,“nested-cascade”,“scale)。

  3. 另外在argv中解析不到相应参数时(比如用户没有输入’cascade”参数值)时,默认参数值(比如“data/haarcascades/haarcascade_frontalface_alt.xml”)来代替。

(二)利用parser对象解析参数

  1. 在解析参数之前,我们应首先判断一下用户是否是需要调用帮助文档,如果是,那么并不真正执行程序,而是显示帮助文档内容,因此并不需要再往下解析参数

在这里插入图片描述

  1. parser对象的get函数,传入参数名,返回参数值。

在这里插入图片描述

  1. 继续解析,利用parser的check函数检查有无丢失参数等错误。

在这里插入图片描述

五、最后今天就解析这里,在此可以把本篇代码简化为以下

编译后,在命令行中运行该程序,可以检测参数的输入与解析

// face1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void detectAndDraw(Mat& img, CascadeClassifier& cascade,
    CascadeClassifier& nestedCascade,
    double scale, bool tryflip);

string cascadeName;
string nestedCascadeName;

int main(int argc, const char** argv)
{
    string inputName;
    bool tryflip;
    double scale;

 CommandLineParser parser(argc, argv,
        "{help h||}"
        "{cascade|data/haarcascades/haarcascade_frontalface_alt.xml|}"
        "{nested-cascade|data/haarcascades/smile.xml|}"
        "{scale|1|}{try-flip||}{@filename||}"
    );
    if (parser.has("help"))
    {
        return 0;
    }
    cascadeName = parser.get<string>("cascade");
    nestedCascadeName = parser.get<string>("nested-cascade");
    scale = parser.get<double>("scale");
    if (scale < 1)
        scale = 1;
    tryflip = parser.has("try-flip");
    inputName = parser.get<string>("@filename");
    if (!parser.check())
    {
        parser.printErrors();
        return 0;
    }
    cout << "该程序接收参数如下:" << endl;
    cout << "cascadeName:" << cascadeName << endl;
    cout << "nestedCascadeName:" << nestedCascadeName << endl;
    cout << "scale:" << scale << endl;
    cout << "tryflip:" << tryflip << endl;
    cout << "inputName:" << inputName << endl;
    return 0;
}


没有输入参数情况下

在这里插入图片描述

用户指定inputName情况下

在这里插入图片描述

六:练习,大家可以修改此代码,试图在用户输入参数“-h”时显示帮助文档。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>