1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Author: Samyak Datta (datta[dot]samyak[at]gmail.com)
3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *
4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * A program to detect facial feature points using
5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Haarcascade classifiers for face, eyes, nose and mouth
6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *
7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/objdetect/objdetect.hpp"
10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/highgui/highgui.hpp"
11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/imgproc/imgproc.hpp"
12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <iostream>
14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <cstdio>
15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <vector>
16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <algorithm>
17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerusing namespace std;
19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerusing namespace cv;
20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Functions to parse command-line arguments
22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic string getCommandOption(const vector<string>&, const string&);
23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void setCommandOptions(vector<string>&, int, char**);
24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool doesCmdOptionExist(const vector<string>& , const string&);
25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Functions for facial feature detection
27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void help();
28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void detectFaces(Mat&, vector<Rect_<int> >&, string);
29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void detectEyes(Mat&, vector<Rect_<int> >&, string);
30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void detectNose(Mat&, vector<Rect_<int> >&, string);
31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void detectMouth(Mat&, vector<Rect_<int> >&, string);
32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void detectFacialFeaures(Mat&, const vector<Rect_<int> >, string, string, string);
33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstring input_image_path;
35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstring face_cascade_path, eye_cascade_path, nose_cascade_path, mouth_cascade_path;
36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerint main(int argc, char** argv)
38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(argc < 3)
40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        help();
42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return 1;
43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    // Extract command-line options
46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    vector<string> args;
47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    setCommandOptions(args, argc, argv);
48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    input_image_path = argv[1];
50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    face_cascade_path = argv[2];
51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    eye_cascade_path = (doesCmdOptionExist(args, "-eyes")) ? getCommandOption(args, "-eyes") : "";
52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    nose_cascade_path = (doesCmdOptionExist(args, "-nose")) ? getCommandOption(args, "-nose") : "";
53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    mouth_cascade_path = (doesCmdOptionExist(args, "-mouth")) ? getCommandOption(args, "-mouth") : "";
54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    // Load image and cascade classifier files
56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat image;
57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    image = imread(input_image_path);
58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    // Detect faces and facial features
60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    vector<Rect_<int> > faces;
61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    detectFaces(image, faces, face_cascade_path);
62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    detectFacialFeaures(image, faces, eye_cascade_path, nose_cascade_path, mouth_cascade_path);
63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    imshow("Result", image);
65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    waitKey(0);
67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return 0;
68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid setCommandOptions(vector<string>& args, int argc, char** argv)
71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for(int i = 1; i < argc; ++i)
73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        args.push_back(argv[i]);
75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return;
77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstring getCommandOption(const vector<string>& args, const string& opt)
80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    string answer;
82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    vector<string>::const_iterator it = find(args.begin(), args.end(), opt);
83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(it != args.end() && (++it != args.end()))
84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        answer = *it;
85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return answer;
86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbool doesCmdOptionExist(const vector<string>& args, const string& opt)
89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    vector<string>::const_iterator it = find(args.begin(), args.end(), opt);
91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return (it != args.end());
92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void help()
95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cout << "\nThis file demonstrates facial feature points detection using Haarcascade classifiers.\n"
97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "The program detects a face and eyes, nose and mouth inside the face."
98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "The code has been tested on the Japanese Female Facial Expression (JAFFE) database and found"
99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "to give reasonably accurate results. \n";
100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cout << "\nUSAGE: ./cpp-example-facial_features [IMAGE] [FACE_CASCADE] [OPTIONS]\n"
102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "IMAGE\n\tPath to the image of a face taken as input.\n"
103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "FACE_CASCSDE\n\t Path to a haarcascade classifier for face detection.\n"
104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "OPTIONS: \nThere are 3 options available which are described in detail. There must be a "
105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "space between the option and it's argument (All three options accept arguments).\n"
106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "\t-eyes : Specify the haarcascade classifier for eye detection.\n"
107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "\t-nose : Specify the haarcascade classifier for nose detection.\n"
108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "\t-mouth : Specify the haarcascade classifier for mouth detection.\n";
109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cout << "EXAMPLE:\n"
112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "(1) ./cpp-example-facial_features image.jpg face.xml -eyes eyes.xml -mouth mouth.xml\n"
113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "\tThis will detect the face, eyes and mouth in image.jpg.\n"
114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "(2) ./cpp-example-facial_features image.jpg face.xml -nose nose.xml\n"
115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "\tThis will detect the face and nose in image.jpg.\n"
116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "(3) ./cpp-example-facial_features image.jpg face.xml\n"
117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        "\tThis will detect only the face in image.jpg.\n";
118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cout << " \n\nThe classifiers for face and eyes can be downloaded from : "
120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        " \nhttps://github.com/Itseez/opencv/tree/master/data/haarcascades";
121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cout << "\n\nThe classifiers for nose and mouth can be downloaded from : "
123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        " \nhttps://github.com/Itseez/opencv_contrib/tree/master/modules/face/data/cascades\n";
124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void detectFaces(Mat& img, vector<Rect_<int> >& faces, string cascade_path)
127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CascadeClassifier face_cascade;
129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    face_cascade.load(cascade_path);
130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    face_cascade.detectMultiScale(img, faces, 1.15, 3, 0|CASCADE_SCALE_IMAGE, Size(30, 30));
132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return;
133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void detectFacialFeaures(Mat& img, const vector<Rect_<int> > faces, string eye_cascade,
136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        string nose_cascade, string mouth_cascade)
137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for(unsigned int i = 0; i < faces.size(); ++i)
139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        // Mark the bounding box enclosing the face
141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Rect face = faces[i];
142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        rectangle(img, Point(face.x, face.y), Point(face.x+face.width, face.y+face.height),
143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                Scalar(255, 0, 0), 1, 4);
144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        // Eyes, nose and mouth will be detected inside the face (region of interest)
146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat ROI = img(Rect(face.x, face.y, face.width, face.height));
147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        // Check if all features (eyes, nose and mouth) are being detected
149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        bool is_full_detection = false;
150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( (!eye_cascade.empty()) && (!nose_cascade.empty()) && (!mouth_cascade.empty()) )
151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            is_full_detection = true;
152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        // Detect eyes if classifier provided by the user
154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if(!eye_cascade.empty())
155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            vector<Rect_<int> > eyes;
157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            detectEyes(ROI, eyes, eye_cascade);
158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            // Mark points corresponding to the centre of the eyes
160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            for(unsigned int j = 0; j < eyes.size(); ++j)
161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                Rect e = eyes[j];
163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                circle(ROI, Point(e.x+e.width/2, e.y+e.height/2), 3, Scalar(0, 255, 0), -1, 8);
164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                /* rectangle(ROI, Point(e.x, e.y), Point(e.x+e.width, e.y+e.height),
165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    Scalar(0, 255, 0), 1, 4); */
166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        // Detect nose if classifier provided by the user
170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        double nose_center_height = 0.0;
171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if(!nose_cascade.empty())
172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            vector<Rect_<int> > nose;
174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            detectNose(ROI, nose, nose_cascade);
175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            // Mark points corresponding to the centre (tip) of the nose
177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            for(unsigned int j = 0; j < nose.size(); ++j)
178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                Rect n = nose[j];
180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                circle(ROI, Point(n.x+n.width/2, n.y+n.height/2), 3, Scalar(0, 255, 0), -1, 8);
181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                nose_center_height = (n.y + n.height/2);
182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        // Detect mouth if classifier provided by the user
186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        double mouth_center_height = 0.0;
187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if(!mouth_cascade.empty())
188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            vector<Rect_<int> > mouth;
190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            detectMouth(ROI, mouth, mouth_cascade);
191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            for(unsigned int j = 0; j < mouth.size(); ++j)
193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                Rect m = mouth[j];
195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                mouth_center_height = (m.y + m.height/2);
196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                // The mouth should lie below the nose
198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if( (is_full_detection) && (mouth_center_height > nose_center_height) )
199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    rectangle(ROI, Point(m.x, m.y), Point(m.x+m.width, m.y+m.height), Scalar(0, 255, 0), 1, 4);
201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                else if( (is_full_detection) && (mouth_center_height <= nose_center_height) )
203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    continue;
204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                else
205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    rectangle(ROI, Point(m.x, m.y), Point(m.x+m.width, m.y+m.height), Scalar(0, 255, 0), 1, 4);
206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return;
212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void detectEyes(Mat& img, vector<Rect_<int> >& eyes, string cascade_path)
215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CascadeClassifier eyes_cascade;
217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    eyes_cascade.load(cascade_path);
218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    eyes_cascade.detectMultiScale(img, eyes, 1.20, 5, 0|CASCADE_SCALE_IMAGE, Size(30, 30));
220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return;
221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void detectNose(Mat& img, vector<Rect_<int> >& nose, string cascade_path)
224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CascadeClassifier nose_cascade;
226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    nose_cascade.load(cascade_path);
227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    nose_cascade.detectMultiScale(img, nose, 1.20, 5, 0|CASCADE_SCALE_IMAGE, Size(30, 30));
229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return;
230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void detectMouth(Mat& img, vector<Rect_<int> >& mouth, string cascade_path)
233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CascadeClassifier mouth_cascade;
235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    mouth_cascade.load(cascade_path);
236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    mouth_cascade.detectMultiScale(img, mouth, 1.20, 5, 0|CASCADE_SCALE_IMAGE, Size(30, 30));
238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return;
239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
240