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