Beispiel #1
0
/*******************************************************************************
Find matching interest points between images.
    image1 - first input image
    interestPts1 - interest points corresponding to image 1
    numInterestsPts1 - number of interest points in image 1
    image2 - second input image
    interestPts2 - interest points corresponding to image 2
    numInterestsPts2 - number of interest points in image 2
    matches - set of matching points to be returned
    numMatches - number of matching points returned
    image1Display - image used to display matches
    image2Display - image used to display matches
*******************************************************************************/
void MainWindow::MatchInterestPoints(QImage image1, CIntPt *interestPts1, int numInterestsPts1,
                             QImage image2, CIntPt *interestPts2, int numInterestsPts2,
                             CMatches **matches, int &numMatches, QImage &image1Display, QImage &image2Display)
{

    // Compute the descriptors for each interest point.
    // You can access the descriptor for each interest point using interestPts1[i].m_Desc[j].
    // If interestPts1[i].m_DescSize = 0, it was not able to compute a descriptor for that point
    ComputeDescriptors(image1, interestPts1, numInterestsPts1);
    ComputeDescriptors(image2, interestPts2, numInterestsPts2);

    
    *matches = new CMatches[numInterestsPts1];

    int x, y, z;
    numMatches = 0;

    // Compute best match from image 2 for each interest point in image 1
    // Best matching point has the smallest norm distance
    for(x = 0; x < numInterestsPts1; x++) {
        // Check if descriptor valid
        if(interestPts1[x].m_DescSize > 0) {
            CIntPt pt1 = interestPts1[x];
            int min = 0;
            double mindist = INFINITY;

            for(y = 0; y < numInterestsPts2; y++) {
                // Check if descriptor valid
                if(interestPts2[y].m_DescSize > 0) {
                    CIntPt pt2 = interestPts2[y];
                    double dist = 0.0;
                    for(z = 0; z < DESC_SIZE; z++) {
                        dist += pow(pt1.m_Desc[z] - pt2.m_Desc[z], 2);
                    }
                    if(dist < mindist) {
                        mindist = dist;
                        min = y;
                    }
                }
            }

            // Store matching points
            (*matches)[numMatches].m_X1 = interestPts1[x].m_X;
            (*matches)[numMatches].m_Y1 = interestPts1[x].m_Y;
            (*matches)[numMatches].m_X2 = interestPts2[min].m_X;
            (*matches)[numMatches].m_Y2 = interestPts2[min].m_Y;
            numMatches++;
        }
    }


    // The position of the interest point in iamge 1 is (m_X1, m_Y1)

    // Draw the matches
    DrawMatches(*matches, numMatches, image1Display, image2Display);
}
Beispiel #2
0
  void DrawMatches(
      const std::string& title,
      const cv::Mat image1,
      const cv::Mat image2,
      const cv::Mat points1,
      const cv::Mat points2,
      const cv::Scalar& color,
      bool draw_image_borders)
  {
    cv::Mat image_out;
    DrawMatches(image_out,
                image1,
                image2,
                points1,
                points2,
                color,
                draw_image_borders);

    opencv_util::ShowScaled(title, image_out);
  }
Beispiel #3
0
void CubicleWrapper::DrawOverlay(IplImage* iplImage, int overlay_level) const
{
  if (overlay_level>=1) {
    DrawMatches(iplImage, overlay_level);
  }
}
/*******************************************************************************
Find matching interest points between images.

    image1: first input image
    interestPts1: interest points corresponding to image 1
    numInterestPts1: number of interest points in image 1
    image2: second input image
    interestPts2: interest points corresponding to image 2
    numInterestPts2: number of interest points in image 2
    matches: set of matching points to be returned
    numMatches: number of matching points returned
    image1Display: image used to display matches
    image2Display: image used to display matches
*******************************************************************************/
void MainWindow::MatchInterestPoints(QImage image1, CIntPt *interestPts1, int numInterestPts1,
                             QImage image2, CIntPt *interestPts2, int numInterestPts2,
                             CMatches **matches, int &numMatches, QImage &image1Display, QImage &image2Display)
{
	
	numMatches = numInterestPts1;

    // Compute the descriptors for each interest point.
    // You can access the descriptor for each interest point using interestPts1[i].m_Desc[j].
    // If interestPts1[i].m_DescSize = 0, it was not able to compute a descriptor for that point
    ComputeDescriptors(image1, interestPts1, numInterestPts1);
    ComputeDescriptors(image2, interestPts2, numInterestPts2);

    // The position of the interest point in image 1 is (m_X1, m_Y1)
    // The position of the interest point in image 2 is (m_X2, m_Y2)
	
	*matches = new CMatches[numMatches];

	double minL2distance;
	int matchNo = 0;
	int attemptNo = 0;
	int rejectNo = 0;

	for(int image1pt = 0; image1pt < numInterestPts1; image1pt++)
	{
		// If the current point doesn't have a descriptor, skip it
		if(interestPts1[image1pt].m_DescSize == 0)
		{
			rejectNo++;
			continue;
		}

		for(int image2pt = 0; image2pt < numInterestPts2; image2pt++)
		{

			// If the current point doesn't have a descriptor, skip it
			if(interestPts2[image2pt].m_DescSize == 0)
			{
				continue;
			}

			// If it's the first match attempted, assume it's right and get the distance
			if(attemptNo == 0)
			{
				(*matches)[matchNo].m_X1 = interestPts1[image1pt].m_X;
				(*matches)[matchNo].m_Y1 = interestPts1[image1pt].m_Y;
				
				(*matches)[matchNo].m_X2 = interestPts2[image2pt].m_X;
				(*matches)[matchNo].m_Y2 = interestPts2[image2pt].m_Y;
				
				minL2distance = getDistance(interestPts1[image1pt], interestPts2[image2pt]);
				attemptNo++;
			}
			else
			{
				// If the distance is shorter, this is a better match
				if(getDistance(interestPts1[image1pt], interestPts2[image2pt]) < minL2distance)
				{
					(*matches)[matchNo].m_X1 = interestPts1[image1pt].m_X;
					(*matches)[matchNo].m_Y1 = interestPts1[image1pt].m_Y;
					
					(*matches)[matchNo].m_X2 = interestPts2[image2pt].m_X;
					(*matches)[matchNo].m_Y2 = interestPts2[image2pt].m_Y;

					minL2distance = getDistance(interestPts1[image1pt], interestPts2[image2pt]);
					attemptNo++;
				}
			}
		}
		attemptNo = 0;
		matchNo++;
	}

	numMatches = numMatches - rejectNo;

    // Draw the matches
    DrawMatches(*matches, numMatches, image1Display, image2Display);

	//delete [] (*matches);
}
/*******************************************************************************
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;
}
Beispiel #6
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;

}