I am using OpenCV 4.4.0 on Ubuntu 20.04 with the installed latest opencv_contrib extra modules. For detecting the face landmarks (based on this tutorial) I use the following #include and namespace sections related to the extra face module :
#include <opencv2/face.hpp>
using namespace cv::face;
The face.hpp file is detected (therefore I assume correct installation of the opencv_contrib modules), but e.g. the line
Ptr<facemark> facemark = FacemarkLBF::create();
throws an error
error: ‘facemark’ was not declared in this scope
I have already tried installing the extra modules with both cmake-gui and with the cmake terminal command. The results are the same. I assume there is an error related to the namespace cv::face. Any ideas on what kind of mistake I am doing here?
The minimal code is here:
#include <opencv2/opencv.hpp>
#include <opencv2/face.hpp>
#include "drawLandmarks.hpp"
using namespace std;
using namespace cv;
using namespace cv::face;
int main(int argc,char** argv)
{
// Load Face Detector
CascadeClassifier faceDetector("haarcascade_frontalface_alt2.xml");
// Create an instance of Facemark
Ptr<facemark> facemark = FacemarkLBF::create();
// Load landmark detector
facemark->loadModel("lbfmodel.yaml");
// Set up webcam for video capture
VideoCapture cam(0);
// Variable to store a video frame and its grayscale
Mat frame, gray;
// Read a frame
while(cam.read(frame))
{
// Find face
vector<rect> faces;
// Convert frame to grayscale because
// faceDetector requires grayscale image.
cvtColor(frame, gray, COLOR_BGR2GRAY);
// Detect faces
faceDetector.detectMultiScale(gray, faces);
// Variable for landmarks.
// Landmarks for one face is a vector of points
// There can be more than one face in the image. Hence, we
// use a vector of vector of points.
vector< vector<point2f> > landmarks;
// Run landmark detector
bool success = facemark->fit(frame,faces,landmarks);
if(success)
{
// If successful, render the landmarks on the face
for(int i = 0; i < landmarks.size(); i++)
{
drawLandmarks(frame, landmarks[i]);
}
}
// Display results
imshow("Facial Landmark Detection", frame);
// Exit loop if ESC is pressed
if (waitKey(1) == 27) break;
}
return 0;
}
As #john and #idclev 463035818 have suggested, the way for creating an instance of Facemark is
Ptr<FacemarkLBF> facemark = FacemarkLBF::create();
e.g. if I want to call it facemark.
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
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
I wrote a simple program in OpenCV that detects SURF feature in a given image and diplays the detected features in a namedWindow.
#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\features2d\features2d.hpp>
using namespace cv;
int main(int argc,char** argv)
{
if(argc!=3)//Check cmd number of argumets
{
std::cout<<"Usage: "<<argv[0]<<" <image-file> <method>"<<std::endl;
return -1;
}
//LOAD THE SOURCE IMAGE
Mat Img = imread(argv[1],CV_LOAD_IMAGE_GRAYSCALE);
if(!Img.data)//Check correct image load
{
std::cout<<"Cannot read image file. Check file path!"<<std::endl;
return -1;
}
//COMPUTE FEATURES
SurfFeatureDetector detector;
std::vector<KeyPoint> features;
detector.detect(Img,features);
//SHOW RESULT
Mat ImgF;
drawKeypoints(Img,features,ImgF);
namedWindow("Features", CV_GUI_NORMAL);
imshow("Features",ImgF);
waitKey();
return 0;
}
Everything is OK, the programs do what it have to do. The problem is when pressing a key to terminate the program a crash error occurs.
It doesn't crash for me... but in order for me to compile your code, I had to add
#include <opencv2/nonfree/features2d.hpp>
because SURF was moved to the nonfree module at some point.
So, I would have to recommend trying the newest version (2.4.6 as of today).
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