示例#1
0
void MultiMatch_delete(MultiMatch* self) 
{
	if (self) {
		ArrayList_delete(self->keySets);
		KDTree_delete(self->globalKeyKD);
		ArrayList_delete(self->globalKeys);
		ArrayList_delete(self->globalMatches);
		PtrMap_delete(self->matchSets, NULL);
		ArrayList_delete(self->filteredMatchSets);
		free(self);
	}
}
示例#2
0
// Limited Best-Bin-First k-d-tree nearest neighbour search.
//
// (Using the algorithm described in the paper "Shape indexing using
// approximate nearest-neighbour search in high-dimensional spaces",
// available at http://www.cs.ubc.ca/spider/lowe/papers/cvpr97-abs.html)
//
// Find the approximate nearest neighbour to the hyperspace point 'target'
// within the kd-tree using 'searchSteps' tail recursions at most (each
// recursion deciding about one neighbours' fitness).
//
// After return 'resDist' contains the absolute distance of the
// approximate nearest neighbour from the target point. The approximate
// nearest neighbour is returned.
SortedLimitedList* KDTree_NearestNeighbourListBBF (KDTree* self, IKDTreeDomain* target,
					   int q, int searchSteps)
{
	ArrayList* hrl = ArrayList_new0(HyperRectangle_delete);

	HyperRectangle* hr =
		HyperRectangle_CreateUniverseRectangle (IKDTreeDomain_GetDimensionCount(target));
		
	ArrayList_AddItem(hrl, hr);

	SortedLimitedList* best = SortedLimitedList_new (q, KDTreeBestEntry_delete);
	best->comparator.compareTo = (int ( *)(IComparator *,const void *,const void *)) KDTreeBestEntry_CompareTo;
	SortedLimitedList* searchHr = SortedLimitedList_new (searchSteps, KDTreeHREntry_delete);
	searchHr->comparator.compareTo = (int ( *)(IComparator *,const void *,const void *))KDTreeHREntry_CompareTo;

	int dummyDist;
	/*IKDTreeDomain* nearest = */KDTree_NearestNeighbourListBBFI (self, best, q, target, hr,
								      INT_MAX, &dummyDist, searchHr, &searchSteps,
								      hrl);

	SortedLimitedList_delete(searchHr);

	int i;
	for(i=0; i<SortedLimitedList_Count(best); i++) {
		KDTreeBestEntry* be = (KDTreeBestEntry*) SortedLimitedList_GetItem(best, i);
		be->distance = sqrt ((double)be->distanceSq);
	}

	ArrayList_delete(hrl);

	return (best);
}
示例#3
0
SortedLimitedList* KDTree_NearestNeighbourList (KDTree* self, IKDTreeDomain* target,
					double* resDist, int q)
{
	ArrayList* hrl = ArrayList_new0(HyperRectangle_delete);

	HyperRectangle* hr =
		HyperRectangle_CreateUniverseRectangle (IKDTreeDomain_GetDimensionCount(target));

	ArrayList_AddItem(hrl, hr);

	SortedLimitedList* best = SortedLimitedList_new (q, KDTreeBestEntry_delete);
	best->comparator.compareTo = (int ( *)(IComparator *,const void *,const void *))KDTreeBestEntry_CompareTo;

	/*IKDTreeDomain* nearest = */KDTree_NearestNeighbourListI (self, best, q, target, hr,
							       Double_PositiveInfinity, resDist, hrl);
	*resDist = sqrt (*resDist);

	int i;
	for(i=0; i<SortedLimitedList_Count(best); i++) {
		KDTreeBestEntry* be = (KDTreeBestEntry*) SortedLimitedList_GetItem(best, i);
		be->distance = sqrt (be->distance);
	}
       
	ArrayList_delete(hrl);

	return (best);
}
示例#4
0
int main (int argc, char* argv[])
{
	ArrayList* al = ArrayList_new0 (FilterPoint_delete);
	Random* rnd = Random_new0 ();

	int n;
	for (n = 0 ; n < 10 ; ++n) {
		FilterPoint* p = FilterPoint_new0 ();
	
		p->x = Random_NextDouble(rnd) * 400.0;
		p->y = Random_NextDouble(rnd) * 400.0;
	
		ArrayList_AddItem(al, p);
	}
	int i;
	for(i=0; i<ArrayList_Count(al); i++) {
		FilterPoint* p = ArrayList_GetItem(al, i);
		WriteLine ("%f %f # GNUPLOT1", p->x, p->y);
	}

	AreaFilter* conv = AreaFilter_new0 ();
	ArrayList* hull = AreaFilter_CreateConvexHull(conv, al);
	
	WriteLine ("\nhull: %d elements", ArrayList_Count(hull));
	int j;
	for(j=0; j<ArrayList_Count(hull); j++) {
		FilterPoint* p = ArrayList_GetItem(hull, j);
		WriteLine ("%f %f # GNUPLOT2", p->x, p->y);
	}
	
	WriteLine ("\npolygon area: %f", AreaFilter_PolygonArea(conv, hull));
	ArrayList_delete(al);
	return 0;
}
示例#5
0
void MatchSet_delete(MatchSet* self)
{
    if (self) {
	ArrayList_delete(self->matches);
	KeypointXMLList_delete(self->keys1);
	KeypointXMLList_delete(self->keys2);
	free(self);
    }
}
示例#6
0
// Build a kd-tree from a list of elements. All elements must implement
// the IKDTreeDomain interface and must have the same dimensionality.
KDTree* KDTree_CreateKDTree (ArrayList* exset)
{
	if (ArrayList_Count(exset) == 0)
		return (NULL);
	
	KDTree* cur = KDTree_new0 ();
	cur->dr = KDTree_GoodCandidate (exset, &cur->splitDim);

	ArrayList* leftElems = ArrayList_new0 (NULL);
	ArrayList* rightElems = ArrayList_new0 (NULL);
	
	// split the exemplar set into left/right elements relative to the
	// splitting dimension
	double bound = IKDTreeDomain_GetDimensionElement (cur->dr, cur->splitDim);
	int i;
	for(i=0; i<ArrayList_Count(exset); i++) {
		IKDTreeDomain* dom = (IKDTreeDomain*) ArrayList_GetItem(exset, i);
		// ignore the current element
		if (dom == cur->dr)
			continue;
		
		if (IKDTreeDomain_GetDimensionElement (dom, cur->splitDim) <= bound) {
			ArrayList_AddItem(leftElems, dom);
		} else {
			ArrayList_AddItem(rightElems, dom);
		}
	}

	// recurse
	cur->left = KDTree_CreateKDTree (leftElems);
	cur->right = KDTree_CreateKDTree (rightElems);

	ArrayList_delete(leftElems);
	ArrayList_delete(rightElems);
	
	return (cur);
}
示例#7
0
// Find the nearest neighbour to the hyperspace point 'target' within the
// kd-tree. After return 'resDist' contains the absolute distance from the
// target point. The nearest neighbour is returned.
IKDTreeDomain* KDTree_NearestNeighbour (KDTree* self, IKDTreeDomain* target, double* resDist)
{
	ArrayList* hrl = ArrayList_new0(HyperRectangle_delete);

	HyperRectangle* hr =
		HyperRectangle_CreateUniverseRectangle (IKDTreeDomain_GetDimensionCount(target));
	
	ArrayList_AddItem(hrl, hr);

	IKDTreeDomain* nearest = KDTree_NearestNeighbourI (self, target, hr,
							   Double_PositiveInfinity, resDist, hrl);
	*resDist = sqrt (*resDist);

	ArrayList_delete(hrl);

	return (nearest);
}
示例#8
0
ArrayList* MatchKeys_FindMatchesBBF (ArrayList* keys1, ArrayList* keys2)
{
	// TODO: swap so smaller list is searched.
    
	ArrayList* al = ArrayList_new0 (NULL);
	int i;
	for (i=0; i<ArrayList_Count(keys2); i++)
		ArrayList_AddItem (al, ArrayList_GetItem(keys2, i));
	
	KDTree* kd = KDTree_CreateKDTree (al);

	ArrayList_delete(al);

	ArrayList* matches = ArrayList_new0 (Match_delete);
	int j;
	for (j=0; j<ArrayList_Count(keys1); j++) {
		KeypointN* kp = (KeypointN*) ArrayList_GetItem(keys1, j);
		ArrayList* kpNNList = (ArrayList*)KDTree_NearestNeighbourListBBF (kd, (IKDTreeDomain*)kp, 2, 40);
		
		if (ArrayList_Count(kpNNList) < 2)
			FatalError ("BUG: less than two neighbours!");

		KDTreeBestEntry* be1 = (KDTreeBestEntry*) ArrayList_GetItem(kpNNList, 0);
		KDTreeBestEntry* be2 = (KDTreeBestEntry*) ArrayList_GetItem(kpNNList, 1);

		if ((be1->distance / be2->distance) > 0.6)
			continue;
		
		KeypointN* kpN = (KeypointN*)KDTreeBestEntry_Neighbour(be1);
		
		ArrayList_AddItem(matches, Match_new (kp, kpN, be1->distance, be2->distance));

		/*
		WriteLine ("(%d,%d) (%d,%d) %d, 2nd: %d", (int)(kp->x + 0.5),
			   (int)(kp->y + 0.5), (int)(kpN->x + 0.5),
			   (int)(kpN->y + 0.5), be1->distance, be2->distance);
		*/
	}
	
	return (matches);
}
示例#9
0
void _List_delete(_List *list) {
	ArrayList_delete(list->data);
	free(list);
}
示例#10
0
int main (int argc, char* argv[])
{
	WriteLine ("autopano-sift, Automatic panorama generation program\n");
  
	if (argc+1 < 3) {
		Usage ();
		exit (1);
	}

	// output to stdout flag
	bool streamout = false;

	// Automatic pre-aligning of images
	bool preAlign = false;
	int bottomDefault = -1;
	int generateHorizon = 0;
  
	// Use RANSAC algorithm match filtration.
	bool useRansac = true;
  
	// Use area based weighting for final match selection.
	bool useAreaFiltration = true;
  
	// Truncate match coordinates to integer numbers.
	bool useIntegerCoordinates = false;
  
	// Use the absolute pathname of the image files in the output PTO
	// file.
	bool useAbsolutePathnames = false;
  
	// Use "keep-best" filtration, keep the maxMatches best.
	int maxMatches = 16;	// default: 16
  
	// Refinement options
	bool refine = false;
	bool refineMiddle = true;
	bool keepUnrefinable = true;
  
	int optionCount = 0;
	int optionN = 1;
	while (optionN < argc &&
	       strlen(argv[optionN]) >= 2 
		   && argv[optionN][0] == '-'
		   && argv[optionN][1] == '-')
		{
			char* optionStr = argv[optionN];

			if (strcmp (optionStr, "--ransac") == 0) {
				useRansac = YesNoOption ("--ransac", argv[optionN + 1]);
				optionN += 2;
			} else if (strcmp (optionStr, "--maxmatches") == 0) {
				if (sscanf(argv[optionN + 1], "%d",  &maxMatches) != 1) {
					WriteLine ("Parameter to maxmatches option invalid. See the usage help.");
					exit (1);
				}
				if (maxMatches < 0) {
					WriteLine ("Maximum number of matches must be positive or zero (unlimited).");
					exit (1);
				}
				optionN += 2;
			} else if (strcmp (optionStr, "--disable-areafilter") == 0) {
				useAreaFiltration = false;
				optionN += 1;
			} else if (strcmp (optionStr, "--integer-coordinates") == 0) {
				useIntegerCoordinates = true;
				optionN += 1;
			} else if (strcmp (optionStr, "--absolute-pathnames") == 0) {
				useAbsolutePathnames = YesNoOption ("--absolute-pathnames", argv[optionN + 1]);
				optionN += 2;
			} else if (strcmp (optionStr, "--align") == 0) {
				preAlign = true;
				optionN += 1;
			} else if (strcmp (optionStr, "--bottom-is-left") == 0) {
				bottomDefault = 0;
				optionN += 1;
			} else if (strcmp (optionStr, "--bottom-is-right") == 0) {
				bottomDefault = 1;
				optionN += 1;
			} else if (strcmp (optionStr, "--generate-horizon") == 0) {
				if (sscanf(argv[optionN + 1], "%d", &generateHorizon) != 1) {
					WriteLine ("Parameter to generate-horizon option invalid. See the usage help.");
					exit (1);
				}
				if (generateHorizon < 0) {
					WriteLine ("The number of horizon lines to generate must be positive.");
					exit (1);
				}

				optionN += 2;
			} else if (strcmp (optionStr, "--refine") == 0) {
				refine = true;
				optionN += 1;
			} else if (strcmp (optionStr, "--refine-by-middle") == 0) {
				refineMiddle = true;
				optionN += 1;
			} else if (strcmp (optionStr, "--refine-by-mean") == 0) {
				refineMiddle = false;
				optionN += 1;
			} else if (strcmp (optionStr, "--keep-unrefinable") == 0) {
				keepUnrefinable = YesNoOption ("--keep-unrefinable", argv[optionN + 1]);
				optionN += 2;
			} else {
				WriteLine ("Usage error. Run \"autopano.exe\" without arguments for help.");
				exit (1);
			}
		}
	optionCount = optionN;
	// is there an output name and at least one input name?
	if( argc - optionN < 2 ){
		WriteLine ("Error. Output name and at least one image name required.");
		Usage();
		exit(1);
	}
	// next arg is either output file name or "-" for stdout
	// anything else beginning with '-' is an error
	if( argv[optionCount][0] == '-' ){
		if( strcmp( argv[optionCount], "-" ) == 0 )streamout = true;
		else {
			WriteLine ("Option error. Run without arguments for help.");
			exit (1);
		}
	}
	
	if (bottomDefault != -1 && preAlign == false) {
		WriteLine ("Please enable automatic alignment (\"--align\") before using the");
		WriteLine ("--bottom-is-* options. Thank you. Run \"autopano.exe\" without");
		WriteLine ("arguments for usage help.");

		exit (1);
	}

	if (generateHorizon > 0 && preAlign == false) {
		WriteLine ("Please enable automatic alignment (\"--align\") before using the");
		WriteLine ("--generate-horizon option. Thank you. Run \"autopano.exe\" without");
		WriteLine ("arguments for usage help.");

		exit (1);
	}

	MultiMatch* mm = MultiMatch_new0 ();
	ArrayList* keyfiles = ArrayList_new0(NULL);
	int i;
	for( i=0; i<argc - 1 - optionCount; i++) {
		ArrayList_AddItem(keyfiles, argv[i+optionCount+1]);
	}

	WriteLine ("Loading keyfiles");
	MultiMatch_LoadKeysets (mm, keyfiles);

	WriteLine ("\nMatching...%s", useRansac == true ? " RANSAC enabled" : "");
	ArrayList* msList = MultiMatch_LocateMatchSets (mm, 3, maxMatches,
							useRansac, useAreaFiltration);

	// Connected component check
	WriteLine ("\nConnected component check...");
	ArrayList* components = MultiMatch_ComponentCheck (mm, msList);
	WriteLine ("Connected component identification resulted in %d component%s:",
		   ArrayList_Count(components), ArrayList_Count(components) > 1 ? "s" : "");

	int compN = 1;
	int j;
	for(j=0; j<ArrayList_Count(components); j++) {
		Component* comp = (Component*) ArrayList_GetItem(components, j);
                char* compstr = Component_ToString(comp);
                WriteLine ("component %d: %s", compN++, compstr);
                free(compstr);
	}

	if (ArrayList_Count(components) > 1) {
		WriteLine ("");
		WriteLine ("Warning: There is one or more components that are not connected through control");
		WriteLine ("         points. An optimization of the resulting PTO will not be possible");
		WriteLine ("         without prior adding of control points between the components listed");
		WriteLine ("         above. Please see the manual page for autopano(1) for details.");
		WriteLine ("");
	} else
		WriteLine ("");

	// BondBall algorithm
	BondBall* bb = NULL;
	if (preAlign) {
		bb = MultiMatch_BuildBondBall (mm, msList, bottomDefault);

		if (bb == NULL) {
			WriteLine ("WARNING: Failed to build bondball as requested. No pre-aligning of images");
			WriteLine ("         takes place.\n");
		}
	}

	if (refine) {
		WriteLine ("Refining keypoints");
		RefineKeypoints (msList, refineMiddle, keepUnrefinable);
	}

	FILE* pto;
	if ( streamout ) {
		pto = stdout;
	} else {
		WriteLine ("Creating output file \"%s\"", argv[optionCount]);
		pto = fopen(argv[optionCount], "w");
	}

	WritePTOFile (pto, mm, msList, bb, generateHorizon, useIntegerCoordinates,
		      useAbsolutePathnames);

	ArrayList_delete(keyfiles);
	ArrayList_delete(components);
	BondBall_delete(bb);
	MultiMatch_delete(mm);
	if ( !streamout )
		fclose(pto);
	return 0;
}
示例#11
0
void WritePTOFile (FILE* pto, MultiMatch* mm,
		   ArrayList* msList, BondBall* bb, int generateHorizon, bool integerCoordinates,
		   bool useAbsolutePathnames)
{
	fprintf(pto, "# Hugin project file\n");
	fprintf(pto, "# automatically generated by autopano-sift, available at\n");
	fprintf(pto, "# http://cs.tu-berlin.de/~nowozin/autopano-sift/\n\n");
	fprintf(pto, "p f2 w3000 h1500 v360  n\"JPEG q90\"\n");
	fprintf(pto, "m g1 i0\n\n");
	
	int imageIndex = 0;
	HashTable* imageNameTab = HashTable_new0 (NULL, NULL);
	ArrayList* resolutions = ArrayList_new0 (Resolution_delete);
	int i;
	for(i=0; i<ArrayList_Count(mm->keySets); i++) {
		KeypointXMLList* kx = (KeypointXMLList*) ArrayList_GetItem(mm->keySets, i);
		HashTable_AddItem(imageNameTab, kx->imageFile, (void*)imageIndex);
		ArrayList_AddItem(resolutions, Resolution_new (kx->xDim, kx->yDim));
		
		char*  imageFile = kx->imageFile;
		
		// If the resolution was already there, use the first image with
		// the exact same resolution as reference for camera-related
		// values.
		
		int refIdx;
		for (refIdx = 0 ; refIdx < (ArrayList_Count(resolutions) - 1) ; ++refIdx) {
			if (Resolution_CompareTo((Resolution*) ArrayList_GetItem(resolutions, refIdx), kx->xDim, kx->yDim) == 0)
				break;
		}
		if (refIdx == (ArrayList_Count(resolutions) - 1))
			refIdx = -1;
		
		Position* pos = bb == NULL ? NULL :
			(Position*) HashTable_GetItem(bb->positions, imageFile);
		/*
		  if (pos != NULL) {
		  WriteLine ("yaw %g, pitch %g, rotation %g",
		  pos->yaw, pos->pitch, pos->rotation);
		  }*/

		double yaw = 0.0, pitch = 0.0, rotation = 0.0;
		if (pos != NULL) {
			yaw = pos->yaw;
			pitch = pos->pitch;
			rotation = pos->rotation;
		}
		
		if (imageIndex == 0 || refIdx == -1) {
			fprintf(pto, "i w%d h%d f0 a0 b-0.01 c0 d0 e0 p%g r%g v180 y%g  u10 n\"%s\"\n",
				kx->xDim, kx->yDim, pitch, rotation, yaw, imageFile);
		} else {
			fprintf(pto, "i w%d h%d f0 a=%d b=%d c=%d d0 e0 p%g r%g v=%d y%g  u10 n\"%s\"\n",
				kx->xDim, kx->yDim, refIdx, refIdx, refIdx, pitch, rotation, refIdx, yaw, imageFile);
		}
		imageIndex += 1;
	}
	
	fprintf(pto, "\nv p1 r1 y1\n\n");
	
	fprintf(pto, "# match list automatically generated\n");
	int j;
	for(j=0; j<ArrayList_Count(msList); j++) {
		MatchSet* ms = (MatchSet*) ArrayList_GetItem(msList, j);
		int k;
		for(k=0; k<ArrayList_Count(ms->matches); k++) {
			Match* m = (Match*) ArrayList_GetItem(ms->matches, k);
			if (integerCoordinates == false) {
				fprintf(pto, "c n%d N%d x%.6f y%.6f X%.6f Y%.6f t0\n",
					(int)HashTable_GetItem(imageNameTab, ms->file1), (int)HashTable_GetItem(imageNameTab, ms->file2),
					m->kp1->x, m->kp1->y, m->kp2->x, m->kp2->y);
			} else {
				fprintf(pto, "c n%d N%d x%d y%d X%d Y%d t0\n",
					(int)HashTable_GetItem(imageNameTab, ms->file1), (int)HashTable_GetItem(imageNameTab, ms->file2),
					(int) (m->kp1->x + 0.5), (int) (m->kp1->y + 0.5),
					(int) (m->kp2->x + 0.5), (int) (m->kp2->y + 0.5));
			}
		}
	}
	
	// Generate horizon if we should
	if (bb != NULL && generateHorizon > 0) {
		WriteLine ("Creating horizon...");
		
		int kMain = 2;
		int hPoints = generateHorizon;
		int horizonPointsMade = 0;

		bool hasGood = true;
		while (hPoints > 0 && hasGood) {
			hasGood = false;
			int kStep = 2 * kMain;

			int p;
			for (p = 0 ; hPoints > 0 && p < kMain ; ++p) {
				double stepSize = ((double) ArrayList_Count(bb->firstRow)) / ((double) kStep);
				double beginIndex = p * stepSize;
				double endIndex = (((double) ArrayList_Count(bb->firstRow)) / (double) kMain) +
					p * stepSize;

// Round to next integer and check if their image distance
// is larger than 1. If its not, we skip over this useless
// horizon point.
				int bi = (int) (beginIndex + 0.5);
				int ei = (int) (endIndex + 0.5);
				if ((ei - bi) <= 1)
					continue;

				hasGood = true;

				bi %= ArrayList_Count(bb->firstRow);
				ei %= ArrayList_Count(bb->firstRow);
				fprintf(pto, "c n%s N%s x%d y%d X%d Y%d t2\n",
					(char*)HashTable_GetItem(imageNameTab, ArrayList_GetItem(bb->firstRow, bi)),
					(char*)HashTable_GetItem(imageNameTab, ArrayList_GetItem(bb->firstRow, ei)),
					((Resolution*) ArrayList_GetItem(resolutions,bi))->x / 2,
					((Resolution*) ArrayList_GetItem(resolutions,bi))->y / 2,
					((Resolution*) ArrayList_GetItem(resolutions,ei))->x / 2,
					((Resolution*) ArrayList_GetItem(resolutions,ei))->y / 2);

				horizonPointsMade += 1;
				hPoints -= 1;
			}

// Increase density for next generation lines
			kMain *= 2;
		}
		WriteLine ("  made %d horizon lines.\n", horizonPointsMade);
	}

	fprintf(pto, "\n# :-)\n\n");
	
	WriteLine ("\nYou can now load the output file into hugin.");
	WriteLine ("Notice: You absolutely must adjust the field-of-view value for the images");

        ArrayList_delete(resolutions);
        HashTable_delete(imageNameTab);
}
示例#12
0
void SortedLimitedList_delete (SortedLimitedList* self)
{
	ArrayList_delete(&self->base);
}