Segmentation fault in OpenCV MWE - c++

I want to get a minimal working example of OpenCV's FABMAP implementation. In order to get there I copied code from this file. I use a different OpenCV version than the provider of the sample code (in my case it is 2.4.8) and had to change the original line
Ptr<DescriptorExtractor> extractor =
new SurfDescriptorExtractor(1000, 4, 2, false, true);
to
Ptr<DescriptorExtractor> extractor =
DescriptorExtractor::create("SURF");
Unfortunately, now I get a segmentation fault that I cannot resolve (I commented the line). Furthermore, I discovered that extractor is a nullpointer whereas matcher is not. Could it be that the nullpointer extractor is causing trouble? How can I resolve this situation?
I'm using Ubuntu 14.04 and g++ for compilation (c++11).
To reproduce this, you would have to download this directory. My minimal (almost) working example:
#include "opencv2/opencv.hpp"
#include "opencv2/features2d/features2d.hpp"
using namespace cv;
using namespace std;
int main(int argc, char * argv[]) {
string dataDir = "fabmap_data/";
FileStorage fs;
//load/generate vocabulary
fs.open(dataDir + string("vocab_small.yml"), FileStorage::READ);
Mat vocab;
fs["Vocabulary"] >> vocab;
fs.release();
//generate test data
Ptr<FeatureDetector> detector =
new DynamicAdaptedFeatureDetector(
AdjusterAdapter::create("STAR"), 130, 150, 5);
Ptr<DescriptorExtractor> extractor =
DescriptorExtractor::create("SURF"); // extractor seems to be a nullpointer (addres:: 0x0)
Ptr<DescriptorMatcher> matcher =
DescriptorMatcher::create("FlannBased");
BOWImgDescriptorExtractor bide(extractor, matcher);
bide.setVocabulary(vocab);
string imageName = "stlucia_test_small0000.jpeg";
Mat frame;
Mat bow;
vector<KeyPoint> kpts;
frame = imread(dataDir + imageName);
detector->detect(frame, kpts);
bide.compute(frame, kpts, bow); // I get a segmentation fault at this line!
return 0;
}

This is a bug, affecting versions from 2.4.4 to 2.4.9: http://code.opencv.org/issues/2280

Related

Problems while trying to extract features using SIFT in opencv 4.5.1

I am trying to extract features of an image using SIFT in opencv 4.5.1, but when I try to check the result by using drawKeypoints() I keep getting this cryptic error:
OpenCV(4.5.1) Error: Assertion failed (!fixedType() || ((Mat*)obj)->type() == mtype) in cv::debug_build_guard::_OutputArray::create, file C:\build\master_winpack-build-win64-vc14\opencv\modules\core\src\matrix_wrap.cpp, line 1147
D:\School\IP2\OpenCVApplication-VS2019_OCV451_basic\x64\Debug\OpenCVApplication.exe (process 6140) exited with code -1.
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
The problem seems to be with the drawKeypoints() function but I'm not sure what causes the problem.
The function:
vector<KeyPoint> extractFeatures(String path) {
Mat_<uchar> source = imread(path, 0);
Mat_<uchar> output(source.rows, source.cols);
vector<KeyPoint> keypoints;
Ptr<SIFT> sift = SIFT::create();
sift->detect(source, keypoints);
drawKeypoints(source, keypoints, output);
imshow("sift_result", output);
return keypoints;
}
You are getting a exception because output argument of drawKeypoints must be 3 channels colored image, and you are initializing output to 1 channel (grayscale) image.
When using: Mat output(source.rows, source.cols); or Mat output;, the drawKeypoints function creates a new colored matrix automatically.
When using the derived template matrix class Mat_<uchar>, the function drawKeypoints raises an exception!
You may replace: Mat_<uchar> output(source.rows, source.cols); with:
Mat_<Vec3b> output(source.rows, source.cols); //Create 3 color channels image (matrix).
Note:
You may also use Mat instead of Mat_:
Mat output; //The matrix is going to be dynamically allocated inside drawKeypoints function.
Note:
My current OpenCV version (4.2.0) has no SIFT support, so I used ORB instead (for testing).
Here is the code sample used for testing:
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;
int main()
{
Mat_<uchar> source = imread("graf.png", 0);
Mat_<Vec3b> output(source.rows, source.cols); //Create 3 color channels image (matrix).
vector<KeyPoint> keypoints;
Ptr<ORB> orb = ORB::create();
orb->detect(source, keypoints);
drawKeypoints(source, keypoints, output);
imshow("orb_result", output);
waitKey(0);
destroyAllWindows();
return 0;
}
Result:

OpenCV 3.0 Segmentation Fault (Bag of visual words)

I am trying to set up a bag of visual words using openCV 3.0. I have looked a bit everywhere and all I seem to be able to find is code that is only compatible with versions in the 2.x domain. As of now this is what I have:
#include <opencv2/core/core.hpp>
#include "opencv2/highgui/highgui.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
int main(int argc, const char** argv) {
Ptr<FeatureDetector> features;
Ptr<DescriptorExtractor> descriptors;
Ptr<DescriptorMatcher> matcher;
int MAX_ITER = 100;
int EPS = 2;
TermCriteria tc(MAX_ITER + EPS,1,0.001);
int dictSize = 1000;
int retries = 1;
int flags = KMEANS_PP_CENTERS;
BOWKMeansTrainer bowTrainer(dictSize,tc,retries,flags);
BOWImgDescriptorExtractor bowDE(descriptors,matcher);
Mat img1 = imread("/Users/Lucas/Desktop/pic2.jpg");
Mat img2 = imread("/Users/Lucas/Desktop/2.jpg");
vector<KeyPoint> keypoints,keypoints2;
features->detect(img1, keypoints);
features->detect(img2, keypoints2);
Mat myFeatures;
Mat myFeatures2;
descriptors->compute(img1, keypoints, myFeatures);
descriptors->compute(img2, keypoints2, myFeatures2);
bowTrainer.add(myFeatures);
bowTrainer.add(myFeatures2);
Mat dictionary = bowTrainer.cluster();
bowDE.setVocabulary(dictionary);
cout << dictionary << endl;
return 0;
}
I have put this together by using a few tutorials and snippets, but I am running into an issue. When the program gets to
features->detect(img1, keypoints);
it exits with a segmentation fault 11, whatever that means. Could someone help me and point out what it is I am doing wrong?
you have to create your FeatureDetector, DescriptorExtractor first. atm, you got null-pointer instances (that's your segfault).
#include <opencv2/xfeatures2d.hpp>
...
Ptr<FeatureDetector> features = xfeatures2d::SIFT::create();
Ptr<DescriptorExtractor> descriptors = xfeatures2d::SIFT::create();
Ptr<DescriptorMatcher> matcher = makePtr<BFMatcher>(NORM_L2);
note, that since you have to use SIFT or SURF, you will need the opencv_contrib repo installed for this

OpenCV: Why SIFT and SURF detectors crashes?

Why do the SIFT and SURF detectors crash?
using namespace std;
using namespace cv;
int main(int argc, char *argv[])
{
Mat image = imread("TestImage.jpg");
// Create smart pointer for SIFT feature detector.
Ptr<FeatureDetector> featureDetector = FeatureDetector::create("SIFT");
vector<KeyPoint> keypoints;
// Detect the keypoints
featureDetector->detect(image, keypoints); // here crash
// ...
}
The error is Segmentation fault (core dumped). I use OpenCV 2.4.8, gcc 4.9 and Ubuntu. If I use the other types of features it runs normally. What am I missing?
Have you tried to call initModule_nonfree()?
#include <opencv2/nonfree/nonfree.hpp>
using namespace std;
using namespace cv;
int main(int argc, char *argv[])
{
initModule_nonfree();
Mat image = imread("TestImage.jpg");
// Create smart pointer for SIFT feature detector.
Ptr<FeatureDetector> featureDetector = FeatureDetector::create("SIFT");
vector<KeyPoint> keypoints;
// Detect the keypoints
featureDetector->detect(image, keypoints); // here crash
// ...
}
Also, you didnt check the pointer featureDetector which is probably null (since you have not called initModule).

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.

watershed segmentation opencv xcode

I am now learning a code from the opencv codebook (OpenCV 2 Computer Vision Application Programming Cookbook): Chapter 5, Segmenting images using watersheds, page 131.
Here is my main code:
#include "opencv2/opencv.hpp"
#include <string>
using namespace cv;
using namespace std;
class WatershedSegmenter {
private:
cv::Mat markers;
public:
void setMarkers(const cv::Mat& markerImage){
markerImage.convertTo(markers, CV_32S);
}
cv::Mat process(const cv::Mat &image){
cv::watershed(image,markers);
return markers;
}
};
int main ()
{
cv::Mat image = cv::imread("/Users/yaozhongsong/Pictures/IMG_1648.JPG");
// Eliminate noise and smaller objects
cv::Mat fg;
cv::erode(binary,fg,cv::Mat(),cv::Point(-1,-1),6);
// Identify image pixels without objects
cv::Mat bg;
cv::dilate(binary,bg,cv::Mat(),cv::Point(-1,-1),6);
cv::threshold(bg,bg,1,128,cv::THRESH_BINARY_INV);
// Create markers image
cv::Mat markers(binary.size(),CV_8U,cv::Scalar(0));
markers= fg+bg;
// Create watershed segmentation object
WatershedSegmenter segmenter;
// Set markers and process
segmenter.setMarkers(markers);
segmenter.process(image);
imshow("a",image);
std::cout<<".";
cv::waitKey(0);
}
However, it doesn't work. How could I initialize a binary image? And how could I make this segmentation code work?
I am not very clear about this part of the book.
Thanks in advance!
There's a couple of things that should be mentioned about your code:
Watershed expects the input and the output image to have the same size;
You probably want to get rid of the const parameters in the methods;
Notice that the result of watershed is actually markers and not image as your code suggests; About that, you need to grab the return of process()!
This is your code, with the fixes above:
// Usage: ./app input.jpg
#include "opencv2/opencv.hpp"
#include <string>
using namespace cv;
using namespace std;
class WatershedSegmenter{
private:
cv::Mat markers;
public:
void setMarkers(cv::Mat& markerImage)
{
markerImage.convertTo(markers, CV_32S);
}
cv::Mat process(cv::Mat &image)
{
cv::watershed(image, markers);
markers.convertTo(markers,CV_8U);
return markers;
}
};
int main(int argc, char* argv[])
{
cv::Mat image = cv::imread(argv[1]);
cv::Mat binary;// = cv::imread(argv[2], 0);
cv::cvtColor(image, binary, CV_BGR2GRAY);
cv::threshold(binary, binary, 100, 255, THRESH_BINARY);
imshow("originalimage", image);
imshow("originalbinary", binary);
// Eliminate noise and smaller objects
cv::Mat fg;
cv::erode(binary,fg,cv::Mat(),cv::Point(-1,-1),2);
imshow("fg", fg);
// Identify image pixels without objects
cv::Mat bg;
cv::dilate(binary,bg,cv::Mat(),cv::Point(-1,-1),3);
cv::threshold(bg,bg,1, 128,cv::THRESH_BINARY_INV);
imshow("bg", bg);
// Create markers image
cv::Mat markers(binary.size(),CV_8U,cv::Scalar(0));
markers= fg+bg;
imshow("markers", markers);
// Create watershed segmentation object
WatershedSegmenter segmenter;
segmenter.setMarkers(markers);
cv::Mat result = segmenter.process(image);
result.convertTo(result,CV_8U);
imshow("final_result", result);
cv::waitKey(0);
return 0;
}
I took the liberty of using Abid's input image for testing and this is what I got:
Below is the simplified version of your code, and it works fine for me. Check it out :
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int main ()
{
Mat image = imread("sofwatershed.jpg");
Mat binary = imread("sofwsthresh.png",0);
// Eliminate noise and smaller objects
Mat fg;
erode(binary,fg,Mat(),Point(-1,-1),2);
// Identify image pixels without objects
Mat bg;
dilate(binary,bg,Mat(),Point(-1,-1),3);
threshold(bg,bg,1,128,THRESH_BINARY_INV);
// Create markers image
Mat markers(binary.size(),CV_8U,Scalar(0));
markers= fg+bg;
markers.convertTo(markers, CV_32S);
watershed(image,markers);
markers.convertTo(markers,CV_8U);
imshow("a",markers);
waitKey(0);
}
Below is my input image :
Below is my output image :
See the code explanation here : Simple watershed Sample in OpenCV
I had the same problem as you, following the exact same code sample of the cookbook (great book btw).
Just to place the matter I was coding under Visual Studio 2013 and OpenCV 2.4.8. After a lot of searching and no solutions I decided to change the IDE.
It's still Visual Studio BUT it's 2010!!!! And boom it works!
Becareful of how you configure Visual Studio with OpenCV. Here's a great tutorial for installation here
Good day to all