在CentOS7下的OpenCV环境搭建与基于C++的人脸辨认(Face Recognition)参考指南

1 篇文章 0 订阅
1 篇文章 0 订阅

本文分为两个部分,一个是OpenCV的搭建,一个是人脸识别程序的

----强烈推荐浏览完全文再进行操作----

OpenCV搭建

文档上说,有两种安装方式,第一种是只安装核心模组(Build core modules),另一种是外加opencv_contrib模组。

在第一开始做该项目时,在编译我的C++程序时发现face.hpp的头文件不存在,于是去目录/usr/local/include寻找,执行ls -al | grep face命令后,确实没有face.hpp,于是经查之后才发现,face.hpp等一系列额外头文件,是存在于opencv_contrib模组中,于是又重新进行了cmake、build、make、make install。

所以,在计算机存储充足、部署时间相对宽裕的情况下,推荐进行全安装。

首先,官方的内容是比较简略的,步骤可以总结为:

  • 确保安装且为最新版的cmake,g++,wget,unzip
  • 利用wget命令来下载源码文件
  • 利用unzip命令来解压文件
  • 创建一个build文件夹用于编译源文件
  • 进行cmake配置
  • 进行cmakebuild (或者直接make)
  • 进行make install

注意,CentOS7安装的gcc(g++)版本为4.8.5,它不支持利用参数-std=c++17,而且不含有filesystem(experimental/filesystem也没有)库。如果你并不需要一些相关库的话,也许gcc 4.*可以满足需求。

为了取代掉CentOS7中老旧的4.*版本,而更换为8.*,我们需要执行(参考地址:https://stackoverflow.com/questions/55345373/how-to-install-gcc-g-8-on-centos):

# 卸载gcc(版本4.*,如果你有的话)
yum -y remove gcc

# 确保有软件集仓库
yum -y install centos-release-scl

# 安装gcc 8和其相关的C++编译器
yum -y install devtoolset-8-gcc devtoolset-8-gcc-c++

# 将安装的gcc写入环境变量,可以直接在命令行窗口执行gcc命令
source scl_source enable devtoolset-8

将内容写入用户目录下的.bash_profile文件,下次用当前用户(如root)登录时可以直接不用source而执行gcc或者g++

vi ~/.bash_profile

在最后一行写入:

source scl_source enable devtoolset-8

于是,除开下载gcc,大致的流程如下代码块

# 安装(ubuntu就用sudo apt update && sudo apt install)
sudo yum install -y cmake wget unzip

# 下载并解压源代码
wget -O opencv.zip https://github.com/opencv/opencv/archive/4.x.zip
wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.x.zip
unzip opencv.zip
unzip opencv_contrib.zip

# 创建并进入build目录
mkdir -p build && cd build

# 对cmake进行参数配置
# cmake的配置有很多,这里比较重要,下面详细说
cmake -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib-4.x/modules -DOPENCV_GENERATE_PKGCONFIG=ON ../opencv-4.x 

# 进行build 
# 与 make -j4 的功能相同
cmake --build .

# 进行安装
sudo make install

官方文档对于安装的定义是这样的:

The installation process only copies files to predefined locations and does minor patching. Installing using this method does not integrate opencv into the system package registry and thus, for example, opencv can not be uninstalled automatically. We do not recommend system-wide installation to regular users due to possible conflicts with system packages.

也就是说,make install的这个安装过程仅将文件复制到预定义的位置并进行少量修补。 使用此方法安装不会将opencv写入系统注册表中,所以说,opencv无法自动卸载(通过一种命令,如remove opencv之类的)。由于可能与系统包发生冲突,我们不建议普通用户(非root)进行系统范围的安装。

对于cmake的参数-D可以在如下官方文档链接中看到:
https://cmake.org/cmake/help/latest/manual/ccmake.1.html?highlight=d#cmdoption-ccmake-D

对于

  • -DOPENCV_EXTRA_MODULES_PATH=<path>
    这个是额外模组的路径,也就是opencv_contrib的模组的路径

  • -DBUILD_EXAMPLES=ON
    官方这样描述:If you also want to build the samples from the “samples” folder of each module, also include the “-DBUILD_EXAMPLES=ON” option.
    这个是是否创建实例文件,可能与一些文件有关,比如说OpenCV官方文档的一个教程Getting Started with Images,其中有个文件叫“starry_night.jpg”,是不是和这个参数有关,因为在我cmake配置参数的时候我并没有使用这个参数,所以我不太清楚。

  • -DOPENCV_GENERATE_PKGCONFIG=ON

    这个是生成pkg-config的命令,默认是不生成的(OFF),如果生成的话,会存在于?,这里会有一个文件opencv4.pc(因为我第一开始安装时候没有使用这个参数命令)。
    之后就可以使用如下命令:

    # 查看opencv4的版本信息
    pkg-config --modversion opencv4
    
    # 查看opencv4的链接的lib库
    pkg-config --libs opencv4
    

    如果我们不使用这个参数命令,那么可以自行创建一个(参考文章

    cd /usr/local/lib
    sudo mkdir pkgconfig && cd pkgconfig
    sudo vi opencv.pc
    

    opencv.pc的内容为

    prefix=/usr/local
    exec_prefix=${prefix}
    includedir=/usr/local/include/opencv4
    libdir=/usr/local/lib
     
    Name: OpenCV
    Description: Open Source Computer Vision Library
    Version: 4.*
    Libs: -L${exec_prefix}/lib -lopencv_core -lopencv_flann -lopencv_imgproc -lopencv_ml -lopencv_photo -lopencv_dnn -lopencv_features2d -lopencv_imgcodecs -lopencv_videoio -lopencv_calib3d -lopencv_highgui -lopencv_objdetect -lopencv_stitching -lopencv_video -lopencv_intensity_transform -lopencv_phase_unwrapping -lopencv_plot -lopencv_quality -lopencv_surface_matching -lopencv_xphoto -lopencv_dnn_superres -lopencv_fuzzy -lopencv_hfs -lopencv_img_hash -lopencv_line_descriptor -lopencv_saliency -lopencv_text -lopencv_barcode -lopencv_mcc -lopencv_rapid -lopencv_rgbd -lopencv_shape -lopencv_structured_light -lopencv_videostab -lopencv_wechat_qrcode -lopencv_xfeatures2d -lopencv_ximgproc -lopencv_xobjdetect -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_dpm -lopencv_face -lopencv_gapi -lopencv_optflow -lopencv_superres -lopencv_tracking -lopencv_stereo
    Libs.private: -ldl -lm -lpthread -lrt
    Cflags: -I${includedir}
    

    将如下内容写入~/.bash_profile最后一行:

    export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH
    

    再执行指令来将其添加入环境变量

    source ~/.bash_profile
    

    此外,对于opencv.pc这个文件,倒数第三行的Libs可能会因为配置的不同而不同
    我的解决方案是用一段shell脚本来查找Libs的-l参数的值,创建一个shell脚本并给他执行权限

    vim findLibs.sh
    chmod 777 ./findLibs.sh
    

    shell脚本findLibs的内容为:

    #!/bin/bash
    
    str=/usr/local/include/opencv4/opencv2/
    # 绝对路径的前缀长度
    prefixSize=${#str}
    
    # 对文件名进行截取处理
    find $str -maxdepth 1 -name "*.hpp" | while read line; do
        printf "-"
        printf "lopencv_${line:$prefixSize:-4} "
    done
    
    printf "\n"
    

    随后,执行shell程序:

    ./findLibs.sh
    

    可以得到需要添加的参数:
    在这里插入图片描述
    直接将上面的内容复制并替换掉Libs中的部分内容即可

    需要注意的是,这种方法得到的链接库有可能不全或者本机上根本没有此库,比如说如果直接将上述内容写入到opencv.pc中,并将其添加入环境变量,我们在最终编译程序代码的时候,有可能出现错误:

    /opt/rh/devtoolset-8/root/usr/libexec/gcc/x86_64-redhat-linux/8/ld: cannot find -lopencv_opencv
    /opt/rh/devtoolset-8/root/usr/libexec/gcc/x86_64-redhat-linux/8/ld: cannot find -lopencv_opencv_modules
    /opt/rh/devtoolset-8/root/usr/libexec/gcc/x86_64-redhat-linux/8/ld: cannot find -lopencv_core_detect
    

    这样的话就需要在opencv.pc这个文本文件中的Libs参数中中找出这些并且将其删除。

    还有一个更好的,用readelf -d <filePrefix>命令来查看需要的.so共享库:

    [root@hello faceE]# ls -al
    total 460
    drwxr-xr-x  4 root root     67 Dec 30 07:56 .
    drwxr-xr-x 11 root root    231 Jan  1 17:39 ..
    -rwxr-xr-x  1 root root 464648 Dec 30 07:56 face
    -rw-r--r--  1 root root   4084 Dec 30 07:54 face.cpp
    drwxr-xr-x  2 root root    287 Dec 30 07:55 testsets
    drwxr-xr-x  8 root root    118 Dec 30 07:55 trainsets
    
    [root@hello faceE]# readelf -d face
    
    Dynamic section at offset 0x51a78 contains 70 entries:
      Tag        Type                         Name/Value
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_superres.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_videostab.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_aruco.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_bgsegm.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_bioinspired.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_ccalib.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_dnn_objdetect.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_dpm.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_face.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_photo.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_fuzzy.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_hfs.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_img_hash.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_line_descriptor.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_optflow.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_reg.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_rgbd.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_saliency.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_stereo.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_structured_light.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_phase_unwrapping.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_surface_matching.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_tracking.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_datasets.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_text.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_dnn.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_plot.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_xfeatures2d.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_shape.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_video.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_ml.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_ximgproc.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_calib3d.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_features2d.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_highgui.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_videoio.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_flann.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_xobjdetect.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_imgcodecs.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_objdetect.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_xphoto.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_imgproc.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libopencv_core.so.407]
     0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
     0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
     0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
     0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
     0x000000000000000c (INIT)               0x4055d8
     0x000000000000000d (FINI)               0x440a44
     0x0000000000000019 (INIT_ARRAY)         0x651038
     0x000000000000001b (INIT_ARRAYSZ)       24 (bytes)
     0x000000000000001a (FINI_ARRAY)         0x651050
     0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
     0x000000006ffffef5 (GNU_HASH)           0x400298
     0x0000000000000005 (STRTAB)             0x401ea0
     0x0000000000000006 (SYMTAB)             0x400640
     0x000000000000000a (STRSZ)              8197 (bytes)
     0x000000000000000b (SYMENT)             24 (bytes)
     0x0000000000000015 (DEBUG)              0x0
     0x0000000000000003 (PLTGOT)             0x652000
     0x0000000000000002 (PLTRELSZ)           3024 (bytes)
     0x0000000000000014 (PLTREL)             RELA
     0x0000000000000017 (JMPREL)             0x404a08
     0x0000000000000007 (RELA)               0x404180
     0x0000000000000008 (RELASZ)             2184 (bytes)
     0x0000000000000009 (RELAENT)            24 (bytes)
     0x000000006ffffffe (VERNEED)            0x4040b0
     0x000000006fffffff (VERNEEDNUM)         3
     0x000000006ffffff0 (VERSYM)             0x403ea6
     0x0000000000000000 (NULL)               0x0
    

在安装环节结束后,官方文档提示我们说,默认的OpenCV安装路径是/usr/local目录

By default OpenCV will be installed to the /usr/local directory, all files will be copied to following locations:

  • /usr/local/bin - executable files(可执行文件)

  • /usr/local/lib - libraries (.so) (共享库,但是我的存放地为/usr/local/lib64

    这有可能会导致程序执行错误:
    在这里插入图片描述
    我在网站https://github.com/cggos/ccv/issues/1找到了解决方案:
    我执行这样的命令:

    sudo find / -name "libopencv_stitching.so.407*"
    

    输出的结果:

    /root/cvTest/build/lib/libopencv_stitching.so.407
    /usr/local/lib64/libopencv_stitching.so.407
    

    于是我找到了我的共享链接库存放到了/usr/local/lib64里,
    创建文件/etc/ld.so.conf.d/opencv.conf,并将上面得到的/usr/local/lib64写入opencv.conf文件中,最后执行命令:

    sudo ldconfig -v
    

    即可解决问题。
    我认为,还有一种解决方案,就是把opencv.pc里面的Libs条例中的-L${exec_prefix}/lib改为-L${exec_prefix}/lib64,这可能与操作系统有关,不同的操作系统需要配置的opencv.pc不一定一样,所以还是推荐在cmake设置参数的时候就让程序自动生成opencv4.pc,这样能省去很多麻烦。

    (ps. 如果有朋友想知道.so,.a,.dll之类文件的区别可以去看https://stackoverflow.com/questions/9688200/difference-between-shared-objects-so-static-libraries-a-and-dlls-so)

  • /usr/local/cmake/opencv4 - cmake package (cmake包,这个我没有,可能与我cmake的安装目录有关)

  • /usr/local/include/opencv4 - headers (c语言头文件)

  • /usr/local/share/opencv4 - other files (e.g. trained cascades in XML format) (其他文件,如训练好的模型文件,位于/usr/local/share/opencv4/haarcascades

cmake 配置完成截图:

在这里插入图片描述

cmake build完成截图

在这里插入图片描述

make install成功截图

在这里插入图片描述

基于C++的人脸辨认(Face Recognition)

该项目是参考于大佬的博客https://anothertechs.com/programming/cpp/opencv/opencv-creating-own-dataset-cpp/

由于我是用非图形化界面的CentOS7来进行人脸辨认实验的,所以没法在虚拟机中展示图片,我们只能以文本结果的形式来判断正误。

我们首先要分析一下程序的功能。我们想要实现一个能够从训练集进行训练,从而在测试集中判断测试图片是谁的脸。

此次数据集,我们采用吴京、孙国帅(昊京)、张维为、谷爱凌的照片作为数据库。

下面是训练集./train的目录结构

train/
	wujing_0/
		img1
		img2
		img3

	sunguoshuai_1/
		img1
		img2
		img3

	zhangweiwei_2/
		img1
		img2
		img3

	guailing_3/
		img1
		img2
		img3

测试集图片如下:
(以下图片均来自于百度图片,侵删)

  • 谷爱凌
    在这里插入图片描述
  • 孙国帅
    在这里插入图片描述
  • 吴京
    在这里插入图片描述
  • 张维为
    在这里插入图片描述

测试集./test图片就是全是图片:
在这里插入图片描述

那么我们来分析一下代码:

  • 从图片中提取人脸数据

    cv::CascadeClassifier classifier;
    int extractfaces(cv::Mat &img, cv::Mat &face) {
      cv::Mat img_gray;
      cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);
      std::vector<cv::Rect> features;
      classifier.detectMultiScale(img, features);
    
      /* 假设每一张图片只有一张脸 */
      if (features.size() > 0) {
        face = img_gray(features[0]);
        return 1;
      } else
        return 0;
    }
    
  • 训练识别器
    从图像中提取人脸后,需要训练这些图像。而OpenCV中有一种称为局部二进制模式直方图 (LBPH) 的人脸识别算法(它闻名于从正面和侧面识别人脸的强大能力)。

    cv::Ptr<cv::face::LBPHFaceRecognizer> model =
        cv::face::LBPHFaceRecognizer::create();
       
    void train_dataset(const std::string &in_dir) {
      std::cout << "开始训练数据集......\n";
    
      std::vector<int> faceIds;
      std::vector<cv::Mat> faceSamples;
    
      for (const auto &file : std::filesystem::directory_iterator(in_dir)) {
        std::string label = file.path().filename();
        std::cout << "正在处理图像,其位于路径: " << label << "...\n";
    
        /*目录格式: 文件名_0, 文件名_1, 文件名_2, ... */
        int faceID = std::stoi(label.substr(label.rfind("_") + 1, label.size()));
    
        for (const auto &f : std::filesystem::directory_iterator(file.path())) {
          cv::Mat src, face;
          std::cout << f << "\n";
          src = cv::imread(f.path());
          if (extractfaces(src, face)) {
            faceSamples.emplace_back(face);
            faceIds.emplace_back(faceID);
          }
        }
        model->train(faceSamples, faceIds);
        std::cout << "完成!!\n";
      }
    
      std::cout << "已结束训练集训练!! \n" ;
    }
    
  • 人脸辨认
    在分类器 (LBPH) 训练了足够多的图像之后,就该测试我们的模型了。

    为此,只需创建一个测试目录并放入要测试的图像。 在测试阶段,我们将再次从测试图像中提取人脸,然后将其提供给我们的模型进行预测。

    void test_dataset(const std::string &in_dir) {
      std::cout << "测试数据中...... \n";
      // 以在训练集中的出现方式来对姓名进行排序
    
      const std::vector<std::string> names = {
        "吴京", "孙国帅", "张维为", "谷爱凌"}; 
    
      for (const auto &file : std::filesystem::directory_iterator(in_dir)) {
        cv::Mat src = cv::imread(file.path());
        // std::cout << "reading test file " << file.path() << "\n";
        cv::Mat face;
        extractfaces(src, face);
        int predictedLabel = -1;
        double confidence = 0.0;
        // std::cout << "正在预测... \n" ;
        model->predict(face, predictedLabel, confidence);
    
        std::cout << "文件: " << file.path().filename();
        std::cout << "\n预测姓名为: " << names[predictedLabel]
              	  << "\n置信值: " << confidence << "\n------------------\n";
      }
    }
    
  • 程序入口

    int main(int argc, char **argv) {
      if (argc < 3) {
        std::cout << "!!! 错误 !!!\n";
        std::cout << "你应该以如下方式来执行程序\n";
        std::cout << "<Program> <DatasetFolder> <Test Folder>\n";
        return -1;
      }
    
      std::cout << "正在读取人脸识别模型文件 ......\n";
      assert(classifier.load("/usr/local/share/opencv4/haarcascades/haarcascade_frontalface_alt.xml"));
      std::cout << "完成!!\n";
    
      // 训练集文件夹argv[1]
      train_dataset(argv[1]);
    
      // 测试集文件夹argv[2]
      test_dataset(argv[2]);
    
      return 0;
    }
    

所有的代码被整合到face.cpp中:

// 导入库
#include "opencv2/face.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <cassert>
#include <filesystem>
#include <iostream>
#include <vector>

cv::CascadeClassifier classifier;
cv::Ptr<cv::face::LBPHFaceRecognizer> model =
    cv::face::LBPHFaceRecognizer::create();

// 从图像中提取人脸
int extractfaces(cv::Mat &img, cv::Mat &face) {
  cv::Mat img_gray;
  cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);
  std::vector<cv::Rect> features;
  classifier.detectMultiScale(img, features);
  // std::cout << "提取人脸中......\n";

  /* 假设每一张图片只有一张脸 */
  if (features.size() > 0) {
    face = img_gray(features[0]);
    return 1;
  } else
    return 0;
}

// 训练集
void train_dataset(const std::string &in_dir) {
  std::cout << "开始训练数据集......\n";

  std::vector<int> faceIds;
  std::vector<cv::Mat> faceSamples;

  for (const auto &file : std::filesystem::directory_iterator(in_dir)) {
    std::string label = file.path().filename();
    std::cout << "正在处理图像,其位于路径: " << label << "...\n";

    /*目录格式: 文件名_0, 文件名_1, 文件名_2, ... */
    int faceID = std::stoi(label.substr(label.rfind("_") + 1, label.size()));

    for (const auto &f : std::filesystem::directory_iterator(file.path())) {
      cv::Mat src, face;
      std::cout << f << "\n";
      src = cv::imread(f.path());
      if (extractfaces(src, face)) {
        faceSamples.emplace_back(face);
        faceIds.emplace_back(faceID);
      }
    }
    model->train(faceSamples, faceIds);
    std::cout << "完成!!\n";
  }

  std::cout << "已结束训练集训练!! \n" ;
}

void test_dataset(const std::string &in_dir) {
  std::cout << "测试数据中...... \n";
  // 以在训练集中的出现方式来对姓名进行排序

  const std::vector<std::string> names = {
    "吴京", "孙国帅", "张维为", "谷爱凌"}; 

  for (const auto &file : std::filesystem::directory_iterator(in_dir)) {
    cv::Mat src = cv::imread(file.path());
    // std::cout << "reading test file " << file.path() << "\n";
    cv::Mat face;
    extractfaces(src, face);
    int predictedLabel = -1;
    double confidence = 0.0;
    // std::cout << "正在预测... \n" ;
    model->predict(face, predictedLabel, confidence);

    std::cout << "文件: " << file.path().filename();
    std::cout << "\n预测姓名为: " << names[predictedLabel]
          << "\n置信值: " << confidence << "\n------------------\n";
  }
}

int main(int argc, char **argv) {
  if (argc < 3) {
    std::cout << "!!! 错误 !!!\n";
    std::cout << "你应该以如下方式来执行程序\n";
    std::cout << "<Program> <DatasetFolder> <Test Folder>\n";
    return -1;
  }

  std::cout << "正在读取人脸识别模型文件 ......\n";
  assert(classifier.load("/usr/local/share/opencv4/haarcascades/haarcascade_frontalface_alt.xml"));
  std::cout << "完成!!\n";

  // 训练集文件夹argv[1]
  train_dataset(argv[1]);

  // 测试集文件夹argv[2]
  test_dataset(argv[2]);

  return 0;
}

因为程序引用了filesystem库,所以需要使用-std=c++17这个c++17标准以及参数-lstdc++fs,不然会出现种种错误(可以自行尝试)

g++ -std=c++17 face.cpp -o face `pkg-config --cflags --libs opencv` -lstdc++fs

在编译成功后,我们当前目录下就有了可执行文件face,所以接下来我们执行命令

./face train test 

在这里,对应到c++代码的主入口里,argv[0]./faceargv[1]trainargv[2]test

即可执行该程序,并获得结果:

[root@hello faceCSDN]# g++ -std=c++17 face.cpp -o face `pkg-config --cflags --libs opencv` -lstdc++fs
[root@hello faceCSDN]# ./face train test
正在读取人脸识别模型文件 ......
完成!!
开始训练数据集......
正在处理图像,其位于路径: guailing_3...
"train/guailing_3/1265683b1cd8a7bb886837d8a5ea520f.jpeg"
"train/guailing_3/24d57c1ff47570fe87c211b533cab14c.jpeg"
"train/guailing_3/40d5f1426f7c3f2221cc6c05f7f61adf.jpg"
"train/guailing_3/dbafef5bf89dc44c1b67042f7097330f.jpeg"
"train/guailing_3/e3242bea4627a51d5344c4e1e100f2e4.jpeg"
完成!!
正在处理图像,其位于路径: sunguoshuai_1...
"train/sunguoshuai_1/09fa572ec760999b2354831a4837ce3a.jpeg"
"train/sunguoshuai_1/312a15aa42e1504c4516e0042981852d.jpeg"
"train/sunguoshuai_1/a583e59451b9d1f3c0f7a456b8529f5d.jpeg"
"train/sunguoshuai_1/defa15f270753adc013f285490e12109.jpeg"
"train/sunguoshuai_1/sgs1.png"
完成!!
正在处理图像,其位于路径: wujing_0...
"train/wujing_0/a52436085f02ff194a008a328e00c6e1.jpeg"
"train/wujing_0/aa8de99c111287d62a8bec921468e8a2.jpg"
"train/wujing_0/img.jpeg"
"train/wujing_0/img1.jpg"
"train/wujing_0/img2.jpg"
"train/wujing_0/img3.jpg"
完成!!
正在处理图像,其位于路径: zhangweiwei_2...
"train/zhangweiwei_2/294fcd9ea7ba6bf028187adb20734424.jpeg"
"train/zhangweiwei_2/54540598ea85afbf7c780e59b6a6d975.jpeg"
"train/zhangweiwei_2/a4246016cc0fc752708c464d38bd3aa9.jpeg"
"train/zhangweiwei_2/f814bea47bf86e6f9c01429f363620c0.jpeg"
完成!!
已结束训练集训练!! 
测试数据中...... 
文件: "guailing0.jpeg"
预测姓名为: 谷爱凌
置信值: 44.1809
------------------
文件: "sunguoshuai0.png"
预测姓名为: 吴京
置信值: 118.333
------------------
文件: "sunguoshuai1.jpg"
预测姓名为: 吴京
置信值: 86.6067
------------------
文件: "wujing0.jpeg"
预测姓名为: 吴京
置信值: 48.4382
------------------
文件: "wujing1.jpeg"
预测姓名为: 孙国帅
置信值: 71.9883
------------------
文件: "zhangweiwei0.jpeg"
预测姓名为: 张维为
置信值: 71.1699
------------------

从结果上看,孙国帅和吴京确实不太容易区分…

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值