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); }
Hi, is this implementation for ASIFT the same as the author’s? i.e. http://www.cmap.polytechnique.fr/~yu/research/ASIFT/demo.html
Thanks!
I believe so. You may have to change the number of tilt variations considered to replicate their results.
Hi, is this code complete? Help please.
Hi Fiong, the code should work as is. What kind of errors are you getting?
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?
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.
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 🙂
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,)
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)
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?
Very useful. I am recommending to Google that they buy this from you.
Could you please show sample code?
It should be as simple as:
#include "ASiftDetector.h"
int main( int argc, char** argv )
{
if( argc != 2)> keypoints;
{
cout < <" Need to give an image filepath!" << endl; return -1; } Mat my_image; my_image = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); std::vector
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.
Oh Thank you very much. I got it.
Do you know which feature matching methode they use on here: http://www.cmap.polytechnique.fr/~yu/research/ASIFT/demo.html
This demo is giving me great results but I tried to implement this code and tried different feature matching methods but unfortunately I can’t reflect the same results as the online demo. Would appreciate if you could tell which one is used in the online demo.
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.
why its soo slow?
the original code works much faster
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.
how to input the images of the ‘.jpg’ format?the demo is the ‘.png’ format
opencv should be able to accept jpg
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
The header may have changed to nonfree/features2d.hpp