opencv上gpu版surf特征点与orb特征点提取及匹配实例

一、前言

本文主要实现了使用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特征点对输入图片大小有要求,不能太小







  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值