forked from karlphillip/GraphicsProgramming
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
133 lines (110 loc) · 4.38 KB
/
main.cpp
File metadata and controls
133 lines (110 loc) · 4.38 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
/* This application demonstrates how to train and use LDA to classify images
* into Apples or Oranges.
*
* This work is mostly a C++ translation to OpenCV of FruitClassification,
* a project written in Python by Eliezer Bernart, available here:
* https://github.com/eliezerb/FruitClassification
*/
#include "toolbox.h"
std::vector<Features> load_training_set(std::string path)
{
std::vector<Features> features_vec;
std::vector<std::string> filenames = ls_dir(path);
for (unsigned int i = 0; i < filenames.size(); i++)
{
Features f = get_features(filenames[i]);
if (f.aspect_ratio == 0 && f.b_color == 0 && f.g_color == 0 && f.r_color == 0)
continue;
features_vec.push_back(f);
}
return features_vec;
}
int main()
{
/* Step 1: Process all images in apples/oranges directories
* in order to extract their features.
*
* The feature vector is made of the following 4 attributes:
* - The aspect ratio of the fruit (width / height);
* The most dominant color of the fruit, which consists of:
* - The average Red color of the fruit;
* - The average Green color of the fruit;
* - The average Blue color of the fruit;
*/
// x_samples contains all the Apples' features for training
std::vector<Features> x_samples = load_training_set("apples");
// y_samples contains all the Orange's features for training
std::vector<Features> y_samples = load_training_set("oranges");
/* Step 2: Create a Mat structure to store the training data */
unsigned int num_cols = 4; // aspect ratio, avg red, avg green, avg blue
unsigned int num_rows = x_samples.size() + y_samples.size();
cv::Mat train_data;
for (unsigned int i = 0; i < x_samples.size(); i++)
{
// Each loop converts a Feature to a Mat's row
cv::Mat row = cv::Mat::zeros(1, 4, CV_64FC1);
row.at<double>(0) = x_samples[i].aspect_ratio;
row.at<double>(1) = x_samples[i].b_color;
row.at<double>(2) = x_samples[i].g_color;
row.at<double>(3) = x_samples[i].r_color;
train_data.push_back(row);
}
for (unsigned int i = 0; i < y_samples.size(); i++)
{
// Each loop converts a Feature to a Mat's row
cv::Mat row = cv::Mat::zeros(1, 4, CV_64FC1);
row.at<double>(0) = y_samples[i].aspect_ratio;
row.at<double>(1) = y_samples[i].b_color;
row.at<double>(2) = y_samples[i].g_color;
row.at<double>(3) = y_samples[i].r_color;
train_data.push_back(row);
}
/* Step 3: create labels for each training data
* - 0 represents the Apple class
* - 1 represents the Orange class
*
* Since the first 10 samples were Apples and the
* next 10 samples where Orange, let's make this simple!
*/
int apple_class = 0;
int orange_class = 1;
std::vector<int> labels;
for (unsigned int i = 0; i < num_rows; i++)
{
if (i < x_samples.size())
labels.push_back(apple_class);
else
labels.push_back(orange_class);
}
/* Step 4: train LDA */
int num_components = 2; // there's only 2 classes anyway
cv::LDA lda(train_data, labels, num_components);
cv::Mat projected = lda.project(train_data);
/* Step 5: test the classifier */
std::vector<Features> t_samples = load_training_set("test");
for (unsigned int i = 0; i < t_samples.size(); i++)
{
// Each loop converts a Feature to a Mat's row
cv::Mat test_data = cv::Mat::zeros(1, 4, CV_64FC1);
test_data.at<double>(0) = t_samples[i].aspect_ratio;
test_data.at<double>(1) = t_samples[i].b_color;
test_data.at<double>(2) = t_samples[i].g_color;
test_data.at<double>(3) = t_samples[i].r_color;
// Project the new data and check its prediction
cv::Mat proj_class = lda.project(test_data);
int min_class = -1;
double best_dist = 999999999.9;
for (int x = 0; x < projected.rows; x++)
{
double dist = cv::norm(projected.row(x), proj_class);
if (dist < best_dist)
{
best_dist = dist;
min_class = labels[x];
}
}
std::cout << t_samples[i].filename << " belongs to class " << min_class << " -> " <<
((min_class==0) ? "Apple" : "Orange") << std::endl;
}
return 0;
}