《Instant-OpenCV-for-iOS》-学习笔记-4

使用级联分类器检测脸部

本文学习如何使用OpenCV的 cv::CascadeClassifier 类检测脸部。我们加载一个经过训练的分类器XML文件,用这个文件识别脸部,并在识别到的脸部上画个方框。

准备

OpenCv自带经过训练的脸部识别分类器XML文件haarcascade_frontalface_alt2.xml。这个文件可以从 https://github.com/Itseez/opencv/tree/master/data/haarcascades获取到。

步骤

  1. 使用《Instant-OpenCV-for-iOS》-学习笔记-3的工程。
  2. 将haarcascade_frontalface_alt2.xml文件拖到xcode的项目侧边栏的Supporting Files目录下。
  3. 修改 ViewController.h文件。加入CascadeClassifier类型变量声明faceDetector。这就是对象检测器。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #import <UIKit/UIKit.h>
    #import <opencv2/opencv.hpp>
    #import <opencv2/imgcodecs/ios.h>

    using namespace cv;

    @interface ViewController : UIViewController{
    CascadeClassifier faceDetector;
    }
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;

    @end
  1. 修改 ViewController.mm中的viewDidLoad 方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //加载haarcascade_frontalface_alt2.xml文件
    NSString * cascadePath =[[NSBundle mainBundle] pathForResource:@"haarcascade_frontalface_alt2" ofType:@"xml"];
    faceDetector.load([cascadePath UTF8String]);
    //加载图片文件
    NSString * path = [[NSBundle mainBundle] pathForResource:@"lena_std" ofType:@"tif"];
    UIImage * image = [UIImage imageWithContentsOfFile:path];
    //转换image中的UIImage * 格式图像到Mat格式,结果存到faceImage中
    Mat faceImage;
    UIImageToMat(image, faceImage);
    //转换faceImage中的图像到单通道灰度图像,结果存到gray中
    Mat gray;
    cvtColor(faceImage, gray, COLOR_BGR2GRAY);
    //检查脸部
    std::vector<cv::Rect> faces;
    faceDetector.detectMultiScale(gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, cv::Size(30,30));
    //给所有检查到的脸部画框
    for (unsigned int i=0;i<faces.size();i++){
    const cv::Rect& face = faces[i];
    //得到左上角 和 右下角 坐标
    cv::Point tl(face.x,face.y);
    cv::Point br=tl+cv::Point(face.width,face.height);
    //画框
    Scalar magenta = Scalar(0,128,255);
    rectangle(faceImage, tl, br, magenta,4,8,0);
    }

    //显示结果
    imageView.image = MatToUIImage(faceImage);
    }
  2. CMD+R 编译运行,检查结果
    2015-10-14-10.50.33.jpg

解释

  1. 我们使用了使用《Instant-OpenCV-for-iOS》-学习笔记-3的工程。当然也可以直接建立一个工程。然后加入OpenCV framework文件,在storyboard里加上UIImageView组件。
  2. 本例中,我们使用基于Haar分类器方法的人脸检测器cv::CascadeClassifier。Haar分类器由Paul Viola提出,后由Rainer Lienhart发展。
  3. haarcascade_frontalface_alt2.xml文件包含了用于检测脸部正面特征的分类器参数。
  4. 加载参赛需要将NSString对象转化为std::string对象。使用UTF8String方法将NSString对象转化为std::string对象。
  5. 使用CascadeClassifier类的detectMultiScale方法在图像中找到脸部区域。
  6. 使用cv::rectangle函数在检测结果区域上加方框。
  7. 可以使用不同的图片或者不同的分类器XML文件进行试验。比如使用haarcascade_eye.xml可以得到这样的效果
    2015-10-14-11.57.28.jpg