int spFeatureCreateFeatureFile(SPPoint* pointArray, const char* filename, int numOfImages,int numOfFeatures, int numOfDim){ FILE *featureFile = NULL; int i,j; char errorMsg[1025]; spLoggerPrintInfo("Creating features file..."); if(filename == NULL){ spLoggerPrintError("filename is NULL", "main.cpp", "main", 182);//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! return 1; //ERROR } //Opening the file featureFile = fopen(filename,"w"); if (featureFile == NULL){ sprintf(errorMsg, "The features file %s couldn’t be open", filename); spLoggerPrintError(errorMsg, "SPFeaturesFiles.c", "spFeatureCreateFeatureFile", 14); return 1; //ERROR } //Writing the file //First line - 1- number of images 2- overall number of features 3- number of dimensions of the features fprintf(featureFile,"%d;;%d;;%d\n",numOfImages,numOfFeatures,numOfDim); for (i = 0; i < numOfFeatures; ++i) { //Feature line - First the matching index of the img and the each coordinate fprintf(featureFile,"%d;;",spPointGetIndex(pointArray[i])); for (j = 0; j < numOfDim; ++j) { fprintf(featureFile,"%f;;",spPointGetAxisCoor(pointArray[i],j)); } fprintf(featureFile, "\n"); } spLoggerPrintInfo("Done creating features file"); fclose(featureFile); return 0; }
SPPoint* spFeatureExtractFromFeatureFile(const char* filename, int numOfImages,int *numOfFeatures, int *numOfDim){ FILE *featureFile = NULL; SPPoint* featureArray = NULL; int i,j, numOfImagesFile; char* str = NULL; char errorMsg[1025]; spLoggerPrintInfo("Extracting features from file..."); if(filename == NULL){ spLoggerPrintError("filename is NULL", "main.cpp", "main", 184);//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! return NULL; //ERROR } featureFile = fopen(filename,"r"); if (featureFile == NULL){ sprintf(errorMsg, "The features file %s couldn’t be open", filename); spLoggerPrintError(errorMsg, "SPFeaturesFiles.c", "spFeatureExtractFromFeatureFile", 48); return NULL; //ERROR } if(fscanf(featureFile,"%d;;%d;;%d\n",&numOfImagesFile,numOfFeatures,numOfDim) != 3){ spLoggerPrintError("Wrong feature file format - couldn't read", "SPFeaturesFiles.c", "spFeatureExtractFromFeatureFile", 54); return NULL; //ERROR } if(numOfImages != numOfImagesFile){ spLoggerPrintError("Number of images from features file isn't matching the given configuration", "SPFeaturesFiles.c", "spFeatureExtractFromFeatureFile", 54); return NULL; //ERROR } featureArray = (SPPoint*) malloc(*numOfFeatures * sizeof(SPPoint)); if(featureArray == NULL){ spLoggerPrintError("Memory Allocation Failure", "SPFeaturesFiles.c", "spFeatureExtractFromFeatureFile", 63); return NULL; //ERROR } for (i = 0; i < *numOfFeatures; ++i) { int imgIndex; double *coorArray; coorArray = (double*) malloc(*numOfDim * sizeof(double)); if(coorArray == NULL){ spLoggerPrintError("Memory Allocation Failure", "SPFeaturesFiles.c", "spFeatureExtractFromFeatureFile", 72); return NULL; //ERROR } if(fscanf(featureFile,"%d;;",&imgIndex) != 1){ spLoggerPrintError("Wrong feature file format - couldn't read", "SPFeaturesFiles.c", "spFeatureExtractFromFeatureFile", 77); return NULL; //ERROR } for (j = 0; j < *numOfDim-1; ++j) { if(fscanf(featureFile,"%lf;;",&coorArray[j]) != 1){ spLoggerPrintError("Wrong feature file format - couldn't read", "SPFeaturesFiles.c", "spFeatureExtractFromFeatureFile", 83); return NULL; //ERROR } } if(fscanf(featureFile,"%lf;;\n",&coorArray[*numOfDim - 1]) != 1){ spLoggerPrintError("Wrong feature file format - couldn't read", "SPFeaturesFiles.c", "spFeatureExtractFromFeatureFile", 88); return NULL; //ERROR } featureArray[i] = spPointCreate(coorArray, *numOfDim, imgIndex); if(featureArray[i] == NULL){ spLoggerPrintError("Memory Allocation Failure", "SPFeaturesFiles.c", "spFeatureExtractFromFeatureFile", 94); return NULL; //ERROR } free(coorArray); } if(fscanf(featureFile,"%s",str) == 1){ spLoggerPrintError("Wrong feature file format - couldn't read", "SPFeaturesFiles.c", "spFeatureExtractFromFeatureFile", 100); return NULL; //ERROR } spLoggerPrintInfo("Done extracting features from file"); fclose(featureFile); return featureArray; }
int main(int argc, char *argv[]) { SPConfig config = NULL; // hold configuration parameters char config_filename[CONFIG_FILE_PATH_SIZE]; // the configuration file name int knn; // the number of similar features in each image to find (spKNN from configuration file) int num_of_similar_images_to_find; // the number of similar images (to the query) to find (from configuration file) int split_method; // holds an int representing the split method: 0=RANDOM, 1= MAX_SPREAD, 2=INCREMENTAL bool minGui = false; // value of the system variable MinimalGui bool extraction_mode; // indicates if extraction mode on or off int num_of_images = 0; // number of images in the directory given by the user in the configuration file char** all_images_paths = NULL; // array with the paths to all the images int last_extracted_feature = 0; // helper - holds the last feature extracted in order to free all extracted features on error SPPoint** features_per_image = NULL; // helper - holds the features for each images int* num_of_features_per_image = NULL; // holds number of features extracted for each image char query_image[CONFIG_FILE_PATH_SIZE]; // the query image SPPoint* query_features = NULL; // all query features int query_num_of_features; // number of features in query image KDTreeNode kd_tree = NULL; // array holds a KDTree for the images int* closest_images = NULL; // array holds the spNumOfSimilarImages indexes of the closest images to the query image int print_result; // holds the result of the call to PrintMinGuiFalse int retval = 0; // return value - default 0 on success char string_holder[CONFIG_FILE_PATH_SIZE]; // helper to hold strings sp::ImageProc *improc = NULL; SP_CONFIG_MSG msg; int i; int j; int n; // validate command line arguments: // cmd line arguments are ok if there was no arguments specified (argc == 1) or two arguments specified ( -c and filname) if (argc != 3 && argc != 1) { printf(INVALID_CMD_LINE_MSG); return -1; } if (argc == 1) { strcpy(config_filename, DEFAULT_CONFIG_FILENAME); config = spConfigCreate(config_filename, &msg); if (msg == SP_CONFIG_CANNOT_OPEN_FILE) { printf(ERROR_OPENING_DEFAULT_CONFIG_FILE_MSG, DEFAULT_CONFIG_FILENAME); } if (msg != SP_CONFIG_SUCCESS) { retval = -1; goto err; // error is printed inside spConfigCreate } } else { // argc == 3 // check that second argument is the -c flag if (strcmp(argv[1], CMD_LINE_CONFIG_FILENAME_FLAG) != 0) { printf(INVALID_CMD_LINE_MSG); retval = -1; goto err; } strcpy(config_filename, argv[2]); config = spConfigCreate(config_filename, &msg); if (msg == SP_CONFIG_CANNOT_OPEN_FILE) { printf(ERROR_OPENING_CONFIG_FILE_MSG, config_filename); } if (msg != SP_CONFIG_SUCCESS) { retval = -1; goto err; // error is printed inside spConfigCreate } } // initiate from config if (initFromConfig(config, &num_of_images, &num_of_similar_images_to_find, &knn, &split_method, &extraction_mode, &minGui, &all_images_paths) == -1 ) { retval = -1; goto err; // error is printed inside initFromConfig } // initiate image proc improc = new sp::ImageProc(config); // extract images features if ((num_of_features_per_image = (int*)malloc(sizeof(*num_of_features_per_image) * num_of_images)) == NULL) { spLoggerPrintError(ALLOCATION_FAILURE_MSG, __FILE__, __func__, __LINE__); retval = -1; goto err; } spLoggerPrintInfo(CHECK_EXTRACTION_MODE_INFO_LOG); if (extraction_mode) { // extraction mode is chosen spLoggerPrintMsg(USE_EXTRACTION_MODE_LOG); spLoggerPrintInfo(EXTRACT_IMAGES_FEATURES_INFO_LOG); if ((features_per_image = (SPPoint**)malloc(sizeof(*features_per_image) * num_of_images)) == NULL) { spLoggerPrintError(ALLOCATION_FAILURE_MSG, __FILE__, __func__, __LINE__); retval = -1; goto err; } // extract each image features and write them to file for (i=0; i < num_of_images; i++) { // extract image features if ((features_per_image[i] = improc->getImageFeatures(all_images_paths[i], i, &(num_of_features_per_image[i]))) == NULL) { last_extracted_feature = i; retval = -1; goto err; // error is printed inside getImageFeatures } } if (saveToDirectory(config, features_per_image, num_of_features_per_image, num_of_images) == -1) { retval = -1; goto err; // error is printed inside saveToDirectory } } else { // not extraction mode spLoggerPrintMsg(USE_NOT_EXTRACTION_MODE_LOG); spLoggerPrintInfo(READ_FEATURES_FROM_FILE_LOG); if ((features_per_image = extractFromFiles(config, num_of_features_per_image, num_of_images)) == NULL) { retval = -1; goto err; // error is printed inside extractFromFiles } } if ((kd_tree = initiateDataStructures(features_per_image, num_of_features_per_image, num_of_images, split_method)) == NULL) { retval = -1; goto err; // error is printed inside initiateDataStructures } query: while(1) { // get a query image from the user printf(ENTER_AN_IMAGE_MSG); fflush(NULL); scanf("%s",query_image); // exit if user asked if (strcmp (query_image,EXIT_SIGN) == 0) { printf(EXIT_MSG); fflush(NULL); goto err; // free memory and quit } if( access( query_image, F_OK ) == -1 ) { printf(FILE_DOESNT_EXIST, query_image); goto query; } // extract query image features spLoggerPrintMsg(EXTRACT_QUERY_IMAGE_FEATURES_LOG); if ((query_features = improc->getImageFeatures(query_image, num_of_images, &query_num_of_features)) == NULL) { retval = -1; goto err_inside_loop; // error log is printed inside getImageFeatures } // print debug log if ((n = sprintf(string_holder, NUM_OF_EXTRACTED_FEATURES_DEBUG_LOG, query_num_of_features)) < 0) { spLoggerPrintError(GENERAL_ERROR_MSG, __FILE__, __func__, __LINE__); retval = -1; goto err_inside_loop; } spLoggerPrintDebug(string_holder, __FILE__, __func__, __LINE__); // print log message if ((n = sprintf(string_holder, SEARCING_SIMILAR_IMAGES_MSG, num_of_similar_images_to_find)) < 0) { spLoggerPrintError(GENERAL_ERROR_MSG, __FILE__, __func__, __LINE__); retval = -1; goto err_inside_loop; } spLoggerPrintMsg(string_holder); // find similar images to the query image closest_images = getKClosestImages(num_of_similar_images_to_find, knn, query_features, kd_tree, query_num_of_features, num_of_images); if (closest_images == NULL) { retval = -1; goto err_inside_loop; // error is printed to inside getKClosestImages } // show (display) closest_images images //need to show images if (minGui==true){ for (i=0; i<num_of_similar_images_to_find; i++){ //get file path of the images by the indexes in closest_images improc->showImage(all_images_paths[closest_images[i]]); } } // i.e. minGui==false, just need to print images path else{ print_result = PrintMinGuiFalse(query_image, num_of_similar_images_to_find, all_images_paths, closest_images); if (print_result == 0) { retval = -1; goto err_inside_loop; // error is printed inside } } // free memory before entering the loop again free(closest_images); if (query_features != NULL) { for (i=0; i<query_num_of_features; i++) { spPointDestroy(query_features[i]); } free(query_features); } } err_inside_loop: free(closest_images); // free query_features if (query_features != NULL) { for (i=0; i<query_num_of_features; i++) { spPointDestroy(query_features[i]); } free(query_features); } // done - destroy logger and free everything err: spLoggerDestroy(); // free the kd tree DestroyKDTreeNode(kd_tree); spConfigDestroy(config); // free all images paths if (all_images_paths != NULL) { for (i = 0; i < num_of_images; i ++) { free(all_images_paths[i]); } free(all_images_paths); } if (features_per_image != NULL) { // free features_per_image for (i = 0; i < last_extracted_feature; i ++) { if (features_per_image[i] != NULL) { for (j = 0; j < num_of_features_per_image[i]; j++) { spPointDestroy(features_per_image[i][j]); } } } free(features_per_image); } free(num_of_features_per_image); // must be freed after features_per_image if (improc != NULL) { delete improc; } return retval; }