-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.cpp
More file actions
335 lines (327 loc) · 12.8 KB
/
main.cpp
File metadata and controls
335 lines (327 loc) · 12.8 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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
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
231
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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
//============================================================================
// Name : SPCBIR.cpp
// Author : Bar Yaacovi and Ofir Moses
// Version : v1.0
//============================================================================
#include <iostream>
#include <cstring>
#include "main_aux.h"
#define MAX_PATH_LENGTH 1024
#define MAX_ERR_MSG_LENGTH 1024
#define QRY_IMG_MSG "Please enter an image path:\n"
#define EXIT_MSG "Exiting...\n"
#define ERR_MSG_INVALID_ARG "Error : One of the arguments supplied to the method %s is invalid."
#define ERR_MSG_INVALID_COMM_LINE_ARG "\"Invalid command line arguments : use -c <config_filename>\"\n"
#define ERR_MSG_READ_CONF_FILE "Error while reading the configuration file : "
#define ERR_MSG_MISSING_DIR "Didn't find images directory path."
#define ERR_MSG_MISSING_PREFIX "Didn't find images prefix."
#define ERR_MSG_MISSING_SUFFIX "Didn't find images suffix."
#define ERR_MSG_MISSING_NUM_IMAGES "Didn't find the number of images."
#define ERR_MSG_CANNOT_OPEN_DEFAULT_CONF_FILE "\"The default configuration file spcbir.config couldn’t be open\"\n"
#define ERR_MSG_CANNOT_OPEN_CONF_FILE "\"The configuration file %s couldn’t be open\"\n"
#define ERR_MSG_ALLOC_FAIL "Error : An allocation error happened "
#define ERR_MSG_INVALID_INTEGER "An integer value was expected"
#define ERR_MSG_INVALID_STRING "One string value was expected"
#define ERR_MSG_GENERAL "General error. Unexpectedly, the program reached to a code where it shouldn't supposed to.\n"
#define ERR_MSG_CONFIG_INVALID_ARGUMENT "Error : The configuration file wasn't given to the method"
#define ERR_MSG_INVALID_ARGUMENT_LOGGER_FILENAME "Error : One of the arguments given to the method spConfigGetLoggerFilename() is invalid."
#define ERR_MSG_INVALID_ARGUMENT_LOGGER_LEVEL_NUM "Error : One of the arguments given to the method spConfigGetLoggerLevel() is invalid."
#define ERR_MSG_INVALID_ARGUMENT_LOGGER_LEVEL_FROM_NUM "Error : One of the arguments given to the method spLoggerLevelFromNum() is invalid."
#define ERR_MSG_CREATE_CONF "in the method spConfigCreate()"
#define ERR_MSG_CREATE_LOGGER "in the method spLoggerCreate()"
#define ERR_MSG_CANNOT_OPEN_LOGGER_FILE "Error : couldn't open logger file."
#define ERR_MSG_GET_IMG_DIR "spConfigGetImagesDirectory()"
#define ERR_MSG_IS_EXT_MODE "spConfigIsExtractionMode()"
#define ERR_MSG_GET_IMG_PREFIX "spConfigGetImagesPrefix()"
#define ERR_MSG_GET_ING_SUFFIX "spConfigGetImagesSuffix()"
#define ERR_MSG_GET_IMG_NUM "spConfigGetNumOfImages()"
#define ERR_MSG_GET_PCA_DIM "spConfigGetPCADim()"
#define ERR_MSG_GET_SPLIT_METHOD "spConfigGetKDTreeSplitMethod()"
#define ERR_MSG_CANNOT_OBTAIN_FEAT "Error : couldn't obtain features correctly."
#define ERR_MSG_CANNOT_CREATE_KDTREE "Error : Couldn't create KDTree from the features."
#define ERR_MSG_IS_MIN_GUI "spConfigMinimalGui()"
#define ERR_MSG_GET_KNN "spConfigGetKNN()"
using namespace std;
int main(int argc, const char* argv[]) {
// Extract configuration from file
SP_CONFIG_MSG configMsg;
bool isDefaultConfig = true;
SPConfig config;
if(argc == 3 && strcmp(argv[1], "-c") == 0){
isDefaultConfig = false;
config = spConfigCreate(argv[2],&configMsg);
}
else if(argc == 1){
config = spConfigCreate("./spcbir.config", &configMsg);
}
else{
printf(ERR_MSG_INVALID_COMM_LINE_ARG);
return 1;
}
switch (configMsg){
case SP_CONFIG_INVALID_ARGUMENT :
printf(ERR_MSG_CONFIG_INVALID_ARGUMENT);
free(config);
return 1;
case SP_CONFIG_MISSING_DIR:
printf("%s%s",ERR_MSG_READ_CONF_FILE, ERR_MSG_MISSING_DIR);
free(config);
return 1;
case SP_CONFIG_MISSING_PREFIX:
printf("%s%s",ERR_MSG_READ_CONF_FILE, ERR_MSG_MISSING_PREFIX);
free(config);
return 1;
case SP_CONFIG_MISSING_SUFFIX:
printf("%s%s",ERR_MSG_READ_CONF_FILE, ERR_MSG_MISSING_SUFFIX);
free(config);
return 1;
case SP_CONFIG_MISSING_NUM_IMAGES:
printf("%s%s",ERR_MSG_READ_CONF_FILE, ERR_MSG_MISSING_NUM_IMAGES);
free(config);
return 1;
case SP_CONFIG_CANNOT_OPEN_FILE :
if(isDefaultConfig){
printf(ERR_MSG_CANNOT_OPEN_DEFAULT_CONF_FILE);
}
else{
printf(ERR_MSG_CANNOT_OPEN_CONF_FILE, argv[2]);
}
free(config);
return 1;
case SP_CONFIG_ALLOC_FAIL:
printf("%s%s", ERR_MSG_ALLOC_FAIL, ERR_MSG_CREATE_CONF);
free(config);
return 1;
case SP_CONFIG_INVALID_INTEGER:
printf("%s%s",ERR_MSG_READ_CONF_FILE, ERR_MSG_INVALID_INTEGER);
free(config);
return 1;
case SP_CONFIG_INVALID_STRING:
printf("%s%s",ERR_MSG_READ_CONF_FILE, ERR_MSG_INVALID_STRING);
free(config);
return 1;
case SP_CONFIG_SUCCESS:
break;
default:
printf(ERR_MSG_GENERAL);
free(config);
return 1;
}
// Initialize logger
char* loggerFilename = spConfigGetLoggerFilename(config, &configMsg);
if(configMsg == SP_CONFIG_INVALID_ARGUMENT){
printf(ERR_MSG_INVALID_ARGUMENT_LOGGER_FILENAME);
free(config);
return 1;
}
if(configMsg == SP_CONFIG_ALLOC_FAIL){
printf(ERR_MSG_ALLOC_FAIL);
free(config);
return 1;
}
int loggerLevelNum;
configMsg = spConfigGetLoggerLevel(config, &loggerLevelNum);
switch (configMsg){
case SP_CONFIG_INVALID_ARGUMENT :
printf(ERR_MSG_INVALID_ARGUMENT_LOGGER_LEVEL_NUM);
free(loggerFilename);
free(config);
return 1;
case SP_CONFIG_SUCCESS:
break;
default:
printf(ERR_MSG_GENERAL);
free(loggerFilename);
free(config);
return 1;
}
SP_LOGGER_LEVEL loggerLevel;
SP_LOGGER_MSG loggerMsg = spLoggerLevelFromNum(loggerLevelNum, &loggerLevel);
switch (loggerMsg){
case SP_LOGGER_INVAlID_ARGUMENT :
printf(ERR_MSG_INVALID_ARGUMENT_LOGGER_LEVEL_FROM_NUM);
free(loggerFilename);
free(config);
return 1;
case SP_LOGGER_SUCCESS:
break;
default:
printf(ERR_MSG_GENERAL);
free(loggerFilename);
free(config);
return 1;
}
loggerMsg = spLoggerCreate(loggerFilename, loggerLevel);
free(loggerFilename);
switch (loggerMsg){
case SP_LOGGER_DEFINED :
break;
case SP_LOGGER_OUT_OF_MEMORY:
printf("%s%s", ERR_MSG_ALLOC_FAIL, ERR_MSG_CREATE_LOGGER);
free(config);
return 1;
case SP_LOGGER_CANNOT_OPEN_FILE:
printf(ERR_MSG_CANNOT_OPEN_LOGGER_FILE);
free(config);
return 1;
case SP_LOGGER_SUCCESS:
break;
default:
printf(ERR_MSG_GENERAL);
free(config);
return 1;
}
// Extract key fields requaired for the algorithm from the configuration object
bool isExtractionMode = spConfigIsExtractionMode(config, &configMsg);
if(configMsg == SP_CONFIG_INVALID_ARGUMENT){
char errorMsg[MAX_ERR_MSG_LENGTH];
sprintf(errorMsg, ERR_MSG_INVALID_ARG, ERR_MSG_IS_EXT_MODE);
spLoggerPrintError(errorMsg, __FILE__, __func__, __LINE__);
spLoggerDestroy();
free(config);
return 2;
}
char imagesDirectory[MAX_PATH_LENGTH];
configMsg = spConfigGetImagesDirectory(config, imagesDirectory);
if(configMsg == SP_CONFIG_INVALID_ARGUMENT){
char errorMsg[MAX_ERR_MSG_LENGTH];
sprintf(errorMsg, ERR_MSG_INVALID_ARG, ERR_MSG_GET_IMG_DIR);
spLoggerPrintError(errorMsg, __FILE__, __func__, __LINE__);
spLoggerDestroy();
free(config);
return 3;
}
char imagesPrefix[MAX_PATH_LENGTH];
configMsg = spConfigGetImagesPrefix(config, imagesPrefix);
if(configMsg == SP_CONFIG_INVALID_ARGUMENT){
char errorMsg[MAX_ERR_MSG_LENGTH];
sprintf(errorMsg, ERR_MSG_INVALID_ARG, ERR_MSG_GET_IMG_PREFIX);
spLoggerPrintError(errorMsg, __FILE__, __func__, __LINE__);
spLoggerDestroy();
free(config);
return 4;
}
char imagesSuffix[MAX_PATH_LENGTH];
configMsg = spConfigGetImagesSuffix(config, imagesSuffix);
if(configMsg == SP_CONFIG_INVALID_ARGUMENT){
char errorMsg[MAX_ERR_MSG_LENGTH];
sprintf(errorMsg, ERR_MSG_INVALID_ARG, ERR_MSG_GET_ING_SUFFIX);
spLoggerPrintError(errorMsg, __FILE__, __func__, __LINE__);
spLoggerDestroy();
free(config);
return 5;
}
int numOfImages = spConfigGetNumOfImages(config, &configMsg);
if(configMsg == SP_CONFIG_INVALID_ARGUMENT){
char errorMsg[MAX_ERR_MSG_LENGTH];
sprintf(errorMsg, ERR_MSG_INVALID_ARG, ERR_MSG_GET_IMG_NUM);
spLoggerPrintError(errorMsg, __FILE__, __func__, __LINE__);
spLoggerDestroy();
free(config);
return 6;
}
int dim = spConfigGetPCADim(config, &configMsg);
if(configMsg == SP_CONFIG_INVALID_ARGUMENT){
char errorMsg[MAX_ERR_MSG_LENGTH];
sprintf(errorMsg, ERR_MSG_INVALID_ARG, ERR_MSG_GET_PCA_DIM);
spLoggerPrintError(errorMsg, __FILE__, __func__, __LINE__);
spLoggerDestroy();
free(config);
return 8;
}
SP_KD_SPLIT_MODE kdSplitMode;
configMsg = spConfigGetKDTreeSplitMethod(config, &kdSplitMode);
if(configMsg == SP_CONFIG_INVALID_ARGUMENT){
char errorMsg[MAX_ERR_MSG_LENGTH];
sprintf(errorMsg, ERR_MSG_INVALID_ARG, ERR_MSG_GET_SPLIT_METHOD);
spLoggerPrintError(errorMsg, __FILE__, __func__, __LINE__);
spLoggerDestroy();
free(config);
return 9;
}
bool isGUIMode = spConfigMinimalGui(config, &configMsg);
if(configMsg == SP_CONFIG_INVALID_ARGUMENT){
char errorMsg[MAX_ERR_MSG_LENGTH];
sprintf(errorMsg, ERR_MSG_INVALID_ARG, ERR_MSG_IS_MIN_GUI);
spLoggerPrintError(errorMsg, __FILE__, __func__, __LINE__);
spLoggerDestroy();
free(config);
return 10;
}
int k = spConfigGetNumOfSimilarImages(config, &configMsg);
if(configMsg == SP_CONFIG_INVALID_ARGUMENT){
char errorMsg[MAX_ERR_MSG_LENGTH];
sprintf(errorMsg, ERR_MSG_INVALID_ARG, ERR_MSG_GET_KNN);
spLoggerPrintError(errorMsg, __FILE__, __func__, __LINE__);
spLoggerDestroy();
free(config);
return 11;
}
// Extract features from the images based on the extraction mode.
SPPoint** features;
int totalNumOfFeatures = 0;
if(isExtractionMode){
sp::ImageProc s = sp::ImageProc(config);
features = ExtractionModeAct(imagesDirectory, imagesPrefix, imagesSuffix, numOfImages, s, &totalNumOfFeatures, dim);
} else{
features = NonExtractionModeAct(imagesDirectory, imagesPrefix, numOfImages, &totalNumOfFeatures, dim);
}
if(!features){
spLoggerPrintError(ERR_MSG_CANNOT_OBTAIN_FEAT, __FILE__, __func__, __LINE__);
spLoggerDestroy();
free(config);
return 8;
}
// Create a KD-Tree for the features
SPKDTree* tree = spInitSPKDTree(features, totalNumOfFeatures, dim, kdSplitMode);
if(!tree){
spLoggerPrintError(ERR_MSG_CANNOT_CREATE_KDTREE, __FILE__, __func__, __LINE__);
spDestroySPPointArray(features, totalNumOfFeatures);
spLoggerDestroy();
free(config);
return 8;
}
// Loop for querying an image to search upon and print results
bool isEnded = false;
char* queryStr;
while(!isEnded){
queryStr = spGetInputFromUser(QRY_IMG_MSG);
if(!queryStr){
spDestroyKDTree(tree);
spDestroySPPointArray(features, totalNumOfFeatures);
spLoggerDestroy();
spConfigDestroy(config);
return 9;
}
if(strcmp(queryStr, "<>") == 0){
printf(EXIT_MSG);
isEnded = true;
} else{
int* KNN = spGetBestKMatches(tree, queryStr, config, numOfImages, k);
if(KNN){
if(isGUIMode){
spMinimalGUI(config,queryStr,KNN,k);
}
else{
spNonMinimalGUI(config, queryStr, KNN, k);
}
}
else{
spDestroyKDTree(tree);
spDestroySPPointArray(features, totalNumOfFeatures);
spLoggerDestroy();
spConfigDestroy(config);
free(queryStr);
return 9;
}
free(KNN);
}
free(queryStr);
}
// Free resources
spDestroyKDTree(tree);
spDestroySPPointArray(features, totalNumOfFeatures);
spLoggerDestroy();
spConfigDestroy(config);
return 0;
}