您的位置:首页 > 编程语言 > C语言/C++

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

2012-02-07 16:34 363 查看
 
用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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息