예제 #1
0
파일: KDTree.c 프로젝트: orrbarkat/c
/**
 * internal help method to find the k nearest neighbors
 */
void spKNNSearch(SPPoint queryFeature, const SPKDTreeNode node, SPBPQueue q){
    SPListElement element;
    int index, distance;
    bool distanceFlag = false;
    if(!node){
        return;
    }
    if(node->dim==INVALID){				//** this is a leaf **//
        index = spPointGetIndex(node->data);
        distance = spPointL2SquaredDistance(queryFeature, node->data);
        element = spListElementCreate(index, distance);
        spBPQueueEnqueue(q, element);
        spListElementDestroy(element);
        return;
    }
    			//** go to the left sub tree **//
    if(spPointGetAxisCoor(queryFeature, node->dim)<= node->val){
        spKNNSearch(queryFeature, node->left, q);
        distance = pow((spPointGetAxisCoor(queryFeature,
        									node->dim) - node->val),2);
        distanceFlag = distance < spBPQueueMaxValue(q);
        if(!spBPQueueIsFull(q) || distanceFlag){
            spKNNSearch(queryFeature, node->right, q);
        }
    }else{
        spKNNSearch(queryFeature, node->right, q);
        distance = pow((spPointGetAxisCoor(queryFeature,
        									node->dim) - node->val),2);
        distanceFlag = distance < spBPQueueMaxValue(q);
        if(!spBPQueueIsFull(q) || distanceFlag){
            spKNNSearch(queryFeature, node->left, q);
        }
    }
    return;
}
예제 #2
0
void SPKDTreeKNNRecursive(SPKDTreeNode treeNode, SPPoint p, SPBPQueue bpq, SP_KDTREE_MSG* msg)
{
	SPListElement listElement;
	SPPoint treePoint;
	bool searchedLeft;
	double dist;

	if(bpq == NULL || treeNode == NULL)
	{
		*msg = SP_KDTREE_INVALID_ARGUMENT;
		return;
	}

	// If treeNode is a leaf
	if(treeNode->left == NULL && treeNode->right == NULL)
	{
		treePoint = *(treeNode->data);
		listElement = spListElementCreate(spPointGetIndex(treePoint), spPointL2SquaredDistance(p, treePoint));
		spBPQueueEnqueue(bpq, listElement);
		spListElementDestroy(listElement);
		*msg = SP_KDTREE_SUCCESS;
		return;
	}

	// Turn to search the tree that would've contain the point p (if it was in the tree)
	if(spPointGetAxisCoor(p, treeNode->dim) <= treeNode->val)
	{
		searchedLeft = true;
		SPKDTreeKNNRecursive(treeNode->left, p, bpq, msg);
		if (*msg != SP_KDTREE_SUCCESS)
			return;
	}
	else
	{
		searchedLeft = false;
		SPKDTreeKNNRecursive(treeNode->right, p, bpq, msg);
		if (*msg != SP_KDTREE_SUCCESS)
			return;
	}

	// dist = |treeNode.val - p[treeNode.dim]|
	dist = treeNode->val - spPointGetAxisCoor(p, treeNode->dim);
	if(dist < 0)
		dist *= -1;
	//dist *= dist;

	if(!spBPQueueIsFull(bpq) || dist < spBPQueueMaxValue(bpq))
	{
		if(searchedLeft)
			SPKDTreeKNNRecursive(treeNode->right, p, bpq, msg);
		else
			SPKDTreeKNNRecursive(treeNode->left, p, bpq, msg);
	}
	
}
예제 #3
0
bool pointGettersTest() {
	double data1[3] = { 1.0, 1.0, 2.0 };
	int dim1 = 3;
	int index1 = 1;
	SPPoint p = spPointCreate((double *)data1, dim1, index1);
	ASSERT_TRUE(spPointGetAxisCoor(p, 0) == 1.0);
	ASSERT_TRUE(spPointGetAxisCoor(p, 1) == 1.0);
	ASSERT_FALSE(spPointGetAxisCoor(p, 2) == 1.0);
	ASSERT_TRUE(spPointGetAxisCoor(p, 2) == 2.0);
	ASSERT_TRUE(spPointGetIndex(p) == 1);
	ASSERT_TRUE(spPointGetDimension(p) == 3);
	spPointDestroy(p);
	return true;
}
예제 #4
0
// Comparator for aforementioned sorting
int SPSortingHelperCompare(const void* t1, const void* t2)
{
	SPSortingHelper *s1, *s2;
	assert(t1 != NULL && t2 != NULL);
	s1 = (SPSortingHelper*) t1;
	s2 = (SPSortingHelper*) t2;
	if (spPointGetAxisCoor((*s1)->point, (*s1)->dim) == spPointGetAxisCoor((*s2)->point, (*s2)->dim)) {
		return spPointGetIndex((*s1)->point) - spPointGetIndex((*s2)->point);
	}
	else if (spPointGetAxisCoor((*s1)->point, (*s1)->dim) > spPointGetAxisCoor((*s2)->point, (*s2)->dim)) {
		return 1;
	}
	return -1;
}
예제 #5
0
//Checks if copy Works
bool pointBasicCopyTest() {
	double data[2] = { 1.0, 1.0 };
	int dim = 2;
	int index = 1;
	SPPoint p = spPointCreate(data, dim, index);
	SPPoint q = spPointCopy(p);
	ASSERT_TRUE(spPointGetIndex(p) == spPointGetIndex(q));
	ASSERT_TRUE(spPointGetDimension(p) == spPointGetDimension(q));
	int i;
	for (i = 0; i < spPointGetDimension(p); i++) {
		ASSERT_TRUE(spPointGetAxisCoor(p, i) == spPointGetAxisCoor(q, i));
	}
	spPointDestroy(p);
	spPointDestroy(q);
	return true;
}
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;
}
예제 #7
0
/**
 * Given a kd-tree and a point p, the function stores the nearest neighbors of p to bpq
 *
 * @param curr - the kd-tree containing the points
 * @param bpq - the bounded priority queue to store the nearest neighbors in
 * @param p - the point to find the nearest neighbors to
 *
 * does nothing if curr == NULL or bpq == NULL or p == NULL
 */
void nearestNeighbors(KDTreeNode curr, SPBPQueue bpq, SPPoint p) {
	SPListElement node;
	SPPoint q;
	bool isLeft;
	double coorDis;
	if (curr == NULL || bpq == NULL || p == NULL )
		return;

	q = curr->data;

	/* Add the current point to the BPQ. Note that this is a no-op if the
	 * point is not as good as the points we've seen so far.*/
	if (curr->dim == -1) {
		int index;
		double dis;

		index = spPointGetIndex(q);
		dis = spPointL2SquaredDistance(p, curr->data);
		node = spListElementCreate(index, dis);
		spBPQueueEnqueue(bpq, node);
		spListElementDestroy(node);
		return;
	}

	/* Recursively search the half of the tree that contains the test point. */
	if (spPointGetAxisCoor(p, curr->dim) <= curr->val) {
		nearestNeighbors(curr->left, bpq, p);
		isLeft = true;
	} else {
		nearestNeighbors(curr->right, bpq, p);
		isLeft = false;
	}

	/* If the candidate hypersphere crosses this splitting plane, look on the
	 * other side of the plane by examining the other subtree*/
	coorDis = abs(spPointGetAxisCoor(p, curr->dim) - curr->val);
	if (!spBPQueueIsFull(bpq) || coorDis*coorDis < spBPQueueMaxValue(bpq)) {
		if (isLeft)
			nearestNeighbors(curr->right, bpq, p);
		else
			nearestNeighbors(curr->left, bpq, p);
	}

}
예제 #8
0
	double spPointL2SquaredDistance(SPPoint p, SPPoint q){
		double sum = 0.0;   // Holds temporary sum
		double pVal;  // holds current p_i value
		double qVal;  // holds current q_i value
		double pqSub; // holds current p_i-q_i value
		int dim;      // dim of p and q
		int i;

		assert(p!=NULL && q!=NULL && p->dim == q->dim);

		dim = p->dim;
		for (i=0; i<dim; i++){
			pVal = spPointGetAxisCoor(p, i); // get current p_i value
			qVal = spPointGetAxisCoor(q, i); // get current q_i value
			pqSub = pVal-qVal;
			sum += (pqSub*pqSub);
		}
		return sum;
	}
예제 #9
0
/**
 * prints the tree for debuging
 */
void printTree(KDTreeNode kdTree) {
	int i;
	if (kdTree == NULL ) {
		return;
	}
	printf(" (");
	printTree(kdTree->left);
	if (kdTree->data == NULL )
		printf("dim: %d, val: %f", kdTree->dim, kdTree->val);
	else {
		printf("index: %d,point: ", spPointGetIndex(kdTree->data));
		for (i = 0; i < spPointGetDimension(kdTree->data); i++) {

			printf("%lf,", spPointGetAxisCoor(kdTree->data, i));
		}
	}
	printTree(kdTree->right);
	printf(" )");
}
예제 #10
0
SP_CONFIG_MSG writeImageFeaturesToFile(SPPoint* imFeatures, int numOfFeats,
		SPConfig config, int imageIndex) {
	FILE* featsFile;
	SP_CONFIG_MSG msg = getFeatsFile(config, imageIndex, &featsFile, "w+");
	int i, j;
	if (msg != SP_CONFIG_SUCCESS) {
		return msg;
	}

	fprintf(featsFile, "%d\n", numOfFeats);
	for (i = 0; i < numOfFeats; i++) {
		SPPoint point = imFeatures[i];
		fprintf(featsFile, "%d,%d\n", spPointGetIndex(point),
				spPointGetDimension(point));
		for (j = 0; j < spPointGetDimension(point); j++) {
			fprintf(featsFile, "%f\n", spPointGetAxisCoor(point, j));
		}
	}

	fflush(featsFile);
	fclose(featsFile);
	return SP_CONFIG_SUCCESS;
}
예제 #11
0
/**
 * 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;
}
예제 #12
0
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;
}
예제 #13
0
SPKDTreeNode SPKDTreeInitHelp(SPKDArray kdArr, int size, SP_KDTREE_SPLIT_METHOD splitMethod, int lastIndex, SP_KDTREE_MSG * msg)
{
	int dim, dims, maxSpread, maxSpreadIndex, spread, i, minVal, maxVal;
	SP_KDARRAY_MSG kdArrMsg;
	SPKDArray* split;
	SPKDTreeNode ret;
	SPPoint workPoint;
	assert(msg != NULL);
	if (kdArr == NULL || size <= 0 || lastIndex < -1)
	{
		*msg = SP_KDTREE_INVALID_ARGUMENT;
		return NULL;
	}
	// Allocate memory
	ret = (SPKDTreeNode)malloc(sizeof(*ret));
	if (ret == NULL)
	{
		*msg = SP_KDTREE_ALLOC_FAIL;
		return NULL;
	}
	if (size == 1)
	{
		// Returned node will be a leaf
		ret->dim = -1;
		ret->val = -1.0;
		ret->left = (ret->right = NULL);
		ret->data = (SPPoint*)malloc(sizeof(SPPoint));
		if (ret->data == NULL)
		{
			*msg = SP_KDTREE_ALLOC_FAIL;
			free(ret);
			return NULL;
		}
		*(ret->data) = SPKDArrayGetPointByDim(kdArr, 0, -1, &kdArrMsg); // Gets the only point in the KD-Array
	}
	else
	{
		// Returned node is not a leaf
		dims = SPKDArrayGetDims(kdArr, &kdArrMsg);
		
		// Calculate the splitting dimension
		switch (splitMethod)
		{
		case SP_KDTREE_MAX_SPREAD:
			maxSpread = 0;
			maxSpreadIndex = 0;
			// calculate the maximum spread dimension
			for (i = 0; i < dims; i++)
			{
				workPoint = SPKDArrayGetPointByDim(kdArr, 0, i, &kdArrMsg);
				minVal = spPointGetAxisCoor(workPoint, i);
				spPointDestroy(workPoint);
				workPoint = SPKDArrayGetPointByDim(kdArr, size - 1, i, &kdArrMsg);
				maxVal = spPointGetAxisCoor(workPoint, i);
				spPointDestroy(workPoint);
				spread = maxVal - minVal;
				if (spread > maxSpread)
				{
					maxSpread = spread;
					maxSpreadIndex = i;
				}
			}
			dim = maxSpreadIndex;
			break;
		case SP_KDTREE_RANDOM:
			dim = rand() % dims;
			break;
		case SP_KDTREE_INCREMENTAL:
			dim = (lastIndex + 1) % dims;
			break;
		}
		
		split = SPKDArraySplit(kdArr, dim, &kdArrMsg); // Split the KD-Array according to the splitting dimension
		workPoint = SPKDArrayGetPointByDim(split[0], SPKDArrayGetSize(split[0], &kdArrMsg) - 1, dim, &kdArrMsg);
		ret->dim = dim;
		ret->val = spPointGetAxisCoor(workPoint, dim);
		
		// Employ recursion to calculate subtrees
		ret->left = SPKDTreeInitHelp(split[0], SPKDArrayGetSize(split[0], &kdArrMsg), splitMethod, lastIndex + 1, msg);
		ret->right = SPKDTreeInitHelp(split[1], SPKDArrayGetSize(split[1], &kdArrMsg), splitMethod, lastIndex + 1, msg);
		ret->data = NULL;
		
		// Get rid of unneeded memory
		SPKDArrayDestroy(split[0]);
		SPKDArrayDestroy(split[1]);
		free(split);
		spPointDestroy(workPoint);
	}
	
	// All done
	*msg = SP_KDTREE_SUCCESS;
	return ret;
}
예제 #14
0
/****
 * The purpose of the test is to compare the features before and after the saving.
 */
bool main_saveLoad()
{
	LoadedFeatures loadedFeatures = NULL;
	LoadedFeatures features = NULL;

	int numOfImages = 0;
	int numOfFeatures = 0;
	int numOfCoords = 0;

	SPPoint * orgArr = NULL;
	SPPoint pointOrg = NULL;

	SPPoint * loadedArr = NULL;
	SPPoint pointLoad = NULL;

	SP_CONFIG_MSG msg;
	char fileName[30] = "./tests/config/saveLoad.cfg";
	SPConfig conf = spConfigCreate(fileName, &msg);
	ASSERT_TRUE(NULL != conf);

	/****
	 * Allocates, creates(by imageProc) and saves the features
	 ****/
	features = allocateFeaturesList(conf);
	ASSERT_TRUE(NULL != features);
	ASSERT_TRUE(true == debugSaveFeatures(conf, features));

	/****
	 * Load the features from the files
	 *****/
	loadedFeatures = allocateFeaturesList(conf);
	ASSERT_TRUE(NULL != loadedFeatures);
	ASSERT_TRUE(true == loadFeatures(conf, loadedFeatures));


	/****************************************
	 * Compare original and loaded features *
	 ****************************************/
	ASSERT_TRUE(getFeaturesImagesNumber(features) ==
							getFeaturesImagesNumber(loadedFeatures));


	numOfImages = getFeaturesImagesNumber(features);
	for (int index_image=0; index_image<numOfImages ; index_image++)
	{
		numOfFeatures = getFeaturesNumber(features, index_image);
		ASSERT_TRUE(numOfFeatures == getFeaturesNumber(loadedFeatures, index_image));


		for (int index_feature=0; index_feature<numOfFeatures ; index_feature++)
		{
			orgArr = getFeatureArray(features, index_image);
			loadedArr = getFeatureArray(loadedFeatures, index_image);

			pointOrg = orgArr[index_feature];
			pointLoad = loadedArr[index_feature];


			numOfCoords = spPointGetDimension(pointOrg);
			ASSERT_TRUE(numOfCoords == spPointGetDimension(pointLoad));

			ASSERT_TRUE(spPointGetIndex(pointOrg) == spPointGetIndex(pointLoad));


			for (int index_coor=0; index_coor<numOfCoords ; index_coor++)
			{
				ASSERT_TRUE(spPointGetAxisCoor(pointOrg, index_coor) ==
								spPointGetAxisCoor(pointLoad, index_coor));
			}
		}

	}

	loadedFeaturesDestroy(loadedFeatures);
	loadedFeaturesDestroy(features);

	return true;
}