facemark.cpp 7.27 KB
Newer Older
Alexander Alekhin's avatar
Alexander Alekhin committed
1 2 3 4
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.

5
/*
6
This file was part of GSoC Project: Facemark API for OpenCV
7 8 9 10 11
Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc
Student: Laksono Kurnianggoro
Mentor: Delia Passalacqua
*/

Alexander Alekhin's avatar
Alexander Alekhin committed
12
#include "precomp.hpp"
13
#include "opencv2/face/facemark_train.hpp"
14 15 16 17 18 19 20 21 22

/*dataset parser*/
#include <fstream>
#include <sstream>
#include <string>
#include <stdlib.h>     /* atoi */

namespace cv {
namespace face {
Alexander Alekhin's avatar
Alexander Alekhin committed
23 24 25

using namespace std;

Alexander Alekhin's avatar
Alexander Alekhin committed
26 27 28 29 30 31
CParams::CParams(String s, double sf, int minN, Size minSz, Size maxSz){
    cascade = s;
    scaleFactor = sf;
    minNeighbors = minN;
    minSize = minSz;
    maxSize = maxSz;
Alexander Alekhin's avatar
Alexander Alekhin committed
32 33 34 35 36

    if (!face_cascade.load(cascade))
    {
        CV_Error_(Error::StsBadArg, ("Error loading face_cascade: %s", cascade.c_str()));
    }
Alexander Alekhin's avatar
Alexander Alekhin committed
37 38
}

Alexander Alekhin's avatar
Alexander Alekhin committed
39 40 41
bool getFaces(InputArray image, OutputArray faces, CParams* params)
{
    CV_Assert(params);
Alexander Alekhin's avatar
Alexander Alekhin committed
42 43 44
    Mat gray;
    std::vector<Rect> roi;

Alexander Alekhin's avatar
Alexander Alekhin committed
45 46
    cvtColor(image.getMat(), gray, COLOR_BGR2GRAY);
    equalizeHist(gray, gray);
Alexander Alekhin's avatar
Alexander Alekhin committed
47

Alexander Alekhin's avatar
Alexander Alekhin committed
48
    params->face_cascade.detectMultiScale( gray, roi, params->scaleFactor, params->minNeighbors, CASCADE_SCALE_IMAGE, params->minSize, params->maxSize);
49

Alexander Alekhin's avatar
Alexander Alekhin committed
50 51
    Mat(roi).copyTo(faces);
    return true;
Alexander Alekhin's avatar
Alexander Alekhin committed
52
}
53

Alexander Alekhin's avatar
Alexander Alekhin committed
54 55
bool loadDatasetList(String imageList, String groundTruth, std::vector<String> & images, std::vector<String> & landmarks){
    std::string line;
56

Alexander Alekhin's avatar
Alexander Alekhin committed
57 58 59
    /*clear the output containers*/
    images.clear();
    landmarks.clear();
60

Alexander Alekhin's avatar
Alexander Alekhin committed
61 62 63 64 65 66 67 68
    /*open the files*/
    std::ifstream infile;
    infile.open(imageList.c_str(), std::ios::in);
    std::ifstream ss_gt;
    ss_gt.open(groundTruth.c_str(), std::ios::in);
    if ((!infile) || !(ss_gt)) {
       printf("No valid input file was given, please check the given filename.\n");
       return false;
69 70
    }

Alexander Alekhin's avatar
Alexander Alekhin committed
71 72 73 74
     /*load the images path*/
    while (getline (infile, line)){
        images.push_back(line);
    }
75

Alexander Alekhin's avatar
Alexander Alekhin committed
76 77 78
    /*load the points*/
    while (getline (ss_gt, line)){
        landmarks.push_back(line);
79 80
    }

Alexander Alekhin's avatar
Alexander Alekhin committed
81 82
    return true;
}
83

Alexander Alekhin's avatar
Alexander Alekhin committed
84 85 86 87 88
bool loadTrainingData(String filename, std::vector<String> & images, OutputArray _facePoints, char delim, float offset){
    std::string line;
    std::string item;
    std::vector<Point2f> pts;
    std::vector<float> raw;
89

Alexander Alekhin's avatar
Alexander Alekhin committed
90
    // FIXIT
Alexander Alekhin's avatar
Alexander Alekhin committed
91 92
    std::vector<std::vector<Point2f> > & facePoints =
        *(std::vector<std::vector<Point2f> >*) _facePoints.getObj();
93

Alexander Alekhin's avatar
Alexander Alekhin committed
94 95 96
    std::ifstream infile;
    infile.open(filename.c_str(), std::ios::in);
    if (!infile) {
Alexander Alekhin's avatar
Alexander Alekhin committed
97
        CV_Error_(Error::StsBadArg, ("No valid input file was given, please check the given filename: %s", filename.c_str()));
Alexander Alekhin's avatar
Alexander Alekhin committed
98
    }
99

Alexander Alekhin's avatar
Alexander Alekhin committed
100 101 102
    /*clear the output containers*/
    images.clear();
    facePoints.clear();
103

Alexander Alekhin's avatar
Alexander Alekhin committed
104 105 106
    /*the main loading process*/
    while (getline (infile, line)){
        std::istringstream ss(line); // string stream for the current line
107

Alexander Alekhin's avatar
Alexander Alekhin committed
108 109 110
        /*pop the image path*/
        getline (ss, item, delim);
        images.push_back(item);
111

Alexander Alekhin's avatar
Alexander Alekhin committed
112 113 114 115 116
        /*load all numbers*/
        raw.clear();
        while (getline (ss, item, delim)){
            raw.push_back((float)atof(item.c_str()));
        }
117

Alexander Alekhin's avatar
Alexander Alekhin committed
118 119 120 121 122 123 124
        /*convert to opencv points*/
        pts.clear();
        for(unsigned i = 0;i< raw.size();i+=2){
            pts.push_back(Point2f(raw[i]+offset,raw[i+1]+offset));
        }
        facePoints.push_back(pts);
    } // main loading process
125

Alexander Alekhin's avatar
Alexander Alekhin committed
126 127
    return true;
}
128

Alexander Alekhin's avatar
Alexander Alekhin committed
129 130 131
bool loadTrainingData(String imageList, String groundTruth, std::vector<String> & images, OutputArray _facePoints, float offset){
    std::string line;
    std::vector<Point2f> facePts;
132

Alexander Alekhin's avatar
Alexander Alekhin committed
133
    // FIXIT
Alexander Alekhin's avatar
Alexander Alekhin committed
134 135
    std::vector<std::vector<Point2f> > & facePoints =
            *(std::vector<std::vector<Point2f> >*) _facePoints.getObj();
136

Alexander Alekhin's avatar
Alexander Alekhin committed
137 138 139
    /*clear the output containers*/
    images.clear();
    facePoints.clear();
140

Alexander Alekhin's avatar
Alexander Alekhin committed
141 142 143 144
    /*load the images path*/
    std::ifstream infile;
    infile.open(imageList.c_str(), std::ios::in);
    if (!infile) {
Alexander Alekhin's avatar
Alexander Alekhin committed
145
       CV_Error_(Error::StsBadArg, ("No valid input file was given, please check the given filename: %s", imageList.c_str()));
Alexander Alekhin's avatar
Alexander Alekhin committed
146
    }
147

Alexander Alekhin's avatar
Alexander Alekhin committed
148 149 150
    while (getline (infile, line)){
        images.push_back(line);
    }
151

Alexander Alekhin's avatar
Alexander Alekhin committed
152 153 154 155 156 157
    /*load the points*/
    std::ifstream ss_gt(groundTruth.c_str());
    while (getline (ss_gt, line)){
        facePts.clear();
        loadFacePoints(line, facePts, offset);
        facePoints.push_back(facePts);
158 159
    }

Alexander Alekhin's avatar
Alexander Alekhin committed
160 161
    return true;
}
162

Alexander Alekhin's avatar
Alexander Alekhin committed
163
bool loadFacePoints(String filename, OutputArray points, float offset){
Alexander Alekhin's avatar
Alexander Alekhin committed
164
    vector<Point2f> pts;
165

Alexander Alekhin's avatar
Alexander Alekhin committed
166 167
    std::string line, item;
    std::ifstream infile(filename.c_str());
168

Alexander Alekhin's avatar
Alexander Alekhin committed
169 170 171
    /*pop the version*/
    std::getline(infile, line);
    CV_Assert(line.compare(0,7,"version")==0);
172

Alexander Alekhin's avatar
Alexander Alekhin committed
173 174 175
    /*pop the number of points*/
    std::getline(infile, line);
    CV_Assert(line.compare(0,8,"n_points")==0);
176

Alexander Alekhin's avatar
Alexander Alekhin committed
177 178 179
    /*get the number of points*/
    std::string item_npts;
    int npts;
180

Alexander Alekhin's avatar
Alexander Alekhin committed
181 182
    std::istringstream linestream(line);
    linestream>>item_npts>>npts;
183

Alexander Alekhin's avatar
Alexander Alekhin committed
184 185
    /*pop out '{' character*/
    std::getline(infile, line);
186

Alexander Alekhin's avatar
Alexander Alekhin committed
187 188 189 190 191 192 193
    /*main process*/
    int cnt = 0;
    std::string x, y;
    pts.clear();
    while (std::getline(infile, line) && cnt<npts )
    {
        cnt+=1;
194

Alexander Alekhin's avatar
Alexander Alekhin committed
195 196 197
        std::istringstream ss(line);
        ss>>x>>y;
        pts.push_back(Point2f((float)atof(x.c_str())+offset,(float)atof(y.c_str())+offset));
198 199 200

    }

Alexander Alekhin's avatar
Alexander Alekhin committed
201
    Mat(pts).copyTo(points);
Alexander Alekhin's avatar
Alexander Alekhin committed
202 203 204
    return true;
}

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
bool getFacesHAAR(InputArray image, OutputArray faces, const String& face_cascade_name)
{
    Mat gray;
    vector<Rect> roi;
    CascadeClassifier face_cascade;
    CV_Assert(face_cascade.load(face_cascade_name) && "Can't loading face_cascade");
    cvtColor(image.getMat(), gray, COLOR_BGR2GRAY);
    equalizeHist(gray, gray);
    face_cascade.detectMultiScale(gray, roi, 1.1, 2, 0|CASCADE_SCALE_IMAGE, Size(30, 30));
    Mat(roi).copyTo(faces);
    return true;
}

bool loadTrainingData(vector<String> filename,vector< vector<Point2f> >
                          & trainlandmarks,vector<String> & trainimages)
{
    string img;
    vector<Point2f> temp;
    string s;
    string tok;
    vector<string> coordinates;
    ifstream f1;
    for(unsigned long j=0;j<filename.size();j++){
        f1.open(filename[j].c_str(),ios::in);
        if(!f1.is_open()){
            cout<<filename[j]<<endl;
231
            CV_Error(Error::StsError, "File can't be opened for reading!");
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
        }
        //get the path of the image whose landmarks have to be detected
        getline(f1,img);
        //push the image paths in the vector
        trainimages.push_back(img);
        img.clear();
        while(getline(f1,s)){
            Point2f pt;
            stringstream ss(s); // Turn the string into a stream.
            while(getline(ss, tok,',')) {
                coordinates.push_back(tok);
                tok.clear();
            }
            pt.x = (float)atof(coordinates[0].c_str());
            pt.y = (float)atof(coordinates[1].c_str());
            coordinates.clear();
            temp.push_back(pt);
        }
        trainlandmarks.push_back(temp);
        temp.clear();
        f1.close();
    }
    return true;
}

Alexander Alekhin's avatar
Alexander Alekhin committed
257 258
void drawFacemarks(InputOutputArray image, InputArray points, Scalar color){
    Mat img = image.getMat();
Alexander Alekhin's avatar
Alexander Alekhin committed
259
    vector<Point2f> pts = points.getMat();
Alexander Alekhin's avatar
Alexander Alekhin committed
260 261 262
    for(size_t i=0;i<pts.size();i++){
        circle(img, pts[i],3, color,-1);
    }
Alexander Alekhin's avatar
Alexander Alekhin committed
263
}
264 265
} /* namespace face */
} /* namespace cv */