用C++重写了OPENCV SURF算法例子

 

用C++重写了OPENCV SURF算法例子(find_obj)
2012-2-7 创建

OPENCV 2.0后大量使用了标准模板类STL,而且图像结构统一为Mat,并提供了SURF类,而OPENCV2.2中带有的find_obj.cpp实际上还是主要使用c结构编写的,我也一直没有找到相对应C++例子
因此花时间改写了一下,为了例子的简洁,删除了不使用FLANN的brute force matching,而且没有进行平面映射,代码仅供参考

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

void newFlannFindPairs(const vector<KeyPoint>& obj_keypoints,
     const vector<float>& obj_descriptors, 
     const vector<KeyPoint>& img_keypoints, 
     const vector<float>& img_descriptors, 
     vector<int>& ptpairs )
{
	// find nearest neighbors using FLANN
	int length = obj_descriptors.size() / obj_keypoints.size();

	cv::Mat m_object(obj_keypoints.size(), length, CV_32F);
	cv::Mat m_image(img_keypoints.size(), length, CV_32F);

	cv::Mat temp_object(obj_descriptors, true);
	cv::Mat temp_image(img_descriptors, true);

	//Use memcpy to keep Mat size
	memcpy(m_object.data, temp_object.data, temp_object.total() * sizeof(float));
	memcpy(m_image.data, temp_image.data, temp_image.total() * sizeof(float));

	//FLANN
	cv::Mat m_indices(obj_keypoints.size(), 2, CV_32S);
	cv::Mat m_dists(obj_keypoints.size(), 2, CV_32F);

	cv::flann::Index flann_index(m_image, cv::flann::KDTreeIndexParams(4));  // using 4 randomized kdtrees
	flann_index.knnSearch(m_object, m_indices, m_dists, 2, cv::flann::SearchParams(64) ); // maximum number of leafs checked

	//Save to point pairs
	int* indices_ptr = m_indices.ptr<int>(0);
	float* dists_ptr = m_dists.ptr<float>(0);
	for (int i=0;i<m_indices.rows;++i) 
	{
		if (dists_ptr[2*i]<0.6*dists_ptr[2*i+1]) 
		{
			ptpairs.push_back(i);
			ptpairs.push_back(indices_ptr[2*i]);
		}
	}
}

int surfTest(const char* object_filename, const char* scene_filename)
{
	double tt = (double)cvGetTickCount();

	Mat obj = imread(object_filename,0);
	Mat img = imread(scene_filename,0);
	if( (img.data == NULL) || (obj.data == NULL) )
	{
		cout<<"Unable to read images "<<endl;
		return 1;
	}

	// Create the SURF object
	Mat obj_mask = 255 * Mat::ones(obj.rows,obj.cols,CV_8U);
	Mat img_mask = 255 * Mat::ones(img.rows,img.cols,CV_8U);
	const int HessianThreshold = 500;
	SURF surf(HessianThreshold);

	vector<KeyPoint> obj_keypoints;
	vector<float> obj_descriptors;
	vector<KeyPoint> img_keypoints;
	vector<float> img_descriptors;

	surf(obj, obj_mask, obj_keypoints, obj_descriptors);
	surf(img, img_mask, img_keypoints, img_descriptors);

	// Plot the keypoints
	const int radius = 1, thickness = 2;
	const Scalar obj_color(255,0,0,0);
	const Scalar img_color(0, 255,0,0);

	vector<int> ptpairs;
	newFlannFindPairs(obj_keypoints, obj_descriptors, img_keypoints, img_descriptors, ptpairs);

	double tt_f = (double)cvGetTickCount() - tt;
	printf( "Extraction pair point time = %gms\n", tt_f/(cvGetTickFrequency()*1000.));

	Mat correspond = Mat::zeros(img.rows + obj.rows, img.cols, CV_8U);
	cv::Rect objRect(Point(0, 0), obj.size());
	Mat objROI = correspond(objRect);
	obj.copyTo(objROI);

	cv::Rect imgRect(Point(0, objRect.height), img.size());
	Mat imgROI = correspond(imgRect);
	img.copyTo(imgROI);


	for( int i = 0; i < (int)ptpairs.size(); i += 2 )
	{
		Point p1 = Point(cvRound(obj_keypoints[ptpairs[i]].pt.x), cvRound(obj_keypoints[ptpairs[i]].pt.y));
		Point p2 = Point(cvRound(img_keypoints[ptpairs[i+1]].pt.x), cvRound(img_keypoints[ptpairs[i+1]].pt.y + objRect.height));

		line(correspond, p1, p2, obj_color);
	}

	imshow("SURF_CORRESPOND", correspond);
	waitKey(0);
	return 0;
}

int main(int argc, char** argv)
{
	const char* object_filename = argc == 3 ? argv[1] : "../debug/box.png";
	const char* scene_filename = argc == 3 ? argv[2] : "../debug/box_in_scene.png";

	return surfTest(object_filename, scene_filename);
}


 


 


使用例子带有的图片,性能如下:

OPENCV自带的C可执行程序:
Object Descriptors: 593
Image Descriptors: 782
Extraction time = 363.425ms
Using approximate nearest neighbor search

重新编译的DEBUG版
Object Descriptors: 593
Image Descriptors: 782
Extraction time = 1316.22ms
Using approximate nearest neighbor search

重新改写的C++代码
注意功能比原例子减少了平面映射,只提取对应点并显示
DEBUG 1820.17ms 
RELEASE 402.799ms

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值