OpenCV how to create a DescriptorExtractor object - c++

I am using OpenCV C++ library but I don't manage to create a DescriptorExtractor object.
Here is what I did :
Mat img = imread("testOrb.jpg",CV_LOAD_IMAGE_UNCHANGED);
std::vector<KeyPoint> kp;
cv::Ptr<cv::ORB> detector = cv::ORB::create();
detector->detect( img, kp )
//this part works
DescriptorExtractor descriptorExtractor;
Mat descriptors;
descriptorExtractor.compute(img, kp, descriptors);
//when these 3 lines are added, an error is thrown
But I have the following error message :
OpenCV Error: The function/feature is not implemented () in detectAndCompute, file ...

DescriptorExtractor is an abstract class, so you can't instantiate it. It's just a common interface for descriptor extractors. You can do like:
Ptr<DescriptorExtractor> descriptorExtractor = ORB::create();
Mat descriptors;
descriptorExtractor->compute(img, kp, descriptors);
Note that exists also FeatureDetector, that is the common interface for detecting keypoints, so you can do:
std::vector<KeyPoint> kp;
Ptr<FeatureDetector> detector = ORB::create();
detector->detect(img, kp);

Related

Want to detect features and match the feature in 2 different frames

I'm currently using OpenCV 3.4.0, c++ in QT creator.
I've tried sample code in this page
https://docs.opencv.org/2.4/doc/tutorials/features2d/feature_description/feature_description.html
int minHessian = 400;
cv::xfeatures2d::SurfFeatureDetector detector(minHessian);
vector<KeyPoint> keypoints1, keypoints2;
detector.detect(img1, keypoints1);
detector.detect(img2, keypoints2);
// computing descriptors
cv::xfeatures2d::SurfDescriptorExtractor extractor;
Mat descriptors1, descriptors2;
extractor.compute(img1, keypoints1, descriptors1);
extractor.compute(img2, keypoints2, descriptors2);
// matching descriptors
BFMatcher matcher(NORM_L2);
vector<DMatch> matches;
matcher.match(descriptors1, descriptors2, matches);
// drawing the results
namedWindow("matches", 1);
Mat img_matches;
drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches);
imshow("matches", img_matches);
waitKey(0);
but the code kept returning error
no matching function for call to 'cv::xfeatures2d::SURF::SURF(int&)(2nd line)
cannot declare variable 'detector' to be of abstract type 'cv::xfeatures2d::SURF'(2nd line)
cannot declare variable 'extractor' to be of astract type 'cv::xfeatures2d::SURF'(7th line)
I have imported all the necessary modules I think including xfeatures2d
What is the problem?
And are there any other sample codes that I can try?
Your coding reflects an older version of OpenCV which is not compatible with OpenCV 3.4.0. You can try like so. It is better to convert the template image to a grayscale image for better matching:
cv::Ptr<Feature2D> detector = cv::xfeatures2d::SurfFeatureDetector::create();
detector->detect(img1, keypoints1);
cv::Ptr<DescriptorExtractor> extractor = cv::xfeatures2d::SurfFeatureDetector::create();
extractor->compute(img1, keypoints1, descriptors1);

OpenCV in C++: "Unknown Type Name"

I'm trying to follow along with the OpenCV tutorial, found here. Part of the tutorial is to create a SURF feature detector.
Unlike the tutorial, my code is in a header file, like this:
class Img {
Mat mat;
int minHessian = 400;
SurfFeatureDetector detector(minHessian);
public:
...
}
The error I'm getting occurs on the line
SurfFeatureDetector detector(minHessian);
and the error is:
Unknown type name 'minHessian'
When I do not put this in a separate class, the compiler does not complain. I have also checked and I have imported the required libraries.
Can anybody tell me what the error is, and how to fix it?
I read the opencv tutorial code:
Mat img1 = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
Mat img2 = imread(argv[2], CV_LOAD_IMAGE_GRAYSCALE);
if(img1.empty() || img2.empty())
{
printf("Can't read one of the images\n");
return -1;
}
// detecting keypoints
SurfFeatureDetector detector(400);
vector<KeyPoint> keypoints1, keypoints2;
detector.detect(img1, keypoints1);
detector.detect(img2, keypoints2);
....
ans as I understand, in this code, the SurfFeatureDetector detector(minHessian); is not a signature of a function that you can write in your header file as you did; but it's actually calling the SurfFeatureDetector function in the code.
So, I think if you remove it from your header file code, and put it in your function(s), where you want call it, it may work.

Loading saved SURF keypoints

I am detecting SURF features in an image and then writing them to a yml file. I then want to load the features from the yml file again to try and detect an object but at the moment I'm having trouble loading the keypoints to draw them on an image.
I'm writing the keypoints like so:
cv::FileStorage fs("keypointsVW.yml", cv::FileStorage::WRITE);
write(fs, "keypoints_1", keypoints_1);
fs.release();
I am trying to read them like so:
cv::FileStorage fs2("keypointsVW.yml", cv::FileStorage::READ);
read(fs2, "keypoints_1", keypoints_1);
fs2.release();
But this is producing a host of errors.
Detection and draw code:
cv::Mat img_1 = cv::imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
int minHessian = 400;
cv::SurfFeatureDetector detector(minHessian);
std::vector<cv::KeyPoint> keypoints_1;
detector.detect(img_1, keypoints_1);
cv::Mat img_keypoints_1;
//......write code
//.......read code
drawKeypoints(img_1, keypoints_1, img_keypoints_1);
imshow("keypoints_1", img_keypoints_1);
Found the solution, I'll post it here in case anyone else has the same problem.
std::vector<cv::KeyPoint> testPoints;
cv::FileStorage fs2("keypointsVW.yml", cv::FileStorage::READ);
cv::FileNode kptFileNode = fs2["keypointsVW"];
read(kptFileNode, testPoints);
fs2.release();

OpenCV saving image, keypoints and descriptors to file

I'm using SURF/FLANN detector and I'm looking to save the image, points, descriptors to a file so I can then compare this image and it's points to a second image and points however I'm getting the following error when I try to write:
In file included from detectFlannPoints.cpp:4:0:
/usr/local/include/opencv2/features2d/features2d.hpp:112:17: note: void cv::write(cv::FileStorage&, const string&, const std::vector<cv::KeyPoint>&)
/usr/local/include/opencv2/features2d/features2d.hpp:112:17: note: candidate expects 3 arguments, 4 provided
This is the code I'm using to write:
FileStorage fs("Keypoints.yml", FileStorage::WRITE);
write(fs, "templateImageOne", keypoints_1, tempDescriptors_1);
fs.release();
I'm not sure where I can specify the extra argument (tempDescriptors_1) as it works fine with this arg removed.
Code immediatly above the write code:
//Detect the keypoints using SURF Detector
int minHessian = 400;
SurfFeatureDetector detector( minHessian );
std::vector<KeyPoint> keypoints_1;
detector.detect( img_1, keypoints_1 );
//-- Step 2: Calculate descriptors (feature vectors)
SurfDescriptorExtractor extractor;
Mat tempDescriptors_1;
extractor.compute( img_1, keypoints_1, tempDescriptors_1 );
//-- Draw keypoints
Mat img_keypoints_1;
drawKeypoints( img_1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
you have to write them one at a time:
FileStorage fs("Keypoints.yml", FileStorage::WRITE);
write(fs, "keypoints_1", keypoints_1);
write(fs, "descriptors_1", tempDescriptors_1);
...
fs.release();

OpenCV Matcher - std::bad_alloc exception

I'm trying to stitch together some images to make a sort of panorama. I'm using OpenCV so first thing to do is detect keypoints and descriptors than matching them. To do that I'm following this tutorial: http://opencv.itseez.com/doc/user_guide/ug_features2d.html
But during debug I get a std::bad_alloc exception relative to this line:
matcher.match(descriptors1, descriptors2, matches);
Somebody can help me with that? Because I cutted & pasted the tutorial and there are no compilation errors.
Thanks.
G
Complete code:
Mat img1 = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
Mat img2 = imread(argv[2], CV_LOAD_IMAGE_GRAYSCALE);
if(img1.empty() || img2.empty())
{
printf("Can't read one of the images\n");
return -1;
}
// detecting keypoints
SurfFeatureDetector detector(400);
vector<KeyPoint> keypoints1, keypoints2;
detector.detect(img1, keypoints1);
detector.detect(img2, keypoints2);
// computing descriptors
SurfDescriptorExtractor extractor;
Mat descriptors1, descriptors2;
extractor.compute(img1, keypoints1, descriptors1);
extractor.compute(img2, keypoints2, descriptors2);
// matching descriptors
BruteForceMatcher<L2<float> > matcher;
vector<DMatch> matches;
matcher.match(descriptors1, descriptors2, matches);
// drawing the results
namedWindow("matches", 1);
Mat img_matches;
drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches);
imshow("matches", img_matches);
waitKey(0);
Update:
if I run this code, I get a:
Run-Time Check Failure #2 - Stack around the variable 'keypoints1' was corrupted.
Code:
#include "opencv\cv.h"
#include "opencv\highgui.h"
using namespace cv;
using namespace std;
int main()
{
Mat img1 = imread("Chessboard1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
Mat img2 = imread("Chessboard3.jpg", CV_LOAD_IMAGE_GRAYSCALE);
if(img1.empty() || img2.empty())
{
printf("Can't read one of the images\n");
return -1;
}
FastFeatureDetector detector(50);
vector<KeyPoint> keypoints1;
detector.detect(img1, keypoints1);
return 0;
}
You need ensure that the following "Additional Dependencies" under the the Properties->Linker->Input are referring to the correct OpenCV libraries with debugger support.
i.e.
C:\OpenCV2.2\lib\opencv_calib3d220d.lib
C:\OpenCV2.2\lib\opencv_core220d.lib
C:\OpenCV2.2\lib\opencv_features2d220d.lib
C:\OpenCV2.2\lib\opencv_highgui220d.lib
C:\OpenCV2.2\lib\opencv_imgproc220d.lib
instead of
C:\OpenCV2.2\lib\opencv_calib3d220.lib
C:\OpenCV2.2\lib\opencv_core220.lib
C:\OpenCV2.2\lib\opencv_features2d220.lib
C:\OpenCV2.2\lib\opencv_highgui220.lib
C:\OpenCV2.2\lib\opencv_imgproc220.lib