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 {
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; }