OpenCV 如何计算给定像素的 SIFT 描述符

OpenCV how to calculate SIFT descriptor at a given pixel

大家好,我正在使用 opencv3 和 contrib。问题是我想计算给定像素的筛选描述符(不使用检测到的关键点)。

我正在尝试用给定的像素构建一个关键点向量。但是,要创建关键点,除了像素位置外,我还需要知道大小信息。

KeyPoint (Point2f _pt, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1)

谁能告诉我构造函数中的大小是多少?我需要角度信息来计算筛选描述符吗?以及如何使用 poencv3 计算它们。

@Utkarsh: 我同意 SIFT 描述符需要关键点的方向和比例信息这一事实。 David G. Lowe 的原始论文(Scale-Invariant 关键点的独特图像特征)说,"In order to achieve orientation invariance, the coordinates of the descriptor and the gradient orientations are rotated relative to the Keypoint orientation"。而 尺度信息用于在计算描述符期间选择图像的高斯模糊级别

但是,post 中的问题是关于计算给定像素的描述符。请注意,给定的像素位置不是使用所需过程计算的 SIFT 关键点。因此在这种情况下方向和比例信息不可用。因此,上一个答案中提到的 code 以默认比例(即 1)和默认方向(不旋转邻域的梯度方向)计算给定像素的 SIFT 描述符。

@腾龙: 另外,我认为您用于匹配两幅图像(原始图像和旋转图像)中的关键点的方法在某种程度上是模棱两可的。您应该分别 运行 对两个图像进行 SIFT 关键点检测,并分别计算它们相应的描述符。然后,您可以使用蛮力匹配这两组关键点。

以下代码计算图像及其 45 度旋转版本的 SIFT 关键点,然后使用蛮力匹配计算 SIFT 关键点描述符。

# include "opencv2/opencv_modules.hpp"
# include "opencv2/core/core.hpp"
# include "opencv2/features2d/features2d.hpp"
# include "opencv2/highgui/highgui.hpp"
# include "opencv2/nonfree/features2d.hpp"
# include "opencv2\imgproc\imgproc.hpp"
# include <stdio.h>

using namespace cv;

int main( int argc, char** argv )
{
    Mat img_1, img_2;

    // Load image in grayscale format
    img_1 = imread( "scene.jpg", CV_LOAD_IMAGE_GRAYSCALE );     

    // Rotate the input image without loosing the corners 
    Point center = Point(img_1.cols / 2, img_1.rows / 2);
    double angle = 45, scale = 1;
    Mat rot = getRotationMatrix2D(center, angle, scale);
    Rect bbox = cv::RotatedRect(center, img_1.size(), angle).boundingRect();
    rot.at<double>(0,2) += bbox.width/2.0 - center.x;
    rot.at<double>(1,2) += bbox.height/2.0 - center.y;
    warpAffine(img_1, img_2, rot, bbox.size());

    // SIFT feature detector
    SiftFeatureDetector detector;
    std::vector<KeyPoint> keypoints_1, keypoints_2;

    detector.detect( img_1, keypoints_1 );
    detector.detect( img_2, keypoints_2 );

    // Calculate descriptors 
    SiftDescriptorExtractor extractor;
    Mat descriptors_1, descriptors_2;

    extractor.compute( img_1, keypoints_1, descriptors_1 );
    extractor.compute( img_2, keypoints_2, descriptors_2 );

    // Matching descriptors using Brute Force
    BFMatcher matcher(NORM_L2);
    std::vector<DMatch> matches;
    matcher.match(descriptors_1, descriptors_2, matches);


    //-- Quick calculation of max and min distances between Keypoints
    double max_dist = 0; double min_dist = 100;

    for( int i = 0; i < descriptors_1.rows; i++ )
    { double dist = matches[i].distance;
      if( dist < min_dist ) min_dist = dist;
      if( dist > max_dist ) max_dist = 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)
    std::vector< DMatch > good_matches;

    for( int i = 0; i < descriptors_1.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_1, keypoints_1, img_2, keypoints_2,
               good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
               vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

    //-- Show detected matches
    imshow( "Good Matches", img_matches );

    waitKey(0);
    return 0;
  }

结果如下: