用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