SP_CONFIG_MSG spConfigGetFeatsPath(char* imagePath, const SPConfig config, int index) { int sprintfRes = 0; if (NULL == config || NULL == imagePath) { spLoggerPrintError(INVALID_ARGUMENT_ERROR_MSG, __FILE__, __func__, __LINE__); return SP_CONFIG_INVALID_ARGUMENT; } if (index >= config->spNumOfImages || 0 > index) { spLoggerPrintError(IMG_INDEX_OUT_OF_RANGE_ERROR_MSG, __FILE__, __func__, __LINE__); return SP_CONFIG_INDEX_OUT_OF_RANGE; } sprintfRes = sprintf(imagePath, FEATURS_PATH_TEMPLATE , config->spImagesDirectory, config->spImagesPrefix, index); /* check failure */ if (0 > sprintfRes) { spLoggerPrintError(SPRINTF_FAILED_ERROR_MSG, __FILE__, __func__, __LINE__); return SP_CONFIG_FAILED_CREATING_PATH; } return SP_CONFIG_SUCCESS; }
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; }
SPKDTreeNode spKDTreeCreateFromArray(SPKDArray kdArr, int prevDim, SPConfig config, SP_CONFIG_MSG *msg, int* problem ){ SPKDTreeNode res = NULL; SPKDArray *children; if (spKDArrayGetNumOfFeatures(kdArr)==1){ res = spKDTreeCreateLeaf(spKDArrayGetPoint(kdArr, 0)); if(!res){ spLoggerPrintError(ALLOC_FAIL, __FILE__, __FUNCTION__, __LINE__); spKDArrayDestroy(kdArr, ALL_ROWS); *problem = true; return NULL; } spKDArrayDestroy(kdArr, ALL_ROWS); return res; } else{ //** KD Array is larger than 1 point **// res = spKDTreeCreateNode(); if(!res){ spLoggerPrintError(ALLOC_FAIL, __FILE__, __FUNCTION__, __LINE__); spKDArrayDestroy(kdArr, ALL_ROWS); *problem = true; return NULL; } res->dim = spKDArrayFindSplitDim(kdArr, prevDim, config, msg); children = spKDArraySplit(kdArr, res->dim); if(!children){ spKDTreeDestroy(res); spKDArrayDestroy(kdArr, ALL_ROWS); *problem = true; return NULL; } res->val = spKDArrayGetMedianVal(children[LEFT], res->dim); spKDArrayDestroy(kdArr, ALL_ROWS); res->left = spKDTreeCreateFromArray(children[LEFT], res->dim, config, msg, problem); if(!(res->left)){ spKDTreeDestroy(res); spKDArrayDestroy(kdArr, ALL_ROWS); spKDMultiArrayDestroy(children, true, ALL_ROWS, true, ALL_ROWS); *problem = true; return NULL; } res->right = spKDTreeCreateFromArray(children[RIGHT], res->dim, config, msg, problem); if(!(res->right)){ spKDTreeDestroy(res); spKDArrayDestroy(kdArr, ALL_ROWS); spKDMultiArrayDestroy(children, true, ALL_ROWS, true, ALL_ROWS); *problem = true; return NULL; } spKDMultiArrayDestroy(children, false, false, false, false); return res; } }
/* * helper function for Init and split * function that allocates memory for a new SPKDArray with all its field * param: * KDArray: address to store the new SPKDArray * size: number of points to allocate * dim: number of dimentions * return: * -1 if an allocation error occurred * 1 otherwise */ int mallocForNewKdArray(SPKDArray* KDArray, int size, int dim){ int i; int j; //allocate memory for *KDArray if ((*KDArray = (SPKDArray)malloc(sizeof(**KDArray)))==NULL){ spLoggerPrintError(ALLOC_ERROR_MSG, __FILE__, __func__, __LINE__); return -1; } // allocate memory for *KDArray->array_of_points if ( ((*KDArray)->array_of_points = (SPPoint*)malloc(size*sizeof(SPPoint))) == NULL){ spLoggerPrintError(ALLOC_ERROR_MSG, __FILE__, __func__, __LINE__); free(*KDArray); return -1; } //allocate memory for *KDArray->matrix_of_sorted_indexes, this will be a d*n matrix, the i'th row is the indexes of the points in arr sorted according to their i'th dimension if ( ((*KDArray)->matrix_of_sorted_indexes = (int**)malloc(dim*sizeof(int*))) == NULL){ spLoggerPrintError(ALLOC_ERROR_MSG, __FILE__, __func__, __LINE__); for (i=0; i<size; i++){ spPointDestroy((*KDArray)->array_of_points[i]); } free((*KDArray)->array_of_points); free(*KDArray); return -1; } for (i=0; i<dim; i++){ if( ((*KDArray)->matrix_of_sorted_indexes[i]=(int*)malloc(size*sizeof(int))) == NULL){ spLoggerPrintError(ALLOC_ERROR_MSG, __FILE__, __func__, __LINE__); for (j=0; j<i; j++){ free((*KDArray)->matrix_of_sorted_indexes[j]); } free((*KDArray)->matrix_of_sorted_indexes); for (i=0; i<size; i++){ spPointDestroy((*KDArray)->array_of_points[j]); } free((*KDArray)->array_of_points); free(*KDArray); return -1; } } return 1; }
/* * @param config - the configs provider * @param imageIndex - index of the image * @param file - output parameter that will store the handler to feats file * @param mode - file open mode, as given to the OS * * The helper function is retrieving a handler to a matching feats file, for either reading or writing * * @return SP_CONFIG_SUCCESS on success * @return SP_CONFIG_UNKNOWN_ERROR on open failure */ SP_CONFIG_MSG getFeatsFile(SPConfig config, int imageIndex, FILE** file, const char* mode) { char featsPath[260]; SP_CONFIG_MSG msg = spConfigGetImageFeatsPath(featsPath, config, imageIndex); if (msg != SP_CONFIG_SUCCESS) { spLoggerPrintError(featsPathErr, __FILE__, __func__, __LINE__); return msg; } *file = fopen(featsPath, mode); if (*file == NULL) { msg = SP_CONFIG_UNKNOWN_ERROR; spLoggerPrintError(featsFileErr, __FILE__, __func__, __LINE__); return msg; } return SP_CONFIG_SUCCESS; }
/** * Help method that allocates a regular KDTreeNode. * the point is copied but not freed. * node doesn't have default parameters. * return a node unless allocation failed occurred then null is returned **/ SPKDTreeNode spKDTreeCreateNode(){ SPKDTreeNode node = (SPKDTreeNode)malloc(sizeof(*node)); if (!node){ spLoggerPrintError(ALLOC_FAIL, __FILE__, __FUNCTION__, __LINE__); return NULL; } node->dim=INVALID; node->left = NULL; node->right = NULL; node->data = NULL; return node; }
SP_CONFIG_MSG spConfigGetPCAPath(char* pcaPath, const SPConfig config) { int sprintfRes = 0; if (NULL == config || NULL == pcaPath) { spLoggerPrintError(INVALID_ARGUMENT_ERROR_MSG, __FILE__, __func__, __LINE__); return SP_CONFIG_INVALID_ARGUMENT; } sprintfRes = sprintf(pcaPath, PCA_PATH_TEMPLATE, config->spImagesDirectory, config->spPCAFilename); /* check failure */ if (0 > sprintfRes) { spLoggerPrintError(SPRINTF_FAILED_ERROR_MSG, __FILE__, __func__, __LINE__); return SP_CONFIG_FAILED_CREATING_PATH; } return SP_CONFIG_SUCCESS; }
SPKDTreeNode spKDTreeCreateLeaf(SPPoint point){ SPKDTreeNode leaf = (SPKDTreeNode)malloc(sizeof(*leaf)); if (!leaf){ spLoggerPrintError(ALLOC_FAIL, __FILE__, __FUNCTION__, __LINE__); return NULL; } leaf->dim = INVALID; leaf->val = INVALID; leaf->left = NULL; leaf->right = NULL; leaf->data = spPointCopy(point); return leaf; }
bool spConfigMinimalGui(const SPConfig config, SP_CONFIG_MSG* msg) { if (NULL == config) { spLoggerPrintError(INVALID_ARGUMENT_ERROR_MSG , __FILE__, __func__, __LINE__); *msg = SP_CONFIG_INVALID_ARGUMENT; return false; } *msg = SP_CONFIG_SUCCESS; return config->spMinimalGUI; }
SP_CONFIG_MSG spConfigGetLoggerFilename(char* loggerFilename, const SPConfig config) { if (NULL == config || NULL == loggerFilename) { spLoggerPrintError(INVALID_ARGUMENT_ERROR_MSG, __FILE__, __func__, __LINE__); return SP_CONFIG_INVALID_ARGUMENT; } strcpy(loggerFilename, config->spLoggerFilename); return SP_CONFIG_SUCCESS; }
int spConfigGetKNN(const SPConfig config, SP_CONFIG_MSG* msg) { if (NULL == config) { spLoggerPrintError(INVALID_ARGUMENT_ERROR_MSG, __FILE__, __func__, __LINE__); *msg = SP_CONFIG_INVALID_ARGUMENT; return NEGATIVE_VALUE_FOR_ERROR; } *msg = SP_CONFIG_SUCCESS; return config->spKNN; }
SP_LOGGER_LEVEL spConfigGetLoggerLevel(const SPConfig config, SP_CONFIG_MSG* msg) { if (NULL == config) { spLoggerPrintError(INVALID_ARGUMENT_ERROR_MSG, __FILE__, __func__, __LINE__); *msg = SP_CONFIG_INVALID_ARGUMENT; return SP_LOGGER_DEBUG_INFO_WARNING_ERROR_LEVEL; } *msg = SP_CONFIG_SUCCESS; return (SP_LOGGER_LEVEL) (config->spLoggerLevel - 1); }
KDTREE_SPLIT_METHOD spConfigGetKDTreeSplitMethod(const SPConfig config, SP_CONFIG_MSG* msg) { if (NULL == config) { spLoggerPrintError(INVALID_ARGUMENT_ERROR_MSG, __FILE__, __func__, __LINE__); *msg = SP_CONFIG_INVALID_ARGUMENT; return SPLIT_METHOD_RANDOM; } *msg = SP_CONFIG_SUCCESS; return config->spKDTreeSplitMethod; }
int* spFindImages(SPPoint* queryFeatures, const int querySize, const SPKDTreeNode root, const SPConfig config, SP_CONFIG_MSG *msg){ int i, knn, numOfSimilarImg, numOfImages; int *imageCounter, *res; SPListElement element; knn = spConfigGetKNN(config, msg); SPBPQueue q = spBPQueueCreate(knn); if(!q){ spLoggerPrintError(ALLOC_FAIL, __FILE__, __FUNCTION__, __LINE__); return NULL; } numOfImages = spConfigGetNumOfImages(config, msg); numOfSimilarImg = spConfigGetNumOfSimilarImages(config, msg); imageCounter = (int*)calloc(numOfImages, sizeof(int)); if(!imageCounter){ spLoggerPrintError(ALLOC_FAIL, __FILE__, __FUNCTION__, __LINE__); spBPQueueDestroy(q); return NULL; } /* count the num of neighbours of every * image for all features of the query */ for(i=0; i<querySize; i++){ spBPQueueClear(q); spKNNSearch(queryFeatures[i], root, q); while((element = spBPQueuePeek(q))!=NULL){ imageCounter[spListElementGetIndex(element)]+=1; spListElementDestroy(element); spBPQueueDequeue(q); } } spBPQueueClear(q); spBPQueueDestroy(q); res = getTopImagesFromArray(imageCounter, numOfImages, numOfSimilarImg); free(imageCounter); return res; }
/* * Internal help getter for the most wanted (similar) images. * @param: imageCounter: to bound the max value. * @param: numOfImages: the number of images to search from. * @param: numOfSimilarImg: according to configuration file - the number of wanted similar * images. * @return: * - NULL in case of an error * - int array that represent the top images */ int* getTopImagesFromArray(int* imageCounter, int numOfImages, const int numOfSimilarImg){ int i, j, maxIndex, maxValue, *res; res = (int*)malloc(numOfSimilarImg*sizeof(int)); if(!res){ spLoggerPrintError(ALLOC_FAIL, __FILE__, __FUNCTION__, __LINE__); return NULL; } for(i=0; i<numOfSimilarImg; i++){ maxValue = 0; maxIndex = i; for(j=0; j<numOfImages; j++){ if(imageCounter[j]>maxValue){ maxIndex = j; maxValue = imageCounter[j]; } } res[i] = maxIndex; imageCounter[maxIndex] = NOT_PRESENT; } return res; }
SP_CONFIG_MSG readImageFeaturesFromFile(SPPoint** imFeatures, int* numOfFeats, SPConfig config, int imageIndex) { FILE* featsFile; char warning[MAX_SIZE]; SP_CONFIG_MSG msg = getFeatsFile(config, imageIndex, &featsFile, "r+"); int i, j; if (msg != SP_CONFIG_SUCCESS) { sprintf(warning, "Feats file for image number %d doesn't exist\n", imageIndex); spLoggerPrintError(warning, __FILE__, __func__, __LINE__); return msg; } fscanf(featsFile, "%d", numOfFeats); *imFeatures = (SPPoint*) malloc(sizeof(SPPoint) * *numOfFeats); VERIFY_ALLOC(*imFeatures); for (i = 0; i < *numOfFeats; i++) { int index; int dimension; fscanf(featsFile, "%d,%d", &index, &dimension); double values[dimension]; for (j = 0; j < dimension; j++) { fscanf(featsFile, "%lf", &(values[j])); } SPPoint point = spPointCreate(values, dimension, index); VERIFY_ALLOC(point); (*imFeatures)[i] = point; } fclose(featsFile); return SP_CONFIG_SUCCESS; }
/** * A recursive function to construct the kd-tree */ KDTreeNode constructTree(KDArray mat, int size, int dim, int splitMethod, int lastLevelDim) { KDTreeNode newNode; KDArray left, right; SPPoint* p; int splitDim = -1; double medianVal; assert(size > 0); p = kdArrayGetPoints(mat); newNode = (KDTreeNode) malloc(sizeof(*newNode)); if (newNode == NULL ) { spLoggerPrintError(ALLOC_ERROR_MSG, __FILE__, __func__, __LINE__); return NULL ; } if (size == 1) { // creates a new leaf which represents a point newNode->dim = -1; newNode->val = -1; newNode->left = NULL; newNode->right = NULL; newNode->data = spPointCopy(p[0]); return newNode; } if (splitMethod == 0) { // RANDOM srand(time(NULL )); splitDim = rand() % dim; } else if (splitMethod == 1) { // MAX SPREAD double maxSpread; int i; maxSpread = 0; for (i = 0; i < dim; i++) { int minIndex, maxIndex; double spread; minIndex = kdArrayGet(mat, i, 0); maxIndex = kdArrayGet(mat, i, size - 1); spread = spPointGetAxisCoor(p[maxIndex], i) - spPointGetAxisCoor(p[minIndex], i); if (spread >= maxSpread) { maxSpread = spread; splitDim = i; } } } else if (splitMethod == 2) { // INCREMENTAL splitDim = (lastLevelDim + 1) % dim; } left = kdArrayInitEmpty(); if (left == NULL ) return NULL ; right = kdArrayInitEmpty(); if (right == NULL ) { kdArrayDestroy(left); return NULL ; } // compute the median to split according to it medianVal = spPointGetAxisCoor(p[kdArrayGet(mat, splitDim, (size - 1) / 2)], splitDim); kdArraySplit(mat, splitDim, left, right); newNode->dim = splitDim; newNode->val = medianVal; // recursively create the left sub-tree newNode->left = constructTree(left, kdArrayGetSize(left), dim, splitMethod, splitDim); // recursively create the right sub-tree newNode->right = constructTree(right, kdArrayGetSize(right), dim, splitMethod, splitDim); newNode->data = NULL; // not a leaf // free data not needed anymore kdArrayDestroy(left); kdArrayDestroy(right); return newNode; }
int Split(SPKDArray kdArr, int coor, SPKDArray* left_array, SPKDArray* right_array){ int n; // number of points in kdArr int d; // number of dimensions of each point in kdArr int num_of_left_points; // number of points that will be in the left half int num_of_right_points; // number of points that will be in the right half int* is_index_in_left; // array of 0's and 1's. value is 1 if the point in this index is in left half int* map_indexes; // mapping from the indexes of the points in kdArr to the indexes in left or right half int helper_function_result; // holds the result of a call to a helper function int index; int i, j; int L_cnt; //index counter for left_points int R_cnt; //index counter for right_points //check validation of arguments if (coor<0){ spLoggerPrintError(INVALID_ARG_ERROR, __FILE__, __func__, __LINE__); spLoggerPrintDebug(PARAMETER_COOR_INVALID, __FILE__, __func__, __LINE__); return -1; } if (kdArr==NULL){ spLoggerPrintError(INVALID_ARG_ERROR, __FILE__, __func__, __LINE__); spLoggerPrintDebug(PARAMETER_KDARR_INVALID, __FILE__, __func__, __LINE__); return -1; } //initialize n and d n = kdArr->n; d = kdArr->d; //initialize num_of_left_points and num_of_right_points if (n%2==0){ num_of_left_points = n/2; } else{ num_of_left_points = (n+1)/2; } num_of_right_points = n - num_of_left_points; //allocate memory for *left_array -> this is creating a new SPKDArray if ( (helper_function_result = mallocForNewKdArray(left_array, num_of_left_points, d)) == -1){ //free memory of left_array is in mallocForNewKdArray return -1; } //allocate memory for *right_array -> this is creating a new SPKDArray if ( (helper_function_result = mallocForNewKdArray(right_array, num_of_right_points, d)) == -1){ //free memory of right_array is in mallocForNewKdArray destroyKDArray(*left_array); return -1; } //initialize n and d for left_array and right_array (*left_array)->d = d; (*left_array)->n = num_of_left_points; (*right_array)->d = d; (*right_array)->n = num_of_right_points; //allocate memory for is_index_in_left if ( (is_index_in_left = (int*)malloc(n*sizeof(int))) == NULL){ spLoggerPrintError(ALLOC_ERROR_MSG, __FILE__, __func__, __LINE__); destroyKDArray(*left_array); destroyKDArray(*right_array); return -1; } // fill is_index_in_left for (i=0; i<num_of_left_points; i++){ is_index_in_left[kdArr->matrix_of_sorted_indexes[coor][i]] = 1; } for (i=num_of_left_points; i<n; i++){ is_index_in_left[kdArr->matrix_of_sorted_indexes[coor][i]] = 0; } // fill left->array_of_points and right->array_of_points L_cnt=0; //index counter for left_points R_cnt=0; //index counter for right_points for (i=0; i<n; i++){ // i= index counter for is_index_in_left if (is_index_in_left[i]==1){ if( ((*left_array)->array_of_points[L_cnt]= spPointCopy(kdArr->array_of_points[i])) == NULL){ destroyKDArray(*left_array); destroyKDArray(*right_array); free(is_index_in_left); return -1; } L_cnt++; } else{ //is_index_in_left[i]==0 if( ((*right_array)->array_of_points[R_cnt]= spPointCopy(kdArr->array_of_points[i])) ==NULL){ destroyKDArray(*left_array); destroyKDArray(*right_array); free(is_index_in_left); return -1; } R_cnt++; } } //allocate memory for map_indexes if ( (map_indexes= (int*)malloc(n*sizeof(int)))==NULL ){ spLoggerPrintError(ALLOC_ERROR_MSG, __FILE__, __func__, __LINE__); destroyKDArray(*left_array); destroyKDArray(*right_array); free(is_index_in_left); return -1; } //fill map_indexes L_cnt=0; //counter for left R_cnt=0; //counter for right for (i=0; i<n; i++){ if (is_index_in_left[i]==1){ //i is an index that belongs to left map_indexes[i] = L_cnt; L_cnt++; } else{ //i is an index that belongs to right map_indexes[i] = R_cnt; R_cnt++; } } //fill left_array->matrix_of_sorted_indexes and right_array->matrix_of_sorted_indexes L_cnt=0; //counter for left R_cnt=0; //counter for right for (i=0; i<d; i++){ //for number of dimensions for(j=0; j<n; j++){ //for number of points index = kdArr->matrix_of_sorted_indexes[i][j]; if (is_index_in_left[index]==1){ //the index to map belongs to left (*left_array)->matrix_of_sorted_indexes[i][L_cnt] = map_indexes[index]; L_cnt++; } else{ //the index to map belongs to right (*right_array)->matrix_of_sorted_indexes[i][R_cnt] = map_indexes[index]; R_cnt++; } } //reset counters R_cnt=0; L_cnt=0; } //free memory and return free(map_indexes); free(is_index_in_left); return 1; }
SPKDArray Init(SPPoint* arr, int size){ SPKDArray KDArray; int d; // d = the dimension of the points (assuming dimension is the same for all points) double** index_val_arr; //double array containing n rows. each row contains the index and the value of a specific coordinate in the point of that index int i,j; int malloc_result; // holds the result of the call to mallocForNewKdArray //check validation of the parameters if (size<1){ spLoggerPrintError(INVALID_ARG_ERROR, __FILE__, __func__, __LINE__); spLoggerPrintDebug(PARAMETER_SIZE_INVALID, __FILE__, __func__, __LINE__); return NULL; } if (arr==NULL){ spLoggerPrintError(INVALID_ARG_ERROR, __FILE__, __func__, __LINE__); spLoggerPrintDebug(PARAMETER_ARR_INVALID, __FILE__, __func__, __LINE__); return NULL; } //initialize d d = spPointGetDimension(arr[0]); // allocate memory for KDArray and its fields malloc_result = mallocForNewKdArray(&KDArray, size, d); if (malloc_result==-1){ // the memory freeing would already be done inside mallocForInitKdArray return NULL; } //copy each point from arr to KDArray->array_of_points for (i=0; i<size; i++){ KDArray->array_of_points[i] = spPointCopy(arr[i]); //spPointCopy returns NULL if an allocation error occurred if (KDArray->array_of_points[i] == NULL){ spLoggerPrintError(GENERAL_ERROR_MSG, __FILE__, __func__, __LINE__); spLoggerPrintDebug(SPPOINTCOPY_RETURNED_NULL, __FILE__, __func__, __LINE__); destroyKDArray(KDArray); return NULL; } } //allocate memory for index_val_arr: n rows, 2 columns if ( (index_val_arr = (double**)malloc(size*sizeof(double*))) == NULL){ spLoggerPrintError(ALLOC_ERROR_MSG, __FILE__, __func__, __LINE__); destroyKDArray(KDArray); return NULL; } for (i=0; i<size; i++){ if( (index_val_arr[i]=(double*)malloc(2*sizeof(double))) == NULL){ spLoggerPrintError(ALLOC_ERROR_MSG, __FILE__, __func__, __LINE__); for (j=0; j<i; j++){ free(index_val_arr[j]); } free(index_val_arr); destroyKDArray(KDArray); return NULL; } } // for each coordinate for (i=0; i<d; i++){ // i=coordinate // fill index and value of coordinate to val_index_arr for (j=0; j<size; j++){ //j=index of point index_val_arr[j][0] = (double)j; index_val_arr[j][1] = spPointGetAxisCoor(arr[j],i); } /* sort the rows in index_val_arr by the value in the second column, * meaning by the value of the coordinate of each point. * the first column will be the indexes of the points sorted by the values of the coordinate */ qsort(index_val_arr, size, sizeof(index_val_arr[0]), copmareByValue); // fill the sorted indexes in to KDArray->Array for (j=0; j<size; j++){ //j=index of point KDArray->matrix_of_sorted_indexes[i][j] = (int)index_val_arr[j][0]; } } // initialize n and d KDArray->n = size; KDArray->d = d; for (j=0; j<size; j++){ free(index_val_arr[j]); } free(index_val_arr); return KDArray; }
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; }
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; }