c++ Opencv sift 位置检测

Posted

技术标签:

【中文标题】c++ Opencv sift 位置检测【英文标题】:c++ Opencv sift Positiondetection 【发布时间】:2015-05-27 19:40:57 【问题描述】:

我使用 ubuntu,代码是 C++ 和 opencv。 我进行了一些测试以检测图片的某些部分。它工作得很好,但现在我想在我的大图中找到位置。代码如下:

#include...
using namespace cv;

int main(int argc, char** argv) 



Mat img = imread("/home/ubuntu/workspace2/sift/src/inputklein.jpg",CV_LOAD_IMAGE_GRAYSCALE);


 while(1)
             Mat img2 =imread("/home/ubuntu/workspace2/sift/src/input.jpeg",CV_LOAD_IMAGE_GRAYSCALE);   //frame
             //initialize SIFT
             // Create smart pointer for SIFT feature detector.
             SIFT sift;
             vector<KeyPoint> key_points;
             vector<KeyPoint> key_points2;

             //-- Step 1: Detect the keypoints using SURF Detector
             int minHessian = 100;
             SurfFeatureDetector detector( minHessian );
             detector.detect( img, key_points );
             detector.detect( img2, key_points2 );

             //-- Step 2: Calculate descriptors (feature vectors)
             SurfDescriptorExtractor extractor;

             Mat descriptors1;
             Mat descriptors2;

             extractor.compute( img, key_points, descriptors1 );
             extractor.compute( img2, key_points2, descriptors2 );


             //-- Step 3: Matching descriptor vectors using FLANN matcher
              FlannBasedMatcher matcher;
              std::vector< DMatch > matches;
              matcher.match( descriptors1, descriptors2, matches );

              double max_dist = 20; double min_dist = 10;


              //-- Quick calculation of max and min distances between keypoints
                for( int i = 0; i < descriptors1.rows; i++ )
                 double dist = matches[i].distance;
                  if( dist < min_dist ) min_dist = dist;
                  if( dist > max_dist ) max_dist = dist;
                

               //std::cout<<"Max dist :"<< max_dist ;
               //std::cout<<"Min dist :"<< min_dist ;

               //-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist,
                //-- or a small arbitary value ( 0.02 ) in the event that min_dist is very
                //-- small)
                //-- PS.- radiusMatch can also be used here.
                std::vector< DMatch > good_matches;

                for( int i = 0; i < descriptors1.rows; i++ )
                 if( matches[i].distance <= max(2*min_dist, 0.02) )
                   good_matches.push_back( matches[i]); 
                

                //-- Draw only "good" matches
                Mat img_matches;
                drawMatches( img, key_points, img2, key_points2,
                             good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
                             vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );


              //std::cout<<key_points[1].pt.x<<"\n";
              //std::cout<<key_points2[1].pt.y<<"\n";



   //-- 3. Apply the classifier to the frame


         cv::imshow( "test", img_matches ); //img_matches
        waitKey(30);
 

return 0;

好的,但是我怎样才能得到位置或关键点最多的位置。有人可以给我一个提示,我必须如何理解它? 我看到我可以使用这样的东西: "key_points[1].pt.x" 或 y,但我不是必须检查每个 x,y 位置吗? 接下来是: good_matches[1].queryIdx 但这是同一个问题。我怎样才能找到它在哪里?

    对我来说一个大问题是,为什么行上只有一个循环? 它不应该超过 row 和 cols 吗?在我的目的地,它应该像在数组(x,y)中一样工作,我检查每个位置是否相同......(有没有简单数据类型的问题......)

    在哪里可以找到/或如何找到 drawMatches 代码的位置(例如)。 正常方式我会尝试“打开声明”(使用 Eclipse、C++),但我只看到标题而不是真正的函数。 我需要代码并希望我可以在没有 opencv 的情况下更改所有内容,或者我可以执行循环...所以我必须了解如何阅读和使用向量 DMatch...

感谢您的帮助。 最好的问候,

【问题讨论】:

【参考方案1】:

如果我理解你,你会找到关键点位置并对它们进行分类。要知道关键点的位置,您需要做一个穿过关键点向量的圆环并将位置保存在矩阵中。

然后,您可以将此关键点的位置与图像区域(无论您想要什么)进行比较,并根据图像中的区域对它们进行分类。

Mat pointsInFirstAreaRight, pointInFirstAreaLeft;
    for (int i = 0; i < 2; i++)
           for(vector<DMatch>::const_iterator it = keypoints[i].begin(); it!= keypoints[i].end(); ++it)
                 // Get the position of keypoints
                 float x = [it->queryIdx].pt.x;
                 float y = [it->queryIdx].pt.y;

                 //If the point detected are in the 20 first pixels   
                 if ( (x < 20) && (y > 20) )
                 
                       //Classify this point in this area
                       if ( i == 0)
                       pointsInFirstAreaRight.push_back(Point2f(x, y));
                       else if (i == 1)
                       pointsInFistAreaLeft.push_back(Point2f(x, y));
                  
          
     

关于 sift 功能,它同时进行检测和提取。我在我的代码中这样使用它:

>  SIFT sift;
>         
>         /* get keypoints on the images */
>         sift(imagenI, Mat(), keypoints[0], descriptors[0]);
>         sift(imagenD, Mat(), keypoints[1], descriptors[1]);

然后我检测关键点并提取点的描述符。

那我只需要匹配即可。

希望能帮到你。

【讨论】:

我不知道我是否理解你的代码。抱歉,我在 2 天后回答,但我认为我不太了解 sift 的工作原理,我想先阅读。但这并没有帮助。参数pointsInFirstAreaRight是什么意思...您的代码中的问题是我无法使用.push_back之类的某些功能。我想在 fpga 中给出代码以及我的理解,它不喜欢带有库的函数。所以我需要一个非常简单的代码...... 参数pointsInFirstArea 是因为我认为您希望根据关键点的位置对关键点进行分类,因此该参数是关键点向量,用于保存(20 x 20)区域中的关键点。 关于 push_back 功能对我来说效果很好,我不知道你为什么可以使用它。在这种情况下,此函数复制点 2f 中的关键点。请参阅我放入 anser 中的筛选代码。

以上是关于c++ Opencv sift 位置检测的主要内容,如果未能解决你的问题,请参考以下文章

sift&surf检测关键点及描述子

如何使用 C++ 在 OpenCV 4.2.0 中使用 SIFT? [关闭]

OpenCV SIFT特征算法详解与使用

(转载)利用SIFT和RANSAC算法(openCV框架)实现物体的检测与定位,并求出变换矩阵(findFundamentalMat和findHomography的比较) 置顶

opencv2.4.3中基于sift算法完成特征检测后,有没有图像融合的函数。直接把检测完的两幅图像拼接起来。

Opencv实现图像无缝拼接,Sift查找特征点,Flann进行匹配