OpenCV Matcher - std::bad_alloc exception - c++

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

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);

How to draw detected object with SIFT features on OpenCV 3.1?

Using this code to find matches between images:
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/xfeatures2d/nonfree.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <vector>
using namespace std;
using namespace cv;
int main(int argc, char *argv[]) {
//cv::initModule_nonfree();
//initModule_features2d();
Mat img_1 = imread("C:/Users/Dan/Desktop/0.jpg", 1);
Mat img_2 = imread("C:/Users/Dan/Desktop/0.jpg", 1);
cv::Ptr<Feature2D> f2d = xfeatures2d::SIFT::create();
//-- Step 1: Detect the keypoints:
std::vector<KeyPoint> keypoints_1, keypoints_2;
f2d->detect(img_1, keypoints_1);
f2d->detect(img_2, keypoints_2);
//-- Step 2: Calculate descriptors (feature vectors)
Mat descriptors_1, descriptors_2;
f2d->compute(img_1, keypoints_1, descriptors_1);
f2d->compute(img_2, keypoints_2, descriptors_2);
Mat out0;
drawKeypoints(img_1, keypoints_1, out0);
imshow("KeyPoint0.jpg", out0);
//-- Step 3: Matching descriptor vectors using BFMatcher :
BFMatcher matcher;
std::vector< DMatch > matches;
matcher.match(descriptors_1, descriptors_2, matches);
Mat img_matches = Mat::zeros( img_1.size(), CV_8UC3 );
drawMatches(img_1,keypoints_1,img_2,keypoints_2,matches,img_matches);
imshow("matches", img_matches);
waitKey(0); // Keep window there until user presses 'q' to quit.
return 0;
}
Since OpenCV 3.1 functions were changed, I looked for example code using SURF or SIFT, but could not find any.
How to modify this code so it will draw contours around detected objects similar to OpenCV version?
You will need to use findHomography to get the transformation that relates your training image (img_1) to the image to be detected (img_2)
Then you can simply do a perspectiveTransform on a bounding box of your training image (at origin) using the homography obtained, to place the correct bounding box on the detected image
Related code taken from ORB detection example
Mat inlier_mask, homography;
vector<KeyPoint> inliers1, inliers2;
vector<DMatch> inlier_matches;
if(matched1.size() >= 4) {
homography = findHomography(Points(matched1), Points(matched2),
RANSAC, ransac_thresh, inlier_mask);
}
for(unsigned i = 0; i < matched1.size(); i++) {
if(inlier_mask.at<uchar>(i)) {
int new_i = static_cast<int>(inliers1.size());
inliers1.push_back(matched1[i]);
inliers2.push_back(matched2[i]);
inlier_matches.push_back(DMatch(new_i, new_i, 0));
}
}
stats.inliers = (int)inliers1.size();
stats.ratio = stats.inliers * 1.0 / stats.matches;
vector<Point2f> new_bb;
perspectiveTransform(object_bb, new_bb, homography);
Mat frame_with_bb = frame.clone();
if(stats.inliers >= bb_min_inliers) {
drawBoundingBox(frame_with_bb, new_bb);
}
Mat res;
drawMatches(first_frame, inliers1, frame_with_bb, inliers2,
inlier_matches, res,
Scalar(255, 0, 0), Scalar(255, 0, 0));

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();

bad memory allocation while doing opencv2 bruteforce matcher

I was trying out the codes from the book openCV2 computer vision applications programming cookbook under surf chapter 8 page 226 out of 304 for the brute force matcher but while executing the code I keep getting this message:
Unhandled exception at 0x7530812f in surf matrix.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x002af6b4.."
I tried Googling but could not find an answer to it and I have checked the book's example and still could not find what went wrong. The break point occurs at this statement: matcher.match(descriptors1,descriptors2, matches);
I am using opencv 2.3. I've included
C:\OpenCV2.3\build\include\opencv
C:\OpenCV2.3\build\include\opencv2
C:\OpenCV2.3\build\include
under additional include directories and the libraries:
opencv_core230.lib
opencv_highgui230.lib
opencv_imgproc230.lib
opencv_features2d230.lib
opencv_calib3d230.lib
...and added C:\OpenCV2.3\build\x86\vc9\lib to the additional library directories field
Below is my code:
#include "cv.h"
#include "highgui.h"
int main(int argc, char* argv[]) {
std::vector<cv::KeyPoint> keypoints1, keypoints2;
cv::Mat image1=cv::imread("C:/Users/folder/44.jpg");
cv::Mat image2=cv::imread("C:/Users/folder/44.jpg");
cv::Mat featureImage=cv::imread("C:/Users/folder/44.jpg");
cvNamedWindow("MyJPG", CV_WINDOW_AUTOSIZE);
cv::imshow("MyJPG", image1);
cv::SurfFeatureDetector surf(2500);
surf.detect(image1, keypoints1);
// Draw the keypoints with scale and orientation information
cv::drawKeypoints(image1, // original image
keypoints1, // vector of keypoints
featureImage, // the resulting image
cv::Scalar(255, 255, 255), // color of the points
cv::DrawMatchesFlags::DRAW_OVER_OUTIMG); //flag
cv::imshow("Results", featureImage);
cv::imshow("MyJPG2", image2);
surf.detect(image2, keypoints2);
cv::drawKeypoints(image2, // original image keypoints2, // vector of
keypoints image2, // the resulting image
cv::Scalar(255,255,255), // color of the points
cv::DrawMatchesFlags::DRAW_OVER_OUTIMG); //flag
// Construction of the SURF descriptor extractor
cv::SurfDescriptorExtractor surfDesc1;
cv::SurfDescriptorExtractor surfDesc2; // Extraction of the SURF descriptors
cv::Mat descriptors1, descriptors2;
surfDesc1.compute(image1, keypoints1, descriptors1);
//printf("%s",surfDesc);
surfDesc2.compute(image2, keypoints2, descriptors2);
cvWaitKey(0); // Construction of the matcher
cv::BruteForceMatcher<cv::L2<float>> matcher; // Match the two image descriptors
std::vector<cv::DMatch> matches;
matcher.match(descriptors1, descriptors2, matches);
//cvReleaseImage( &image1 );
cvDestroyWindow("MyJPG");
return 0;
}

OpenCV, feature matching with code from the tutorial

I copied the code of the Feature Matching with FLANN from the OpenCV tutorial page, and made the following changes:
I used the SIFT features, instead of SURF;
I modified the check for a 'good match'. Instead of
if( matches[i].distance < 2*min_dist )
I used
if( matches[i].distance <= 2*min_dist )
otherwise I would get zero good matches when comparing an image with itself.
Modified parameter in drawing the keypoints:
drawMatches( img1, k1, img2, k2,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::DEFAULT);
I extracted the SIFT from all the images in the folder Ireland of the INRIA-Holidays dataset. Then I compared each image to all the others and draw the matches.
However there is a strange problem I have never experienced with any other SIFT/Matcher implementation I used in the past:
the matches for an image I matched against itself are good. Each keypoint is mapped onto itself except for some. See image above.
When I match I against another image J (with J not equal to I), many points are mapped onto the same one. Some examples are below.
Is there anyone who used the same code from the OpenCV tutorial and can report a different experience from mine?
Checkout the matcher_simple.cpp example. It uses a brute force matcher that seems to work pretty well. Here is the code:
// 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
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);