OpenCV ASift C++ Implementation

A C++ version of this.  My version has not been parallelized or optimized in any way.  Please leave any bug reports in the comments below.

ASiftDetector.h

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

using namespace cv;

class ASiftDetector
{
public:
  ASiftDetector();

  void detectAndCompute(const Mat& img, std::vector< KeyPoint >& keypoints, Mat& descriptors);

private:
  void affineSkew(double tilt, double phi, Mat& img, Mat& mask, Mat& Ai);
};

ASiftDetector.cpp

#include "ASiftDetector.h"

#include <iostream>

#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

ASiftDetector::ASiftDetector()
{

}
  
void ASiftDetector::detectAndCompute(const Mat& img, std::vector< KeyPoint >& keypoints, Mat& descriptors)
{
  keypoints.clear();
  descriptors = Mat(0, 128, CV_32F);
  for(int tl = 1; tl < 6; tl++)
  {
    double t = pow(2, 0.5*tl);
    for(int phi = 0; phi < 180; phi += 72.0/t)
    {
      std::vector<KeyPoint> kps;
      Mat desc;

      Mat timg, mask, Ai;
      img.copyTo(timg);

      affineSkew(t, phi, timg, mask, Ai);

#if 0
      Mat img_disp;
      bitwise_and(mask, timg, img_disp);
      namedWindow( "Skew", WINDOW_AUTOSIZE );// Create a window for display.
      imshow( "Skew", img_disp ); 
      waitKey(0);
#endif

      SiftFeatureDetector detector;
      detector.detect(timg, kps, mask);
  
      SiftDescriptorExtractor extractor;
      extractor.compute(timg, kps, desc);

      for(unsigned int i = 0; i < kps.size(); i++)
      {
        Point3f kpt(kps[i].pt.x, kps[i].pt.y, 1);
        Mat kpt_t = Ai*Mat(kpt);
        kps[i].pt.x = kpt_t.at<float>(0,0);
        kps[i].pt.y = kpt_t.at<float>(1,0);
      }
      keypoints.insert(keypoints.end(), kps.begin(), kps.end());
      descriptors.push_back(desc);
    }   
  }
}
   
void ASiftDetector::affineSkew(double tilt, double phi, Mat& img, Mat& mask, Mat& Ai)
{
  int h = img.rows;
  int w = img.cols;

  mask = Mat(h, w, CV_8UC1, Scalar(255));  

  Mat A = Mat::eye(2,3, CV_32F);

  if(phi != 0.0)
  {
    phi *= M_PI/180.;
    double s = sin(phi);
    double c = cos(phi);
    
    A = (Mat_<float>(2,2) << c, -s, s, c);

    Mat corners = (Mat_<float>(4,2) << 0, 0, w, 0, w, h, 0, h);
    Mat tcorners = corners*A.t();
    Mat tcorners_x, tcorners_y;
    tcorners.col(0).copyTo(tcorners_x);
    tcorners.col(1).copyTo(tcorners_y);
    std::vector<Mat> channels;
    channels.push_back(tcorners_x);
    channels.push_back(tcorners_y);
    merge(channels, tcorners);

    Rect rect = boundingRect(tcorners);
    A =  (Mat_<float>(2,3) << c, -s, -rect.x, s, c, -rect.y);
    
    warpAffine(img, img, A, Size(rect.width, rect.height), INTER_LINEAR, BORDER_REPLICATE);
  }
  if(tilt != 1.0)
  {
    double s = 0.8*sqrt(tilt*tilt-1);
    GaussianBlur(img, img, Size(0,0), s, 0.01);
    resize(img, img, Size(0,0), 1.0/tilt, 1.0, INTER_NEAREST);
    A.row(0) = A.row(0)/tilt;
  }
  if(tilt != 1.0 || phi != 0.0)
  {
    h = img.rows;
    w = img.cols;
    warpAffine(mask, mask, A, Size(w, h), INTER_NEAREST);
  }
  invertAffineTransform(A, Ai);
}

22 Replies to “OpenCV ASift C++ Implementation”

  1. I tried to create 2 files as your code. But an error occurred at std::vector kps; And then I modified it to std::vector kps; That place’s ok but the other error occurred: kpt_t.at(0,0); I pointed this line, the error info is “no instance of overloaded function at cv::Mat::at….” and it cant understand M_PI. Can you help me?

    1. Just add the following to the top of the cpp file to get rid of the M_PI error:

      #define _USE_MATH_DEFINES
      #include

      Also, make sure you are using OpenCV 2.4.9. Not using that version may result in the other error you described.

      1. I added #define _USE_MATH_DEFINES and M_PI is ok now.
        Im using OpenCV_2.4.9 and Visual Studio 2012. But I dont know why the error still occurred at “kps[i].pt.x = kpt_t.at(0,0);” and “Mat_(2,2)”. It can not build. And then I tried to change “kps[i].pt.x = kpt_t.at(0,0);” to “kps[i].pt.x = kpt_t.at(0,0);” and “Mat_(2,2)” to “Mat_(2,2)”. They’re ok and can build successfully. But it doesnt work in runtime 🙂

      2. Omg!!!! Because of web tag HTML, when you post your code here, this website will automatically remove your code. For example: Mat_(2,2) to Mat_(2,)

      3. Omg!!!! Because of web tag HTML, when you post your code here, this website will automatically remove your code. For example: Mat_(2,2) to Mat_(2,2)

        1. Ahhhh, you are absolutely correct. Stuff must’ve gotten messed up when I copied and pasted. I added all of the templated stuff back in that had been removed. Thanks for noticing! What kind of runtime errors are you getting?

    1. It should be as simple as:


      #include "ASiftDetector.h"
      int main( int argc, char** argv )
      {

      if( argc != 2)
      {
      cout < <" Need to give an image filepath!" << endl; return -1; } Mat my_image; my_image = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); std::vector > keypoints;
      Mat descriptors;
      ASiftDetector asd;
      asd.detectAndCompute(my_image, keypoints, descriptors);
      }

      You can use the output to do feature matching or other computer vision stuff as you would with any other OpenCV detector. For examples of how to do that, look at OpenCV’s website.

        1. For filtering out bad matches, people typically do a 2-nearest neighbor match and use the ratio test to see whether it is a good match or not. I’ve had good results doing that with ASIFT. I can’t tell for sure how they do it in the demo. You can further filter out bad matches by estimating the fundamental matrix for the two images using a RANSAC approach, and then only keep matches which were inliers.

    1. This version isn’t using GPU or anything. You can try swapping out the SIFT features for SIFTGpu. You can also try reducing the number of views that it generates. I’ve never used the original and I’ve never looked at the code, so I can’t say for sure why it is slower.

  2. i’m using opencv 2.4 but i’m having the following error, Maybe i’m unable to import opencv headers. (includes)

    imported include headers

    #include
    #include
    #include
    #include
    #include

    SiftDescriptorExtractor extractor; // ERROR undeclared identifier
    extractor.compute(timg, kps, desc); // ERROR undeclared identifier

Leave a Reply to admin Cancel reply

Your email address will not be published. Required fields are marked *