OpenCV 2.2 中的 Sift 实现

33

请问有人知道使用OpenCV 2.2实现SIFT的示例链接。 谢谢。

6个回答

35

以下是一个最简示例:

#include <opencv/cv.h>
#include <opencv/highgui.h>

int main(int argc, const char* argv[])
{
    const cv::Mat input = cv::imread("input.jpg", 0); //Load as grayscale

    cv::SiftFeatureDetector detector;
    std::vector<cv::KeyPoint> keypoints;
    detector.detect(input, keypoints);

    // Add results to image and save.
    cv::Mat output;
    cv::drawKeypoints(input, keypoints, output);
    cv::imwrite("sift_result.jpg", output);

    return 0;
}

在OpenCV 2.3上测试过


1
如何匹配两张图片? - maximus
5
请查看OpenCV2.3.1/samples/cpp/matcher_simple.cpp https://code.ros.org/trac/opencv/browser/trunk/opencv/samples/cpp/matcher_simple.cpp。您需要使用`DescriptorMatcher`(例如`BruteForceMatcher`)。有关此类的更多文档可以在此找到:http://opencv.itseez.com/modules/features2d/doc/common_interfaces_of_descriptor_matchers.html。 - Unapiedra
6
为了使用OpenCV 2.4.4编译您的代码,我需要添加#include <opencv2/nonfree/features2d.hpp> - Alessandro Jacopson

30

你可以通过多种方式获取SIFT检测器和基于SIFT的提取器。其他人已经提供了更直接的方法,我将提供一种更加“软件工程”的方法,可以使你的代码更加灵活适应变化(例如更容易切换到其他检测器和提取器)。

首先,如果你想使用内置参数获取检测器,最好的方法是使用OpenCV的工厂方法来创建它。以下是具体步骤:

#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <vector>

using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{        
  Mat image = imread("TestImage.jpg");

  // Create smart pointer for SIFT feature detector.
  Ptr<FeatureDetector> featureDetector = FeatureDetector::create("SIFT");
  vector<KeyPoint> keypoints;

  // Detect the keypoints
  featureDetector->detect(image, keypoints); // NOTE: featureDetector is a pointer hence the '->'.

  //Similarly, we create a smart pointer to the SIFT extractor.
  Ptr<DescriptorExtractor> featureExtractor = DescriptorExtractor::create("SIFT");

  // Compute the 128 dimension SIFT descriptor at each keypoint.
  // Each row in "descriptors" correspond to the SIFT descriptor for each keypoint
  Mat descriptors;
  featureExtractor->compute(image, keypoints, descriptors);

  // If you would like to draw the detected keypoint just to check
  Mat outputImage;
  Scalar keypointColor = Scalar(255, 0, 0);     // Blue keypoints.
  drawKeypoints(image, keypoints, outputImage, keypointColor, DrawMatchesFlags::DEFAULT);

  namedWindow("Output");
  imshow("Output", outputImage);

  char c = ' ';
  while ((c = waitKey(0)) != 'q');  // Keep window there until user presses 'q' to quit.

  return 0;

}

使用工厂方法的原因是灵活的,因为现在你可以通过改变传递给“create”工厂方法的参数来更改到不同的关键点检测器或特征提取器,例如SURF:

Ptr<FeatureDetector> featureDetector = FeatureDetector::create("SURF");
Ptr<DescriptorExtractor> featureExtractor = DescriptorExtractor::create("SURF");

要创建其他检测器或提取器的可能参数,请参见: http://opencv.itseez.com/modules/features2d/doc/common_interfaces_of_feature_detectors.html#featuredetector-create

http://opencv.itseez.com/modules/features2d/doc/common_interfaces_of_descriptor_extractors.html?highlight=descriptorextractor#descriptorextractor-create

现在,使用工厂方法意味着您可以方便地创建检测器或提取器而不必猜测要传递哪些合适的参数。这对于新手来说非常方便。但是,如果您想创建自己的自定义SIFT检测器,则可以使用自定义参数创建SiftDetector对象,并将其包装到智能指针中,然后像上面那样使用featureDetector智能指针变量引用它。


谢谢,这个很有帮助。 :) - mr.pppoe
我忘记了补充一点 - 对于一些人来说可能不太明显 - 你可以混合和匹配探测器和提取器。例如,您可以拥有一个SIFT探测器和一个SURF提取器,以便在SIFT关键点上提取SURF描述符,反之亦然。请点击上面的链接查看其他可用的探测器和提取器。 - lightalchemist
嗨,lightalchemist,我们可以将描述符的维度从128更改为64或类似的值吗? - MMH
1
在2.4 beta版本中,SURF和SIFT被移动到非自由模块中,以指示在用户应用程序中使用这些算法可能存在的法律问题。因此现在必须包含"opencv2/nonfree/nonfree.hpp"头文件。它们也继承了cv::Algorithm,所以在使用SURF、SIFT算法之前必须调用cv::initModule_nonfree()以避免注册问题。参考链接1: http://answers.opencv.org/question/411/feature-detector-crash/cv::initModule_nonfree();//此行代码很重要
参考链接2: https://dev59.com/B2gu5IYBdhLWcg3wpYnJ
- user2301281

6
在OpenCV 2.4中使用SIFT非免费特征检测器的简单示例。
#include <opencv2/opencv.hpp>
#include <opencv2/nonfree/nonfree.hpp>
using namespace cv;

int main(int argc, char** argv)
{

    if(argc < 2)
        return -1;

    Mat img = imread(argv[1]);

    SIFT sift;
    vector<KeyPoint> key_points;

    Mat descriptors;
    sift(img, Mat(), key_points, descriptors);

    Mat output_img;
    drawKeypoints(img, key_points, output_img);

    namedWindow("Image");
    imshow("Image", output_img);
    waitKey(0);
    destroyWindow("Image");

    return 0;
}

5

OpenCV提供了SIFTSURF这里也有)以及其他特征描述符的开箱即用功能。
请注意,SIFT算法受到专利保护,因此可能与常规的OpenCV使用/许可证不兼容。


3

以下是使用OpenCV 2.4中的SIFT非免费特征检测器的另一个简单示例。请确保添加opencv_nonfree240.lib依赖项。

#include "cv.h"
#include "highgui.h"
#include <opencv2/nonfree/nonfree.hpp>

int main(int argc, char** argv)
{
   cv::Mat img = cv::imread("image.jpg");

   cv::SIFT sift(10);   //number of keypoints

   cv::vector<cv::KeyPoint> key_points;

   cv::Mat descriptors, mascara;
   cv::Mat output_img;

   sift(img,mascara,key_points,descriptors);
   drawKeypoints(img, key_points, output_img);

   cv::namedWindow("Image");
   cv::imshow("Image", output_img);
   cv::waitKey(0);

   return 0;
}

1

如果有人想知道如何使用两张图片来实现,请看以下方法:

import numpy as np
import cv2

print ('Initiate SIFT detector')
sift = cv2.xfeatures2d.SIFT_create()
print ('find the keypoints and descriptors with SIFT')
gcp1, des1 = sift.detectAndCompute(src_img,None)
gcp2, des2 = sift.detectAndCompute(trg_img,None)

# create BFMatcher object
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)


matches = bf.match(des1,des2)
# Sort them in the order of their distance.
matches = sorted(matches, key = lambda x:x.distance)

#print only the first 100 matches
img3 = drawMatches(src_img, gcp1, trg_img, gcp2, matches[:100])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接