一、前言
本文主要實現了使用opencv裡的gpu版surf特徵檢測器和gpu版orb檢測器,分別對圖片進行特徵點提取及匹配,並對尋獲的特徵點進行了距離篩選,將匹配較為好的特徵點進行展示
二、實現代碼
我不生產代碼,我只是代碼的搬運工和修改工
//main.cpp//#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/gpu/gpu.hpp>#include <opencv2/nonfree/gpu.hpp>#include <opencv2/nonfree/features2d.hpp> #include <iostream>using namespace std;using namespace cv;Mat rotatedImage(const Mat & _src, double _degree){int width_src = _src.cols;int height_src = _src.rows;float center_x = width_src / 2.0;float center_y = height_src / 2.0;double angle = _degree * CV_PI / 180.; double a = sin(angle), b = cos(angle);Mat map_matrix = getRotationMatrix2D(Point2f(center_x, center_y), _degree, 1.0);//獲得旋轉矩陣int height_rotated = height_src*fabs(b) + width_src*fabs(a);int width_rotated = height_src*fabs(a) + width_src*fabs(b);map_matrix.at<double>(0, 2) += (width_rotated - width_src) / 2.0; //將座標移到中點map_matrix.at<double>(1, 2) += (height_rotated - height_src) / 2.0; //將座標移到中點Mat dst;warpAffine(_src, dst, map_matrix, Size(width_rotated, height_rotated), CV_INTER_CUBIC | CV_WARP_FILL_OUTLIERS, BORDER_CONSTANT, cvScalarAll(0));return dst;}//主要獲得surf特徵點、描述子、及特徵點匹配void surfExtractor(Mat& _src_Img, Mat& _dst_Img ){gpu::GpuMat src_gpu(_src_Img);gpu::GpuMat dst_gpu(_dst_Img);std::vector<KeyPoint> keypoints_src;std::vector<KeyPoint> keypoints_dst;std::vector<DMatch> matches;gpu::SURF_GPU FeatureFinder_gpu(500);gpu::GpuMat keypoints_gpu_src, keypoints_gpu_dst;gpu::GpuMat descriptors_gpu_src, descriptors_gpu_dst;std::vector<float> descriptors_v1, descriptors_v2;//計算特徵點和特徵描述子FeatureFinder_gpu(src_gpu, gpu::GpuMat(), keypoints_gpu_src, descriptors_gpu_src);FeatureFinder_gpu(dst_gpu, gpu::GpuMat(), keypoints_gpu_dst, descriptors_gpu_dst);//將特徵點下載回cpu,便於畫圖使用FeatureFinder_gpu.downloadKeypoints(keypoints_gpu_src, keypoints_src);FeatureFinder_gpu.downloadKeypoints(keypoints_gpu_dst, keypoints_dst);//使用gpu提供的BruteForceMatcher進行特徵點匹配gpu::BruteForceMatcher_GPU< L2<float> > matcher_lk;matcher_lk.match(descriptors_gpu_src, descriptors_gpu_dst, matches, gpu::GpuMat());float max_distance = 0.2; //定義特徵點好壞衡量距離std::vector<DMatch> good_matches; //收集較好的匹配點for (int i = 0; i < descriptors_gpu_src.rows; i++) {if (matches[i].distance < max_distance) {good_matches.push_back(matches[i]);}}Mat image_matches;drawMatches(_src_Img, keypoints_src, _dst_Img, keypoints_dst, good_matches,image_matches, Scalar(0, 255, 0) , Scalar::all(-1), vector<char>(), 0); imshow("Gpu Surf", image_matches);}void orbExtractor(Mat& _src_Img, Mat& _dst_Img){gpu::GpuMat src_gpu(_src_Img);gpu::GpuMat dst_gpu(_dst_Img);std::vector<KeyPoint> keypoints_src, keypoints_dst;gpu::GpuMat descriptors_gpu_src, descriptors_gpu_dst;std::vector<DMatch> matches;gpu::ORB_GPU orb_finder(500);orb_finder.blurForDescriptor = true; //設定模糊cv::gpu::GpuMat fullmask_1(src_gpu.size(), CV_8U, 0xFF);cv::gpu::GpuMat fullmask_2(dst_gpu.size(), CV_8U, 0xFF);orb_finder(src_gpu, fullmask_1, keypoints_src, descriptors_gpu_src);orb_finder(dst_gpu, fullmask_2, keypoints_dst, descriptors_gpu_dst);//使用gpu提供的BruteForceMatcher進行特徵點匹配gpu::BruteForceMatcher_GPU< HammingLUT > matcher_lk;matcher_lk.match(descriptors_gpu_src, descriptors_gpu_dst, matches, gpu::GpuMat());float max_distance = 60; //定義特徵點好壞衡量距離std::vector<DMatch> good_matches; //收集較好的匹配點for (int i = 0; i < descriptors_gpu_src.rows; i++) {if (matches[i].distance < max_distance) {good_matches.push_back(matches[i]);}}Mat image_matches;drawMatches(_src_Img, keypoints_src, _dst_Img, keypoints_dst, good_matches,image_matches, Scalar(255, 0, 0), Scalar::all(-1), vector<char>(), 0);imshow("Gpu ORB", image_matches);}int main(){int num_devices = cv::gpu::getCudaEnabledDeviceCount();if (num_devices <= 0){std::cerr << "There is no device." << std::endl;return -1;}int enable_device_id = -1;for (int i = 0; i < num_devices; i++){cv::gpu::DeviceInfo dev_info(i);if (dev_info.isCompatible()){enable_device_id = i;}}if (enable_device_id < 0){std::cerr << "GPU module isn't built for GPU" << std::endl;return -1;}gpu::setDevice(enable_device_id);Mat src_Img = imread("book.bmp" , 0);Mat dst_Img = rotatedImage(src_Img, -30.0);surfExtractor(src_Img, dst_Img);orbExtractor(src_Img, dst_Img);cv::waitKey(0);return 0; }
三、運行結果
運行環境為vs2013+opencv2.4.9+cuda7.0,結果展示如下,orb演算法尋找特徵點及計算描述子速度較快,gpu版的surf特徵點對輸入圖片大小有要求,不能太小