-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.cpp
More file actions
executable file
·175 lines (139 loc) · 5.81 KB
/
Copy pathmain.cpp
File metadata and controls
executable file
·175 lines (139 loc) · 5.81 KB
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>
#include <time.h>
#include <iomanip>
#include <opencv2/core/core.hpp>
#include <opencv2/contrib/contrib.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
//CONSTANTS
//Path to csv file containint images in the trained database
const string DATABASE_KNOWN = "at_1-30.csv";
//Path to csv file containint images in the set of non-trained images
const string DATABASE_UNKNOWN = "at_31-40.csv";
//This function reads the face database and stores the images and labels into the corresponding vectors
static void readDB(const string& filename, vector<Mat>& images, vector<int>& labels);
int main()
{
cout << "Face recognition using EIGENFACES" << endl << endl;
//Vectors to hold the set of images and lables that will be part of the model
vector <Mat> images;
vector <int> labels;
//Vectors to hold set of images and lables that will not be part of the model
vector <Mat> unknownImages;
vector <int> unknownLabels;
//Read images and labels into Mat objects
try{
readDB(DATABASE_KNOWN, images, labels); //pass file name
readDB(DATABASE_UNKNOWN, unknownImages, unknownLabels);
}
//If the database was not properly read
catch (Exception& e){
cout << "Error openning file " << e.msg << endl;
return 1;
}
//The "images" and "unkown" Mat objects must contains 2 picture or more in order for the program to execute correctly
if (images.size() <= 1 || unknownImages.size() <= 1){
cout << "This program requires more than one known and unknow image";
return 1;
}
//Display the initial size of each vector
cout << "Initial 'images' vector size: " << images.size() << endl;
cout << "Initial 'unknownImages' vector size: " << unknownImages.size() << endl << endl;
//Get sample test images from the "images" and "unknownImages" vectors (for the purpose of this program,random pictures will be used)
//Remove selected images from the corresponding vectors so that the training and test data don't overlap
//Create vector with known and unknown images for testing purposes
vector<Mat>testImages;
vector<int>testLabels;
srand(time(NULL));
for (int i = 0; i < 5; i++){
int randomNumber0 = rand() % images.size();
int randomNumber1 = rand() % unknownImages.size();
//Insert images into test vector
testImages.push_back(images[randomNumber0]);
testLabels.push_back(labels[randomNumber0]);
testImages.push_back(unknownImages[randomNumber1]);
testLabels.push_back(unknownLabels[randomNumber1]);
//Delete images from original vector
images.pop_back();
labels.pop_back();
unknownImages.pop_back();
unknownLabels.pop_back();
}
cout << "The number of images that have been added to the testImages vectors is: " << testImages.size() << endl << endl;
//Create and train an Eigenface model for face recognition
cout << "1. TRAIN THE MODEL" << endl;
cout << "Training starting..." << endl;
Ptr<FaceRecognizer> eigenModel = createEigenFaceRecognizer();
eigenModel->train(images, labels);
cout << "Training finished..." << endl << endl;
//Save trained model to external file
cout << "2. SAVE THE MODEL" << endl;
cout << "Saving model to 'eigenfaces.yaml'" << endl << endl;
eigenModel->save("eigenfaces.yaml");
//Create a new model for demonstration purposes
//This model can be load into different programs
cout << "3. LOAD THE SAVED MODEL (NOT NECESSARY)" << endl;
Ptr<FaceRecognizer> eigenModel2 = createEigenFaceRecognizer();
cout << "Loading model from 'eigenfaces.yaml'" << endl << endl;
eigenModel2->load("eigenfaces.yaml");
//Recognize faces using the loaded model and the images stored in the test vector
cout << "4. TRY TO RECOGNIZE THE TEST IMAGE (FACE)" << endl;
cout << "Predict face from model: " << endl;
int predictLabel;
for (int i = 0; i < testImages.size(); i++){
int confidencePredictLabel = -1;
double confidence = 0.0;
//Apply thrshold to the prediction. If the distance to the nearest neighbor (level of confidence) is larger than the threshold (10), the mothod return -1
double current_threshold = eigenModel->getDouble("threshold");
eigenModel2->set("threshold", 10.0);
//Try to recognize test images
predictLabel = eigenModel2->predict(testImages[i]);
//confidencePredictLabel and confidence will present different values if a threshold is not used (these variables are not necessary in this function given that a threshold is being used).
//In order to see level of confidece, comment out lines 116 and 117, and uncomment line 129.
eigenModel2->predict(testImages[i], confidencePredictLabel, confidence);
//Show results
//cout << " Confidence: " << confidence << endl;
cout << "Image " << i << ": ";
//If the predicted label is equal to -1, the face was not recognized, otherwise it was (1-10)
if (predictLabel == -1){
cout << " Predicted class = " << predictLabel << setw(36) << " -> Unknown face" << endl;
}
else{
cout << " Predicted class = " << predictLabel << " / Actual label = " << testLabels[i] << setw(3) << " -> (!)Knwon face" << endl;
}
}
//Terminate the program
waitKey();
cout << endl;
system("pause");
return 0;
}
static void readDB(const string& filename, vector<Mat>& images, vector<int>& labels){
ifstream csv_File;
csv_File.open(filename);
if (csv_File.is_open()){
string line, path, img_label;
char separator = ';';
int count = 0;
while (getline(csv_File, line)){
stringstream lines(line);
getline(lines, path, separator);
getline(lines, img_label);
if (!path.empty() && !img_label.empty()){
images.push_back(imread(path, CV_LOAD_IMAGE_GRAYSCALE));
labels.push_back(atoi(img_label.c_str()));
}
count++;
}
}
else{
cout << "The input file is not valid";
}
}