/*******************************************************************************
Compute homography transformation between images using RANSAC.

    matches: set of matching points between images
    numMatches: number of matching points
    numIterations: number of iterations to run RANSAC
    inlierThreshold: maximum distance between points that are considered to be inliers
    hom: returned homography transformation (image1 -> image2)
    homInv: returned inverse homography transformation (image2 -> image1)
    image1Display: first image used to display matches
    image2Display: second image used to display matches
*******************************************************************************/
void MainWindow::RANSAC(CMatches *matches, int numMatches, int numIterations, double inlierThreshold,
                        double hom[3][3], double homInv[3][3], QImage &image1Display, QImage &image2Display)
{
	// We'll be comparing groups of 4 points
	#define MATCH_GROUP_SIZE 4
	
	// If there are fewer than matchGroupSize matches, this won't work, so return.
	if(numMatches < MATCH_GROUP_SIZE)
	{
		return;
	}
	
	CMatches potentialInliers[MATCH_GROUP_SIZE];
	int numInliers, maxInliers, randomMatchID;
	int usedMatchIDs[MATCH_GROUP_SIZE];
	double potentialInlierHom[3][3];
	double bestHom[3][3];
	
	for(int i = 0; i < MATCH_GROUP_SIZE; i++)
	{
		usedMatchIDs[i] = -1;
	}

	// Initialize random seed
	srand( time(NULL) );	

	maxInliers = -1;

	for (int iter = 0; iter < numIterations; iter++)
	{
		// Randomly select 4 pairs of potentially matching points from matches
		for(int i = 0; i < MATCH_GROUP_SIZE; i++)
		{
			// Make sure that the match selected is unique
			bool matchUnique = false;
			while(!matchUnique)
			{
				matchUnique = true;
				randomMatchID = rand() % numMatches;
			
				// Compare generated match to every other match,
				// and make sure we're not reusing one
				for(int j = 0; j < i; j++)
				{
					
					// Check for a match with a previously used match
					if(randomMatchID == usedMatchIDs[j])
					{
						matchUnique = false;
						continue;
					}
				}
			}
			
			// Once we've reached this point, we know that we have a unique match,
			// so let's add the randomly generated match to the array of potential inliers
			potentialInliers[i] = matches[randomMatchID];
			
			// Make sure we don't use the same match again
			usedMatchIDs[i] = randomMatchID;
		}

		// Now that we have four unique, randomly selected matches,
		// compute the homography relating the four selected matches
		ComputeHomography(potentialInliers, MATCH_GROUP_SIZE, potentialInlierHom, true);

		// Using the computed homography, compute the number of inliers against all of the matches
		numInliers = ComputeInlierCount(potentialInlierHom, matches, numMatches, inlierThreshold);

		// If this homography produces the highest number of inliers, store it as the best homography
		if(numInliers > maxInliers)
		{
			maxInliers = numInliers;
			for(int i = 0; i < 3; i++)
			{
				for(int j = 0; j < 3; j++)
				{
					bestHom[i][j] = potentialInlierHom[i][j];
				}
			}
		}
	}

	CMatches *inliers = new CMatches[maxInliers];

    // Given the highest scoring homography, once again find all the inliers
	GetInliers(bestHom, matches, numMatches, inlierThreshold, inliers);
	numInliers = ComputeInlierCount(bestHom, matches, numMatches, inlierThreshold);

	// Compute a new refined homography using all of the inliers
	ComputeHomography(inliers, maxInliers, hom, true);

	// Compute an inverse homography as well
	ComputeHomography(inliers, maxInliers, homInv, false);
	
	// Display the inlier matches
    DrawMatches(inliers, numInliers, image1Display, image2Display);

	delete inliers;
}
Exemplo n.º 2
0
/*******************************************************************************
Compute homography transformation between images using RANSAC.
    matches - set of matching points between images
    numMatches - number of matching points
    numIterations - number of iterations to run RANSAC
    inlierThreshold - maximum distance between points that are considered to be inliers
    hom - returned homography transformation (image1 -> image2)
    homInv - returned inverse homography transformation (image2 -> image1)
    image1Display - image used to display matches
    image2Display - image used to display matches
*******************************************************************************/
void MainWindow::RANSAC(CMatches *matches, int numMatches, int numIterations, double inlierThreshold,
                        double hom[3][3], double homInv[3][3], QImage &image1Display, QImage &image2Display)
{
    int i, j;
    CMatches randomMatches[4];
    double h[3][3];

    int max = 0;

    for(i = 0; i < numIterations; i++) {

        // Randomly select 4 matching pairs
        
        for(j = 0; j < 4; j++) {
            int num = rand() % numMatches;

            randomMatches[j].m_X1 = matches[num].m_X1;
            randomMatches[j].m_X2 = matches[num].m_X2;
            randomMatches[j].m_Y1 = matches[num].m_Y1;
            randomMatches[j].m_Y2 = matches[num].m_Y2;
        }

        // Compute Homography for the 4 random matches and inliers count
        if(ComputeHomography(randomMatches, 4, h, true)) {
            int count = ComputeInlierCount(h, matches, numMatches, inlierThreshold);

            // Check if the homography is the best
            if(count > max) {
                max = count;
                int x, y;
                for(x = 0; x < 3; x++) {
                    for(y = 0; y < 3; y++) {
                        hom[x][y] = h[x][y];
                    }
                }
            }
        }
    }

    CMatches *inliers = new CMatches[max];
    int numInliers = 0;

    for(i = 0; i < numMatches; i++) {
        double x2, y2;

        Project(matches[i].m_X1, matches[i].m_Y1, x2, y2, hom);

        double distance = pow(x2 - matches[i].m_X2, 2.0) + pow(y2 - matches[i].m_Y2, 2.0);

        if(distance < inlierThreshold * inlierThreshold) {
            inliers[numInliers].m_X1 = matches[i].m_X1;
            inliers[numInliers].m_Y1 = matches[i].m_Y1;
            inliers[numInliers].m_X2 = matches[i].m_X2;
            inliers[numInliers].m_Y2 = matches[i].m_Y2;

            numInliers++;
        }

    }

    // Recompute the best homography and inverse homography
    ComputeHomography(inliers, numInliers, hom, true);
    ComputeHomography(inliers, numInliers, homInv, false);

    // After you're done computing the inliers, display the corresponding matches.
    DrawMatches(inliers, numInliers, image1Display, image2Display);

    // Clean up
    delete [] inliers;

}