4.5 定义人脸和人脸探测器

4.5 定义人脸和人脸探测器

让我们用纯c++代码定义faces和face detector,不使用任何依赖(OpenCV除外)。这确保了ManyMasks的计算机视觉功能是可移植的。我们可以使用不同的UI库集在不同的平台上重用代码的核心。
脸是有物种区分的。对于我们的情况,可以分为人,猫,或者混合的。让我们创建一个头文件,Species.h,并在其中定义如下枚举:

#ifndef SPECIES_H
 #define SPECIES_H 
 enum Species {
	Human,
	Cat,
	Hybrid
	 };
 #endif // !SPECIES_H

一张脸也有一个图像数据矩阵和三个特征点,代表眼睛的中心和鼻尖。我们可以用以下任何一种方法来构造一张脸:

  • 指定物种、矩阵和特征点。
  • 创建一个带有默认值的空的脸对象,包括一个空矩阵。
  • 复制一张现有的脸。
  • 合并两个现有的脸.
    让我们创建另一个头文件Face.h,并在其中声明Face类的如下公共接口:
#ifndef FACE_H 
#define FACE_H 
#include <opencv2/core.hpp> 
#include "Species.h" 

class Face {
    public:
    Face(Species species, const cv::Mat &mat,const cv::Point2f &leftEyeCenter, const cv::Point2f &rightEyeCenter, const cv::Point2f &noseTip);
    
    /** * Construct an empty face. */
    Face();
    
    /** * Construct a face by copying another face. */
    Face(const Face &other);
    
    /** * Construct a face by merging two other faces. */
    Face(const Face &face0, const Face &face1);
    
    bool isEmpty() const;
    
    Species getSpecies() const;
    
    const cv::Mat &getMat() const; int getWidth() const; int getHeight() const;
    
    const cv::Point2f &getLeftEyeCenter() const;
    const cv::Point2f &getRightEyeCenter() const;
    const cv::Point2f &getNoseTip() const;

注意,Face被设计为不可变类型,这意味着它的属性在构造之后不会改变。为了帮助实现这一点,我们在方法声明的末尾添加了const关键字。使用不可变类型有助于使代码安全、可预测和优雅,因为对象是无状态的(或者更准确地说,其当前状态与初始状态保持相同)。调用者可以分配一个脸的副本(通过复制构造函数),但不能重新排列现有脸的元素。ManyMasks是一款艺术应用,而不是一部黑帮电影;我们构造面,我们不重新排列它们。
Face类的私有接口定义了预期的变量以及帮助融合Face的方法。下面是完成Face.h的相关代码:


private:
    
    void initMergedFace(const Face &biggerFace,const Face &smallerFace);
    Species species;
    cv::Mat mat;
    cv::Point2f leftEyeCenter;
    cv::Point2f rightEyeCenter;
    cv::Point2f noseTip;
    
};
#endif /* Face_hpp */

我们的人脸检测器有级联分类器,用于人脸、左眼和右眼以及猫脸。构造函数接受到相关级联文件的路径作为参数。在它被构造之后,人脸检测器的作用就是简单地检测人脸!检测函数接受场景的当前图像以及向量来填充返回值。可选地,调用者还可以指定检测器应该处理调整大小的图像,并在原始图像上绘制检测结果的可视化标志。可选的可视化标志包括显示检测到的面部、眼睛和鼻子位置的矩形和圆形。让我们创建另一个头文件FaceDetector.h,并在其中为FaceDetector类声明如下公共接口:

#ifndef FACE_DETECTOR_H
#define FACE_DETECTOR_H
#include <opencv2/objdetect.hpp>
#include "Face.hpp"

class FaceDetector {
public:
    FaceDetector(const std::string &humanFaceCascadePath, const std::string &catFaceCascadePath, const std::string &humanLeftEyeCascadePath, const std::string &humanRightEyeCascadePath);
    void detect(cv::Mat &image, std::vector<Face> &faces, double resizeFactor = 1.0, bool draw = false);

私有接口声明了几个变量和辅助方法,以均衡图像(即标准化其对比度)并检测眼睛和鼻子。均衡均衡化有助于保证不同光照条件下检测结果的一致性。下面是完成FaceDetector.h的相关代码:

private:
    void equalize(const cv::Mat &image);
    void detectInnerComponents(const cv::Mat &image,std::vector<Face> &faces, double resizeFactor, bool draw,Species species, cv::Rect faceRect);
    cv::CascadeClassifier humanFaceClassifier;
    cv::CascadeClassifier catFaceClassifier;
    cv::CascadeClassifier humanLeftEyeClassifier;
    cv::CascadeClassifier humanRightEyeClassifier;
    
#ifdef WITH_CLAHE
    cv::Ptr<cv::CLAHE> clahe;
#endif
    
    cv::Mat resizedImage;
    cv::Mat equalizedImage;
};

[注意预处理器条件WITH_CLAHE的使用。如果我们在项目Build Settings|Preprocessor Macros中定义了预处理器宏WITH_CLAHE,我们的人脸检测器将利用一种称为对比度受限自适应直方图均衡化(CLAHE)的高级均衡化算法。否则,它将使用一种更轻量级但不太健壮的均衡算法。]

在本章的后面,在"检测脸部元素的层次结构"和"对齐和混合脸部元素"中,我们将在Face.cpp和FaceDetector.cpp文件中研究值得注意的实现细节。不过,首先让我们考虑使用faces和face detection的视图控制器。

###返回到第四章目录###
###返回到书籍目录###

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值