opencv program crash after matching descriptors - c++

I'm using SIFT descriptor and FLANN matcher to get the minimum distance of the matches between two pictures. The first picture is a query picture and the second picture is from the dataset. I want to load the second picture one by one using a loop, but right after the first iteration, the program crashes at runtime after displaying the result of the first iteration and fails to enter the second iteration. I'm using opencv 2.4.13 and vs2017. Below is my code:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/nonfree/features2d.hpp"
#include <opencv2/legacy/legacy.hpp>
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
using namespace cv;
#define IMAGE_folder "D:\\Project\\dataset1" // change to your folder location
int main()
{
initModule_nonfree();
const int filename_len = 900;
char tempname1[filename_len];
sprintf_s(tempname1, filename_len, "%s\\%s", IMAGE_folder, "995.jpg");
Mat i1 = imread(tempname1);
Mat img1, img2;
cvtColor(i1, img1, COLOR_BGR2GRAY);
if (!i1.data)
{
printf("Cannot find the input image!\n");
system("pause");
return -1;
}
std::vector<KeyPoint> key_points1, key_points2;
Mat descriptors1, descriptors2;
SIFT sift;
sift(img1, Mat(), key_points1, descriptors1);
for (int i = 990; i < 1000; i++)
{
initModule_nonfree();
cout << i << endl;
char tempname2[filename_len];
sprintf_s(tempname2, filename_len, "%s\\%d.jpg", IMAGE_folder, i);
Mat i2 = imread(tempname2);
if (!i2.data)
{
printf("Cannot find the input image!\n");
system("pause");
return -1;
}
cvtColor(i2, img2, COLOR_BGR2GRAY);
sift(img2, Mat(), key_points2, descriptors2);
FlannBasedMatcher matcher;
vector<DMatch> matches;
matches.clear();
matcher.match(descriptors1, descriptors2, matches); //if I comment this line and the code below to show the distance, it can work
double max_dist = 0;
double min_dist = 100;
for (int j = 0; j < descriptors1.rows; j++)
{
double dist = matches[j].distance;
if (dist < min_dist)
min_dist = dist;
if (dist > max_dist)
max_dist = dist;
}
//matcher.clear(); //I've tried these four but still cannot help
//matches.clear();
//key_points1.clear();
//key_points2.clear();
printf("-- Max dist : %f \n", max_dist);
printf("-- Min dist : %f \n", min_dist);
cout << "Done!" << endl;
}
//waitKey(0);
return 0;
}
I've tried a lot and here are my problems and observation:
It is not because I use iterations. If I only run the matcher.match(descriptors1, descriptors2, matches); , it will also crash after execution.
It is also not working for SURF descriptor or BruteForceMatcher, both have the same problem with the code above. I've used different pieces of code from opencv tutorial using SURF, and it still crashes after displaying the result. Example code from opencv tutorial see here
I've also tried initModule_nonfree(); as some answers said, but still didn't help.
The program crashes after displaying "Done!" and not entering the next iteration.
If I delete the matcher.match(descriptors1, descriptors2, matches); and the relevant code below, it can work properly. So the problem must be with the "match" function.
Thanks a lot in advance!
-----------------------------updated-----------------------------
My includes and linked libraries are shown below:
C:\Program Files (x86)\opencv\build\include
C:\Program Files (x86)\opencv\build\include\opencv
C:\Program Files (x86)\opencv\build\include\opencv2
C:\Program Files (x86)\opencv\build\x64\vc12\staticlib
C:\Program Files (x86)\opencv\build\x64\vc12\lib
opencv_objdetect2413.lib
opencv_ts2413.lib
opencv_video2413.lib
opencv_nonfree2413.lib
opencv_ocl2413.lib
opencv_photo2413.lib
opencv_stitching2413.lib
opencv_superres2413.lib
opencv_videostab2413.lib
opencv_calib3d2413.lib
opencv_contrib2413.lib
opencv_core2413.lib
opencv_features2d2413.lib
opencv_flann2413.lib
opencv_gpu2413.lib
opencv_highgui2413.lib
opencv_imgproc2413.lib
opencv_legacy2413.lib
opencv_ml2413.lib
I think the configuration may not have problems... I use it in release mode under x86, thanks!

I've found out the problem. The code works for opencv2.4.13 and vs2012 instead of vs2017. Maybe it's just because opencv2.4.13 is not compatible with vs2017.

Related

OpenCV Detecting Multiple, Rotated, Scaled objects

I've only been using OpenCV for 12 hours or so and haven't been able to solve this problem. The end goal is to take an image and store each character as an entry inside of 6 separate vector2 arrays (5 chars + bubbles)
Additionally, I need to know whether a character is "enlarged" or not.
Link to resources: https://imgur.com/a/lT5HA
As you can tell at any given moment there's a ton of stuff going on, making this a somewhat difficult task. I know that it's possible, though - Robotmon identifies each character with almost 100% accuracy - the only downfall is that the "enlarged" characters get identified 3 times (the distance when discarding duplicates just doesn't work on the big ones due to them being large enough to register multiple times).
All characters are tagged with a single color and characters from the same color group won't appear in the same match.
I'm sure I'm making a ton of errors - I'm not finding much useful information on OpenCV for this usecase. A decent amount is trial and error + looking inside of the files.
For instance, I'm sure that if I were to add all of the characters appearing in a screenshot, searched for all of them, and then compared the "scores" I'd be able to rule out a few false identifications (because the character would be accurately claimed).
To restate my question:
How do I identify every character within the images with no false positives (including small characters being "sent" to the score or transparent characters fading away), all characters identified accurately, and with the enlarged characters identified separately? (And using OpenCL perhaps?)
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/core.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <iostream>
#include <stdio.h>
#include <string>
using namespace cv;
using namespace std;
using namespace cv::xfeatures2d;
int MatchFunction();
int main()
{
MatchFunction();
waitKey(0);
return 0;
}
int MatchFunction()
{
Mat Image_Scene = imread("Bubbles.jpg");
Mat image_Object = imread("block_peterpan_s.png");
// Check for invalid input
if (Image_Scene.empty() || image_Object.empty())
{
cout << "Could not open or find the image" << endl;
return 0;
}
// Initiate ORB detector
Ptr<ORB> detector = ORB::create();
//detector->setMaxFeatures(50);
detector->setScaleFactor(1.1);
detector->setNLevels(12);
//detector->setPatchSize(16);
std::vector<KeyPoint> keypoints_object, keypoints_scene;
Mat descriptors_object, descriptors_scene;
// find the keypoints and descriptors with ORB
detector->detect(image_Object, keypoints_object);
detector->detect(Image_Scene, keypoints_scene);
detector->compute(image_Object, keypoints_object, descriptors_object);
detector->compute(Image_Scene, keypoints_scene, descriptors_scene);
//-- Step 3: Matching descriptor vectors with a brute force matcher
//BFMatcher matcher(NORM_HAMMING, true); //BFMatcher matcher(NORM_L2);
//Ptr<BFMatcher> matcher = BFMatcher::create(); //Ptr<ORB> detector = ORB::create();
Ptr<BFMatcher> matcher = BFMatcher::create(NORM_HAMMING, true);
vector<DMatch> matches;
matcher->match(descriptors_object, descriptors_scene, matches);
//matcher.match(descriptors_object, descriptors_scene, matches);
vector<DMatch> good_matches;
//vector<Point2f> featurePoints1;
//vector<Point2f> featurePoints2;
//Sort the matches by adding them 1 by 1 to good_matches
//for (int i = 0; i<int(matches.size()); i++) { //Size is basically length
// good_matches.push_back(matches[i]);
//}
string k = to_string((matches.size()));
cout << k << endl;
//cout << " Usage: ./SURF_FlannMatcher <img1> <img2>" << std::endl;
double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min distances between keypoints
for (int i = 0; i < int(matches.size()); i++)
{
//cout << to_string(i) << endl;
double dist = matches[i].distance;
if (dist < min_dist) min_dist = dist;
if (dist > max_dist) max_dist = dist;
}
//printf("-- Max dist : %f \n", max_dist);
//printf("-- Min dist : %f \n", min_dist);
//-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist,
//-- or a small arbitary value ( 0.02 ) in the event that min_dist is very
//-- small)
//-- PS.- radiusMatch can also be used here.
//std::vector< DMatch > good_matches;
for (int i = 0; i < int(matches.size()); i++)
{
if (matches[i].distance <= max(4 * min_dist, 0.02))
{
good_matches.push_back(matches[i]);
}
}
Mat img_matches;
drawMatches(image_Object, keypoints_object, Image_Scene, keypoints_scene,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
imshow("Good Matches", img_matches);
}
Template matching would be the most naive approach, but you'd have to brute-force the same template at different scales and rotations for each object. If you have the information about the possible number of such scales/rotations in the game, this will narrow down the number of iterations drastically.
The image seems free from noise, distortion or occlusions, so machine learning approach is not really necessary in this case. If you want something more efficient and are familiar with scientific language and implementing algorithms, take a look at this study which uses radial and circular filters to narrow down the number of combinations:
http://pdfs.semanticscholar.org/c965/0f78bf9d18eba3850281841dc7ddd20e8d5e.pdf
The algorithm or more specifically the filters can be parallelized with OpenCL or any other library if needed. On modern machines this shouldn't be necessary as serial implementation works quite fast.
I successfully implemented it some time ago and it works well and is fast enough to solve your problem with near-realtime performance. RGB won't be neccessary. To my best knowledge it is not implemented anywhere as open-source code, but you can also try looking up for scale and rotation invariant template matching and see what comes up.

OpenCV Image Stitching with Image Resolutions greater than 1080 * 1080

I've been working with OpenCV to stitch two images together on a Raspberry Pi and on a Windows OS based PC.
#include <stdio.h>
#include <iostream>
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
int main (int argc, char** argv) {
Mat image_1 = imread (argv[1]);
Mat image_2 = imread (argv[2]);
Mat gray_image_1;
Mat gray_image_2;
cvtColor (image_1, gray_image_1, CV_RGB2GRAY);
cvtColor (image_2, gray_image_2, CV_RGB2GRAY);
// Check if image files can be read
if (!gray_image_1.data) {
std::cout << "Error Reading Image 1" << std::endl;
return 0;
}
if (!gray_image_2.data) {
std::cout << "Error Reading Image 2" << std::endl;
return 0;
}
// Detect the keypoints using SURF Detector
// Based from Anna Huaman's 'Features2D + Homography to find a known object' Tutorial
int minHessian = 50;
SurfFeatureDetector detector (minHessian);
std::vector <KeyPoint> keypoints_object, keypoints_scene;
detector.detect (gray_image_2, keypoints_object);
detector.detect (gray_image_1, keypoints_scene);
// Calculate Feature Vectors (descriptors)
// Based from Anna Huaman's 'Features2D + Homography to find a known object' Tutorial
SurfDescriptorExtractor extractor;
Mat descriptors_object, descriptors_scene;
extractor.compute (gray_image_2, keypoints_object, descriptors_object);
extractor.compute (gray_image_1, keypoints_scene, descriptors_scene);
// Matching descriptor vectors using FLANN matcher
// Based from Anna Huaman's 'Features2D + Homography to find a known object' Tutorial
FlannBasedMatcher matcher;
std::vector <DMatch> matches;
matcher.match (descriptors_object, descriptors_scene, matches);
double max_dist = 0;
double min_dist = 100;
// Quick calculation of max and min distances between keypoints
// Based from Anna Huaman's 'Features2D + Homography to find a known object' Tutorial
for (int i = 0; i < descriptors_object.rows; i++) {
double dist = matches[i].distance;
if (dist < min_dist) {
min_dist = dist;
}
}
// Use matches that have a distance that is less than 3 * min_dist
std::vector <DMatch> good_matches;
for (int i = 0; i < descriptors_object.rows; i++){
if (matches[i].distance < 3 * min_dist) {
good_matches.push_back (matches[i]);
}
}
std::vector <Point2f> obj;
std::vector <Point2f> scene;
for (int i = 0; i < good_matches.size(); i++) {
// Get the keypoints from the good matches
obj.push_back (keypoints_object[good_matches[i].queryIdx].pt);
scene.push_back (keypoints_scene[good_matches[i].trainIdx].pt);
}
// Find the Homography Matrix
Mat H = findHomography (obj, scene, CV_RANSAC);
// Use the Homography Matrix to warp the images
cv::Mat result;
warpPerspective (image_2, result, H, cv::Size (image_2.cols + image_1.cols, image_2.rows));
cv::Mat half (result, cv::Rect (0, 0, image_1.cols, image_1.rows));
image_1.copyTo (half);
// Write image
imwrite("Update.jpg", result);
waitKey (0);
return 0;
}
The two images I use as inputs result in success. But, only when those two images have resolutions of <= 1080 * 1080 pixels.
For 1440 * 1440 and 1944 * 1944 resolutions I found that the findHomography couldn't function because I was no longer getting more than 3 good matches. findHomography needs at least 4 good matches.
I have tried...
cv::resize(the input images) - results in no resolution size images producing enough good matches for the findHomography.
min Hessian increased or decreased - no change
minimum distance increased or decreased - no change
Note: Both images overlap and have the same dimensions.
Does anyone have a solution to this problem? I have spent a few hours researching this issue and only being lead to the conclusion that OpenCV Image Stitching cannot process high resolution images.
Below I'll include two high resolution images for anyone wishing to help.
colour_1_1440
colour_2_1440
I was using OpenCV 2.4.13 and not the new OpenCV 3.1.0.
Based from Martin Matilla's comment:
"are you sure you are not discarding good matches in the distance filter section? if (matches[i].distance < 3 * min_dist)" – Martin Matilla 53 mins ago
The solution did lie at 3 * min_dist. I changed the value '3' to '4' to allow for high resolution images to be processed.
Note: Originally I changed '3' to '30' and found that the 2nd input image was distorted as expected. <- Just to let anyone know :)

use warpAffine of OpenCV to do image registration

I am trying to do an image registration with ORB feature.
I got a problem at using warpAffine. The compiler told that it is not possible to convert parameter '1' from cv::Mat * to cv::InputArray.
Here is my code:
#pragma once
// Standard C++ I/O library.
#include <iostream>
#include <string>
#include <iomanip>
#include <vector>
// OpenCV library.
#include <cv.h>
#include <highgui.h>
// OpenCV feature library.
#include <opencv2/opencv.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <nonfree/features2d.hpp>
// main().
int main(int argv, char ** argc)
{
cv::Mat im_ref, im_cmp;
std::string str_ref, str_cmp;
// Read reference image.
//std::cout<<"Input reference image filename: ";
//std::cin>>str_ref;
std::cout<<"-> Reading images."<<std::endl;
str_ref = "F:\\CPPs\\ImageRegistration\\OpenCVTest\\206.png";
im_ref = cv::imread(str_ref);
cv::imshow("Reference image", im_ref);
// Read testing image.
//std::cout<<"Input testing image filename: ";
//std::cin>>str_cmp;
str_cmp = "F:\\CPPs\\ImageRegistration\\OpenCVTest\\227.png";
im_cmp = cv::imread(str_cmp);
cv::imshow("Testing image", im_cmp);
std::cout<<"Press any key to continue."<<std::endl;
cvWaitKey(0);
// Feature detection.
std::cout<<"-> Feature detection."<<std::endl;
std::vector <cv::KeyPoint> key_ref, key_cmp; // Vectors for features extracted from reference and testing images.
cv::Mat des_ref, des_cmp; // Descriptors for features of 2 images.
cv::ORB orb1; // An ORB object.
orb1(im_ref, cv::Mat(), key_ref, des_ref); // Feature extraction.
orb1(im_cmp, cv::Mat(), key_cmp, des_cmp);
// Show keypoints.
std::cout<<"-> Show keypoints."<<std::endl;
cv::Mat drawkey_ref, drawkey_cmp; // Output image for keypoint drawing.
cv::drawKeypoints(im_ref, key_ref, drawkey_ref); // Generate image for keypoint drawing.
cv::imshow("Keypoints of reference", drawkey_ref);
cv::drawKeypoints(im_cmp, key_cmp, drawkey_cmp);
cv::imshow("Keypoints of test", drawkey_cmp);
cvWaitKey(0);
// Matching.
std::cout<<"-> Matching."<<std::endl;
cv::FlannBasedMatcher matcher1(new cv::flann::LshIndexParams(20,10,2));
std::vector<cv::DMatch> matches1;
matcher1.match(des_ref, des_cmp, matches1); // Match two sets of features.
double max_dist = 0;
double min_dist = 100;
// Find out the minimum and maximum of all distance.
for( int i = 0; i < des_ref.rows; i++ )
{
double dist = matches1[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}
cvWaitKey(0);
// Eliminate relatively bad points.
std::cout<<"-> Bad points elimination"<<std::endl;
std::vector<cv::KeyPoint> kgood_ref, kgood_cmp;
std::vector<cv::DMatch> goodMatch;
for (int i=0; i<matches1.size(); i++)
{
if(matches1[i].distance < 2*min_dist) // Keep points that are less than 2 times of the minimum distance.
{
goodMatch.push_back(matches1[i]);
kgood_ref.push_back(key_ref[i]);
kgood_cmp.push_back(key_cmp[i]);
} // end if
} // end for
cvWaitKey(0);
// Calculate affine transform matrix.
std::cout<<"-> Calculating affine transformation."<<std::endl;
std::vector<cv::Point2f> frm1_feature, frm2_feature;
const int p_size = goodMatch.size();
// * tmpP = new tmpPoint[p_size];
cv::Point2f tmpP;
for(int i=0; i<goodMatch.size(); i++)
{
tmpP.x = kgood_ref[i].pt.x;
tmpP.y = kgood_ref[i].pt.y;
frm1_feature.push_back(tmpP);
tmpP.x = kgood_cmp[i].pt.x;
tmpP.y = kgood_cmp[i].pt.y;
frm2_feature.push_back(tmpP);
}
cv::Mat affine_mat = cv::estimateRigidTransform(frm1_feature, frm2_feature, true);
cv::Mat im_transformed;
// Output results.
cv::warpAffine(&im_cmp, &im_transformed, affine_mat, CV_INTER_LINEAR|CV_WARP_FILL_OUTLIERS); // error comes from here.
cv::imshow("Transformed image", im_transformed);
cvWaitKey(0);
return 0;
}
I have got the result before using the answer given by Evgeniy.
The transform I had used is
//cv::warpAffine( im_cmp, im_transformed, affine_mat, cv::Size(im_cmp.cols, im_cmp.rows) );
The transformed result is quite strange
What I want to do is finally get a merged image of both the reference image and this transformed image. This is actually my first step. Is this the problem of using the transformation parameter of the warpAffine().
Finally, I want to get a result like an example here (two images taken at difference position and they are finally aligned)
You are giving a pointer, but wrapAffine accepts reference to a cv::Mat.
You can change your code like this:
cv::warpAffine(im_cmp, im_transformed, affine_mat, cv::Size(), CV_INTER_LINEAR|CV_WARP_FILL_OUTLIERS);
Just remove '&'

OpenCV C++ 'Access Violation' with SURF

I'm trying using SURF feature detector but I'm always getting this error-
The program '[1120] Corner Detection.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.
Here is the code
#include "stdafx.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/nonfree/features2d.hpp"
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <stdio.h>
#include "opencv2/core/core.hpp"
#include "opencv2\nonfree\nonfree.hpp"
using namespace cv;
using namespace std;
void foo(Mat &image1, Mat &image2)
{
int minHeassian = 400;
SurfFeatureDetector detector(minHeassian);
std::vector< KeyPoint > keypoints1, keypoints2;
keypoints1.resize(1000);
keypoints2.resize(1000);
detector.detect(image1, keypoints1); // <--- crashes at this line
detector.detect(image2, keypoints2); // <--- probably will crash here too
SurfDescriptorExtractor extractor;
Mat discriptors1, discriptors2;
extractor.compute(image1, keypoints1, discriptors1);
extractor.compute(image2, keypoints2, discriptors2);
FlannBasedMatcher matcher;
std::vector< DMatch > matches;
matcher.match(discriptors1, discriptors2, matches);
double minDist = 100;
for (int i = 0; i < matches.size(); ++i)
if (matches[i].distance < minDist)
minDist = matches[i].distance;
std::vector< DMatch > goodMatches;
for (int i = 0; i < matches.size(); ++i)
if (matches[i].distance <= max(0.02, (double)matches[i].distance))
goodMatches.push_back(matches[i]);
Mat matchImage;
drawMatches(image1, keypoints1, image2, keypoints2,
goodMatches, matchImage,
Scalar::all(-1), Scalar::all(-1), vector<char>(),
DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
namedWindow("Matches", WINDOW_AUTOSIZE);
imshow("Matches", matchImage);
waitKey(0);
}
int _tmain(int argc, _TCHAR* argv[])
{
cv::initModule_nonfree();
Mat left, right;
right = imread("D:\\right.jpg", IMREAD_COLOR);
left = imread("D:\\left.jpg", IMREAD_COLOR);
foo(left, right);
return 0;
}
I get the error at the line
detector.detect(image1, keypoints1);
I have following lib files mentioned to linker-
opencv_core249d.lib
opencv_imgproc249d.lib
opencv_highgui249d.lib
opencv_ml249d.lib
opencv_video249d.lib
opencv_features2d249d.lib
opencv_calib3d249d.lib
opencv_objdetect249d.lib
opencv_contrib249d.lib
opencv_legacy249d.lib
opencv_flann249d.lib
opencv_features2d249.lib
opencv_nonfree249.lib
I have tried everything I found on the Internet but nothing worked. What is wrong with this code?
I'm running VS 2013 on Windows 8.1 and I'm using OpenCV version 2.4.9.
Solved
It was a silly mistake. I used the library opencv_nonfree249.lib whereas I should be using opencv_nonfree249**d**.lib as I was working in debug mode.
You are using the library opencv_nonfree249.lib in a debug environment which is meant for release environment. Add a d to the lib name to make it opencv_nonfree249d.lib which will work for debug environment.

OpenCV - C++ Code runs in Eclipse but not in terminal?

I am trying to make the follwing Code by Mohammad Reza Mostajabi (http://alum.sharif.ir/~mostajabi/Tutorial.html) run under Ubuntu 12.04 with OpenCV 2.4.6.1. I made some minor changes with the libraries included and added "cv::initModule_nonfree()" right after starting the main file.
#include "cv.h"
#include "highgui.h"
#include "ml.h"
#include <stdio.h>
#include <iostream>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/nonfree/nonfree.hpp>
#include <vector>
using namespace cv;
using namespace std;
using std::cout;
using std::cerr;
using std::endl;
using std::vector;
char ch[30];
//--------Using SURF as feature extractor and FlannBased for assigning a new point to the nearest one in the dictionary
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased");
Ptr<DescriptorExtractor> extractor = new SurfDescriptorExtractor();
SurfFeatureDetector detector(500);
//---dictionary size=number of cluster's centroids
int dictionarySize = 1500;
TermCriteria tc(CV_TERMCRIT_ITER, 10, 0.001);
int retries = 1;
int flags = KMEANS_PP_CENTERS;
BOWKMeansTrainer bowTrainer(dictionarySize, tc, retries, flags);
BOWImgDescriptorExtractor bowDE(extractor, matcher);
void collectclasscentroids() {
IplImage *img;
int i,j;
for(j=1;j<=4;j++)
for(i=1;i<=60;i++){
sprintf( ch,"%s%d%s%d%s","train/",j," (",i,").jpg");
const char* imageName = ch;
img = cvLoadImage(imageName,0);
vector<KeyPoint> keypoint;
detector.detect(img, keypoint);
Mat features;
extractor->compute(img, keypoint, features);
bowTrainer.add(features);
}
return;
}
int main(int argc, char* argv[])
{
cv::initModule_nonfree();
int i,j;
IplImage *img2;
cout<<"Vector quantization..."<<endl;
collectclasscentroids();
vector<Mat> descriptors = bowTrainer.getDescriptors();
int count=0;
for(vector<Mat>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++)
{
count+=iter->rows;
}
cout<<"Clustering "<<count<<" features"<<endl;
//choosing cluster's centroids as dictionary's words
Mat dictionary = bowTrainer.cluster();
bowDE.setVocabulary(dictionary);
cout<<"extracting histograms in the form of BOW for each image "<<endl;
Mat labels(0, 1, CV_32FC1);
Mat trainingData(0, dictionarySize, CV_32FC1);
int k=0;
vector<KeyPoint> keypoint1;
Mat bowDescriptor1;
//extracting histogram in the form of bow for each image
for(j=1;j<=4;j++)
for(i=1;i<=60;i++){
sprintf( ch,"%s%d%s%d%s","train/",j," (",i,").jpg");
const char* imageName = ch;
img2 = cvLoadImage(imageName,0);
detector.detect(img2, keypoint1);
bowDE.compute(img2, keypoint1, bowDescriptor1);
trainingData.push_back(bowDescriptor1);
labels.push_back((float) j);
}
//Setting up SVM parameters
CvSVMParams params;
params.kernel_type=CvSVM::RBF;
params.svm_type=CvSVM::C_SVC;
params.gamma=0.50625000000000009;
params.C=312.50000000000000;
params.term_crit=cvTermCriteria(CV_TERMCRIT_ITER,100,0.000001);
CvSVM svm;
printf("%s\n","Training SVM classifier");
bool res=svm.train(trainingData,labels,cv::Mat(),cv::Mat(),params);
cout<<"Processing evaluation data..."<<endl;
Mat groundTruth(0, 1, CV_32FC1);
Mat evalData(0, dictionarySize, CV_32FC1);
k=0;
vector<KeyPoint> keypoint2;
Mat bowDescriptor2;
Mat results(0, 1, CV_32FC1);;
for(j=1;j<=4;j++)
for(i=1;i<=60;i++){
sprintf( ch,"%s%d%s%d%s","eval/",j," (",i,").jpg");
const char* imageName = ch;
img2 = cvLoadImage(imageName,0);
detector.detect(img2, keypoint2);
bowDE.compute(img2, keypoint2, bowDescriptor2);
evalData.push_back(bowDescriptor2);
groundTruth.push_back((float) j);
float response = svm.predict(bowDescriptor2);
results.push_back(response);
}
//calculate the number of unmatched classes
double errorRate = (double) countNonZero(groundTruth- results) / evalData.rows;
printf("%s%f","Error rate is ",errorRate);
return 0;
}
After doing this I can compile the Code without problems. I can also run it within Eclipse, but once I try to make it work in terminal I get the following error message:
" OpenCV Error: Assertion failed (!_descriptors.empty()) in add, file /home/mark/Downloads/FP/opencv-2.4.6.1/modules/features2d/src/bagofwords.cpp, line 57
terminate called after throwing an instance of 'cv::Exception'
what(): /home/mark/Downloads/FP/opencv-2.4.6.1/modules/features2d/src/bagofwords.cpp:57: error: (-215) !_descriptors.empty() in function add "
I've been trying to solve the problem for a few days now, but I just cannot get rid of this error. I also tried to do it with CodeBlocks, which gives me the same error. I would appreciate some help very much!
Thanks!
It's possible that your program fails to load input images (when launched from the terminal window) because it can't find them. Make sure that your input images are copied to the directory from which you run the application. Eclipse may have a different home directory and hence it sees the image when the program is started in Eclipse.