【问题标题】:OpenCV Keypoint matching DMatch distance variableOpenCV 关键点匹配 DMatch 距离变量
【发布时间】:2014-12-20 07:42:25
【问题描述】:

我正在研究Features2D + Homography to find a known object OpenCV 教程中的代码..

我没看清楚,matcher类中的距离变量是什么。是两幅图像中匹配关键点的像素之间的距离吗?

QA 表示其相似性度量(欧几里得距离或二进制描述符的汉明距离),并根据描述符向量之间的距离计算得出。

是否有人可以分享如何计算此距离或如何在不使用 OpenCV 现有匹配器的情况下匹配关键点的信息。

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

  double max_dist = 0; double min_dist = 100;

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

谢谢。

【问题讨论】:

  • 是描述符之间的距离,不是关键点之间的距离
  • @berak 你能提供更多信息如何计算它。因为我喜欢在不使用现有匹配器的情况下进行关键点匹配。

标签: opencv computer-vision feature-detection


【解决方案1】:

我在使用 SIFT 特征检测器进行实时对象匹配时遇到了一些问题。这是我的视频解决方案。

首先我创建了一个结构来存储匹配的关键点。该结构包含模板图像中关键点的位置、输入图像中关键点的位置和相似性度量。这里我使用向量的互相关作为相似性度量。

struct MatchedPair
    {
        Point locationinTemplate;
        Point matchedLocinImage;
        float correlation;
        MatchedPair(Point loc)
        {
            locationinTemplate=loc;
        }
    }

我将根据它们的相似性选择对匹配的关键点进行排序,因此我需要一个辅助函数来告诉std::sort() 如何比较我的MatchedPair 对象。

bool comparator(MatchedPair a,MatchedPair b)
{
        return a.correlation>b.correlation;
}

现在主代码开始了。我已经使用标准方法从输入图像和模板图像中检测和解密特征。计算特征后我实现了自己的匹配函数。这就是您要寻找的答案

 int main()
    {
        Mat templateImage = imread("template.png",IMREAD_GRAYSCALE); // read a template image
        VideoCapture cap("input.mpeg"); 
        Mat frame; 

        vector<KeyPoint> InputKeypts,TemplateKeypts; 
        SiftFeatureDetector detector;
        SiftDescriptorExtractor extractor;
        Mat InputDescriptor,templateDescriptor,result; 
        vector<MatchedPair> mpts; 
        Scalar s;
        cap>>frame; 
        cvtColor(image,image,CV_BGR2GRAY);
        Mat outputImage =Mat::zeros(templateImage.rows+frame.rows,templateImage.cols+frame.cols,CV_8UC1);
        detector.detect(templateImage,TemplateKeypts); // detect template interesting points
        extractor.compute(templateImage,TemplateKeypts,templateDescriptor); 

        while( true) 
        {
            mpts.clear(); // clear for new frame
            cap>>frame;  // read video to frame
            outputImage=Mat::zeros(templateImage.rows+frame.rows,templateImage.cols+frame.cols,CV_8UC1); // create output image 
            cvtColor(frame,frame,CV_BGR2GRAY);
            detector.detect(frame,InputKeypts);
            extractor.compute(frame,InputKeypts,InputDescriptor); // detect and descrypt frames features

            /*
                So far we have computed descriptors for template and current frame using traditional methods
                From now onward we are going to implement our own match method

     - Descriptor matrixes are by default have 128 colums to hold features of a keypoint.    
     - Each row in descriptor matrix represent 128 feature of a keypoint.

 Match methods are using this descriptor matrixes to calculate similarity.

My approach to calculate similarity is using cross correlation of keypoints descriptor vector.Check code below to see how I achieved.
        */

   // Iterate over rows of templateDesciptor ( for each keypoint extracted from     //  template Image)   i keypoints in template,j keypoints in input
            for ( int i=0;i<templateDescriptor.rows;i++)
            {
                mpts.push_back(MatchedPair(TemplateKeypts[i].pt));
                mpts[i].correlation =0;
                for ( int j=0;j<InputDescriptor.rows;j++)
                {
                    matchTemplate(templateDescriptor.row(i),InputDescriptor.row(j),result,CV_TM_CCOR_NORMED);
 // I have used opencvs built function to calculate correlation.I am calculating // row(i) of templateDescriptor with row(j) of inputImageDescriptor.
                    s=sum(result); // sum is correlation of two rows
// Here I am looking for the most similar row in input image.Storing the correlation of best match and matchLocation in input image.
                    if(s.val[0]>mpts[i].correlation)
                    {
                       mpts[i].correlation=s.val[0];
                       mpts[i].matchedLocinImage=InputKeypts[j].pt;
                    }
                }

            }

// I would like to show template,input and matching lines in one output.            templateImage.copyTo(outputImage(Rect(0,0,templateImage.cols,templateImage.rows)));
            frame.copyTo(outputImage(Rect(templateImage.cols,templateImage.rows,frame.cols,frame.rows)));

  // Here is the matching part. I have selected 4 best matches and draw lines         // between them. You should check for correlation value again because there can // be 0 correlated match pairs.

            std::sort(mpts.begin(),mpts.end(),comparator);
            for( int i=0;i<4;i++)
            {

                if ( mpts[i].correlation>0.90)
                {
// During drawing line take into account offset of locations.I have added 
// template image to upper left of input image in output image.  
            cv::line(outputImage,mpts[i].locationinTemplate,mpts[i].matchedLocinImage+Point(templateImage.cols,templateImage.rows),Scalar::all(255));
                }
            }
            imshow("Output",outputImage);
            waitKey(33);
        }

    }

【讨论】:

  • 您能否减少您的帖子,使其专注于解决 OP 的问题,而不是谈论您的方法以及它如何解决您的问题?
  • @rayryeng 我希望他和未来的访问者能够轻松理解这就是我使用许多 cmets 的原因。重点是数学部分,我已经预先定义了一些变量和结构,因此它们应该出现在代码中。我还告诉了我是如何比较描述符的,因此一旦他理解描述符的含义,他就可以实现自己的匹配方法,而不是使用我的匹配方法。如果您可以编辑我的答案以使其更清楚,我将感谢您的帮助。
  • 哦,我明白了!那没关系。我会离开它:)
猜你喜欢
  • 2012-02-09
  • 2016-05-03
  • 2012-11-20
  • 2012-05-01
  • 1970-01-01
  • 2015-07-21
  • 1970-01-01
  • 1970-01-01
  • 2022-06-18
相关资源
最近更新 更多