void GPUSURFFeatureMatcher::MatchFeatures(int idx_i, int idx_j, vector<DMatch>* matches) {
	
#ifdef __SFM__DEBUG__
	Mat img_1; imgs[idx_i].download(img_1);
	Mat img_2; imgs[idx_j].download(img_2);
#endif
	const vector<KeyPoint>& imgpts1 = imgpts[idx_i];
	const vector<KeyPoint>& imgpts2 = imgpts[idx_j];
	const GpuMat& descriptors_1 = descriptors[idx_i];
	const GpuMat& descriptors_2 = descriptors[idx_j];
	
	std::vector< DMatch > good_matches_,very_good_matches_;
	std::vector<KeyPoint> keypoints_1, keypoints_2;
	
	//cout << "imgpts1 has " << imgpts1.size() << " points (descriptors " << descriptors_1.rows << ")" << endl;
	//cout << "imgpts2 has " << imgpts2.size() << " points (descriptors " << descriptors_2.rows << ")" << endl;
	
	keypoints_1 = imgpts1;
	keypoints_2 = imgpts2;
	
	if(descriptors_1.empty()) {
		CV_Error(0,"descriptors_1 is empty");
	}
	if(descriptors_2.empty()) {
		CV_Error(0,"descriptors_2 is empty");
	}
	
	//matching descriptor vectors using Brute Force matcher
	BruteForceMatcher_GPU <L2<float> > matcher;
	std::vector<DMatch> matches_;
	if (matches == NULL) {
		matches = &matches_;
	}
	if (matches->size() == 0) {
		cout << "match " << descriptors_1.rows << " vs. " << descriptors_2.rows << " ...";

		if(use_ratio_test) {
			vector<vector<DMatch> > knn_matches;
			GpuMat trainIdx,distance,allDist;
			CV_PROFILE("match", 
				matcher.knnMatchSingle(descriptors_1,descriptors_2,trainIdx,distance,allDist,2); 
				matcher.knnMatchDownload(trainIdx,distance,knn_matches);
			)

			(*matches).clear();

			//ratio test
			for(int i=0;i<knn_matches.size();i++) {
				if(knn_matches[i][0].distance / knn_matches[i][1].distance < 0.7) {
					(*matches).push_back(knn_matches[i][0]);
				}
			}
			cout << "kept " << (*matches).size() << " features after ratio test"<<endl;
		} else {
Пример #2
0
Mat Homographier::findHomography_GPU(Mat &image1, Mat &image2)
{
	Timer::send(Timer::Homography, id, Timer::HmgTimeval::Start);

    Mat gray1 = mat2Grayscale(image1);
    Mat gray2 = mat2Grayscale(image2);

	GpuMat gray_gpu1(gray1);
	GpuMat gray_gpu2(gray2);

	SURF_GPU gpu_surfer(config.hessianThreshold, config.nOctaves, config.nOctaveLayers, 
		config.extended);

	maskA = Mat::ones(gray1.rows, gray1.cols, CV_8UC1);
	maskB = Mat::ones(gray2.rows, gray2.cols, CV_8UC1);

	float overlap = float(config.frameOverlap) / 100.0;
	//set mask for first image
	switch(hmgDirections[0])
	{
	case 'R':	//the ROI is on the right of the image (set left side to 0)
		maskA.colRange(0, (maskA.cols-1) * (1 - overlap)).rowRange(0, maskA.rows-1).setTo(0);
		break;
	case 'L':	//ROI is to the left
		maskA.colRange((maskA.cols-1) * overlap, maskA.cols-1).rowRange(0, maskA.rows-1).setTo(0);
		break;
	case 'D':	//ROI is down/bottom half
		maskA.rowRange(0, (maskA.rows-1) * (1 - overlap)).colRange(0, maskA.cols-1).setTo(0);
		break;
	case 'U':	//ROI is up/top half
		maskA.rowRange((maskA.rows-1) * overlap, maskA.rows-1).colRange(0, maskA.cols-1).setTo(0);
		break;
	default:
		break;
	}

	//set mask for second image
	switch(hmgDirections[1])
	{
	case 'R':	//the ROI is on the right of the image (set left side to 0)
		maskB.colRange(0, (maskB.cols-1) * (1 - overlap)).rowRange(0, maskB.rows-1).setTo(0);
		break;
	case 'L':	//ROI is to the left
		maskB.colRange((maskB.cols-1) * overlap, maskB.cols-1).rowRange(0, maskB.rows-1).setTo(0);
		break;
	case 'D':	//ROI is down/bottom half
		maskB.rowRange(0, (maskB.rows-1) * (1 - overlap)).colRange(0, maskB.cols-1).setTo(0);
		break;
	case 'U':	//ROI is up/top half
		maskB.rowRange((maskB.rows-1) * overlap, maskB.rows-1).colRange(0, maskB.cols-1).setTo(0);
		break;
	default:
		break;
	}

	GpuMat mask_gpuA(maskA);
	GpuMat mask_gpuB(maskB);

	GpuMat keypoints1GPU, keypoints2GPU;
    GpuMat descriptors1GPU, descriptors2GPU;
    gpu_surfer(gray_gpu1, mask_gpuA, keypoints1GPU, descriptors1GPU);
    gpu_surfer(gray_gpu2, mask_gpuB, keypoints2GPU, descriptors2GPU);

	Timer::send(Timer::Homography, id, Timer::HmgTimeval::Detect);

	// matching descriptors
    BruteForceMatcher_GPU< L2<float> > matcher;
    GpuMat trainIdx, distance;
    matcher.matchSingle(descriptors1GPU, descriptors2GPU, trainIdx, distance);

	Timer::send(Timer::Homography, id, Timer::HmgTimeval::Match);
    
    // downloading results
    vector<KeyPoint> keypoints1, keypoints2;
    vector<float> descriptors1, descriptors2;
    vector<DMatch> matches, good_matches;
    gpu_surfer.downloadKeypoints(keypoints1GPU, keypoints1);
    gpu_surfer.downloadKeypoints(keypoints2GPU, keypoints2);
    gpu_surfer.downloadDescriptors(descriptors1GPU, descriptors1);
    gpu_surfer.downloadDescriptors(descriptors2GPU, descriptors2);
    BruteForceMatcher_GPU< L2<float> >::matchDownload(trainIdx, distance, matches);

	if (keypoints1.size() == 0 || keypoints2.size() == 0)
	{
		return Mat(0,0,0);
	}

	double total_dist = 0;
	double min_dist = matches[0].distance;
	double max_dist = matches[0].distance;
	double avg_dist, swing; 
	double tolerance = float(config.matchTolerance) / 100.0;

	for(int i=0; i<matches.size(); i++)
	{
		double dist = matches[i].distance;

		if(dist < min_dist)
			min_dist = dist;
		if(dist > max_dist)
			max_dist = dist;
		total_dist += dist;
	}

	avg_dist = total_dist / (double)matches.size();

	if( (avg_dist - min_dist) > (max_dist - avg_dist))
		swing = (avg_dist - min_dist) * tolerance;
	else
		swing = (max_dist - avg_dist) * tolerance;

	for (int i=0; i<matches.size(); i++)
	{
		if((avg_dist - swing <= matches[i].distance) 
			&& (matches[i].distance <= avg_dist + swing))
		{
			good_matches.push_back(matches[i]);
		}
	}

	vector<Point2f> image1Points, image2Points;
	for (int i=0; i<matches.size(); i++)
	{
		image1Points.push_back(keypoints1[good_matches[i].queryIdx].pt);
		image2Points.push_back(keypoints2[good_matches[i].trainIdx].pt);
	}

    Mat homography = cv::findHomography(image1Points, image2Points, CV_RANSAC,
		float(config.ransacReprojThresh) / 10.0);

	Timer::send(Timer::Homography, id, Timer::HmgTimeval::End);

	if (config.showMatches)
	{
		drawMatches(gray1, keypoints1, gray2, keypoints2, good_matches, matchesFrame);

		// Draw descriptive keypoints:
		//drawMatches(gray1, keypoints1, gray2, keypoints2, good_matches, matchesFrame, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS | DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
	}

    return homography;
}
int main(int argc, char* argv[])
{
    if (argc != 5)
    {
        help();
        return -1;
    }

    GpuMat img1, img2;
    for (int i = 1; i < argc; ++i)
    {
        if (string(argv[i]) == "--left")
        {
            img1.upload(imread(argv[++i], CV_LOAD_IMAGE_GRAYSCALE));
            CV_Assert(!img1.empty());
        }
        else if (string(argv[i]) == "--right")
        {
            img2.upload(imread(argv[++i], CV_LOAD_IMAGE_GRAYSCALE));
            CV_Assert(!img2.empty());
        }
        else if (string(argv[i]) == "--help")
        {
            help();
            return -1;
        }
    }

    cv::gpu::printShortCudaDeviceInfo(cv::gpu::getDevice());

    SURF_GPU surf;

    // detecting keypoints & computing descriptors
    GpuMat keypoints1GPU, keypoints2GPU;
    GpuMat descriptors1GPU, descriptors2GPU;
    surf(img1, GpuMat(), keypoints1GPU, descriptors1GPU);
    surf(img2, GpuMat(), keypoints2GPU, descriptors2GPU);
    
    cout << "FOUND " << keypoints1GPU.cols << " keypoints on first image" << endl;
    cout << "FOUND " << keypoints2GPU.cols << " keypoints on second image" << endl;

    // matching descriptors
    BruteForceMatcher_GPU< L2<float> > matcher;
    GpuMat trainIdx, distance;
    matcher.matchSingle(descriptors1GPU, descriptors2GPU, trainIdx, distance);
    
    // downloading results
    vector<KeyPoint> keypoints1, keypoints2;
    vector<float> descriptors1, descriptors2;
    vector<DMatch> matches;
    surf.downloadKeypoints(keypoints1GPU, keypoints1);
    surf.downloadKeypoints(keypoints2GPU, keypoints2);
    surf.downloadDescriptors(descriptors1GPU, descriptors1);
    surf.downloadDescriptors(descriptors2GPU, descriptors2);
    BruteForceMatcher_GPU< L2<float> >::matchDownload(trainIdx, distance, matches);

    // drawing the results
    Mat img_matches;
    drawMatches(Mat(img1), keypoints1, Mat(img2), keypoints2, matches, img_matches);
    
    namedWindow("matches", 0);
    imshow("matches", img_matches);
    waitKey(0);

    return 0;
}