-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathassignment1.cc
140 lines (108 loc) · 3.56 KB
/
assignment1.cc
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
///
/// Assignment 1
/// Skin Color Classification
///
/// Group Number:
/// Authors:
///
#define _OPENCV_FLANN_HPP_
#include <opencv2/opencv.hpp>
#include <opencv/highgui.h>
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
#include <iostream>
#include "skinmodel.h"
#include "ROC.h"
using namespace std;
int main(int argc, char* argv[]) {
cv::setNumThreads(0);
/// parse command line options
boost::program_options::variables_map pom;
{
namespace po = boost::program_options;
po::options_description pod(string("Allowed options for ")+argv[0]);
pod.add_options()
("help,h", "produce this help message")
("gui,g", "Enable the GUI")
("out,o", po::value<string>(), "Path where to write the results")
("path", po::value<string>()->default_value("data"), "Path where to read input data");
po::positional_options_description pop;
pop.add("path", -1);
po::store(po::command_line_parser( argc, argv ).options(pod).positional(pop).run(), pom);
po::notify(pom);
if (pom.count("help")) {
cout << "Usage:" << endl << pod << "\n";
return 0;
}
}
/// get image filenames
string path = pom["path"].as<string>();
vector<string> images;
{
namespace fs = boost::filesystem;
for (fs::directory_iterator it(fs::path(path+"/.")); it!=fs::directory_iterator(); it++)
if (is_regular_file(*it) and it->path().filename().string().substr(0,5)!="mask-")
images.push_back(it->path().filename().string());
}
if (images.empty()) { cerr << "No images found." << endl; return -1; }
// srand(time(0));
random_shuffle(images.begin(), images.end());
/// Perform a 5 fold cross evaluation, store results on a ROC
ROC<int> roc;
constexpr uint nFolds = 5;
for (uint fold=0; fold<nFolds; fold++) {
cout << "\x1b[31;1m" << "Start fold " << (fold+1) << " of " << nFolds << "\x1b[0m" << endl;
vector<string> testImgs, trainImgs;
for (uint i=0; i<images.size(); i++) {
if (i%nFolds==fold) {
testImgs.push_back(images[i]);
} else {
trainImgs.push_back(images[i]);
}
}
/// create skin color model instance
SkinModel model;
/// train model with all images in the train folder
model.startTraining();
for (auto &f:trainImgs) {
cout << "Training on Image " << path+"/"+f << endl;
cv::Mat3b img = cv::imread(path+"/"+f);
cv::Mat1b mask = cv::imread(path+"/mask-"+f,0);
cv::threshold( mask, mask, 127, 255, cv::THRESH_BINARY);
model.train( img, mask );
}
model.finishTraining();
/// test model with all images in the test folder,
for (auto &f:testImgs) {
cout << "Testing Image " << path+"/"+f << endl;
cv::Mat3b img = cv::imread(path+"/"+f);
cv::Mat1b hyp = model.classify(img);
cv::Mat1b mask = cv::imread(path+"/mask-"+f,0);
for (int i=0; i<hyp.rows; i++)
for (int j=0; j<hyp.cols; j++)
roc.add(mask(i,j)>127, hyp(i,j));
}
}
/// After testing, update statistics and show results
roc.update();
cout << "Overall F1 score: " << roc.F1 << endl;
/// Display final result if desired
if (pom.count("gui")) {
cv::imshow("ROC", roc.draw());
cv::waitKey(0);
}
/// Ouput a summary of the data if required
if (pom.count("out")) {
string p = pom["out"].as<string>();
/// GRAPH format with one FPR and TPR coordinates per line
ofstream graph(p+"/graph.txt");
for (auto &dot : roc.graph)
graph << dot.first << " " << dot.second << endl;
/// Single output of the F1 score
ofstream score(p+"/score.txt");
score << roc.F1 << endl;
/// Ouput of the obtained ROC figure
cv::imwrite(p+"/ROC.png", roc.draw());
}
}