OpenCV: Eigenfaces with CSV file - c++

I'm struggling with this issue for quite some time now and maybe someone here might have a suggestion of what's going wrong. I'm trying to use the libfacerec to implement Eigenfaces in OpenCV from this site: https://github.com/bytefish/libfacerec I'm using OpenCV-2.3.1 with Visual Studio 2010
The sample code usess the orl_faces dataset from this site: http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html and loads these images by using a csv file. In this file all paths to all 400 images (10 images of 40 different people) are listed and a label is attached to each persons. Both entries are seperated by a " ; ". I've added a few lines of this csv file below:
C:/Users/PIMMES/Documents/libraries/orl_faces/s1/1.pgm;0
C:/Users/PIMMES/Documents/libraries/orl_faces/s1/2.pgm;0
...
C:/Users/PIMMES/Documents/libraries/orl_faces/s2/1.pgm;1
C:/Users/PIMMES/Documents/libraries/orl_faces/s2/2.pgm;1
...
etc
I've added the piece of code below which should load the image data. This is exactly the same piece of code as listed in the main.cpp file in the /src folder from the libfacerec website:
void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';')
{
std::ifstream file(filename.c_str(), ifstream::in);
if (!file) throw std::exception();
string line, path, classlabel;
while (getline(file, line))
{
stringstream liness(line);
getline(liness, path, separator);
getline(liness, classlabel);
images.push_back(imread(path, 0));
labels.push_back(atoi(classlabel.c_str()));
}
}
int main(int argc, const char *argv[])
{
// check for command line arguments
if(argc != 2)
{
cout << "usage: " << argv[0] << " <csv.ext>" << endl;
exit(1);
}
// path to your CSV
string fn_csv = string(argv[1]);
// images and corresponding labels
vector<Mat> images;
vector<int> labels;
// read in the data
try
{
read_csv(fn_csv, images, labels);
}
catch (exception& e)
{
cerr << "Error opening file \"" << fn_csv << "\"." << endl;
exit(1);
}
// get width and height
int width = images[0].cols;
int height = images[0].rows;
// get test instances
Mat testSample = images[images.size() - 1];
int testLabel = labels[labels.size() - 1];
...
etc.
}
The whole project builds fine without any errors, but when I try to run a crash occurs. I went into Debug mode and figured that both vector< Mat > images and vector< int > labels (don't mind the spaces cause without them it doesn't display properly here) are still 0 which means no data is loaded. However when I print the variables height and width it show 140 for both (all images from orl_faces are 140x140 pixels)
So my question, what is going wrong? Why aren't both vectors filled while height and width are filled?
Edit: It seems that both vectors are filled correctly on my other pc (vector images [400], vector labels [400]. However the program still crashes and when running Debug I find this error:
Unhandled exception at 0x77c415de in Test.exe: 0xC0000005: Access violation writing location 0x00000000.
It is located in the mat.hpp file and when stepping through this file, a vector v shows these errors:
[size] CXX0030: Error: expression cannot be evaluated
[capacity CXX0030: Error: expression cannot be evaluated

I am pretty sure the problem is this.
You are linking against the libraries:
opencv_core231.lib
opencv_highgui231.lib
opencv_imgproc231.lib
And then you build with the Debug Configuration in Visual Studio. See the problem? If you want to do this switch to the opencv_core231d.lib libraries. BUT: The OpenCV2.3.1 superpack for some mysterious reasons doesn't come with the tbb_debug.dll, so the Debug build is going to fail. If you are using the superpack and want to use libfacerec, then activate the Release Build Configuration in Visual Studio, build & run and everything is going to work just fine.
I've written a tutorial on it, which should be easy to follow: http://www.bytefish.de/blog/opencv_visual_studio_and_libfacerec. Scroll to the very bottom to see the Eigenfaces in Windows. So you see, it actually works.

Related

Magick++ and Qt - Unable to open image reads directory as random gibberish

I was working on a small project for understanding Qt.
But Magick+ is creating a weird error.
"Read" function of the "Image" can't work with strings.
When I tried to printf/cout the exception, I realized It just reads the filename as random gibberish like this:
"Unable to open image '~—': Invalid argument # error/blob.c/OpenBlob/3537"
When I call it multiple times -even though the strings are different- it gives the same gibberish every time in a session. But when I restart the program, it changes.
I replaced it with a small, hardcoded filename ("image.jpg"); it doesn't work. Same error.
The code:
void ConvertImage(string filedir, string newext, QString destPath, string fileName)
{
Image image;
try
{
replace(filedir.begin(),filedir.end(),'/','\\');
cout << filedir << endl; // Debug print
image.read(filedir);
newext.insert(0,".");
image.write(QstToStd(destPath).append(fileName).append(newext));
}
catch( Exception &error_ )
{
cout << error_.what() << endl; // Debug print
}
}
The repo:
https://github.com/edgarbarney/BatchImageConverter

OpenCV Creating Video From Text File

I am trying to build an application, which get data from webcam or external device, saves Video Frames into text file, then read frames from created text file.
I don't know whether it is a good idea to save to text file, I'm open suggestions.
So far I've done to saving to a text file.
My problem is reading from text file. Basically I read text line by line, but I don't know how to convert this text into Mat object.
So far my code is:
ifstream read_storage(new_vid_frm_path);
if(!read_storage.is_open()) {
perror("\n\n\n\t\t\t(-)FAIL : Can't Open SavedVideoFrames.txt\n\n\n\t\t\t");
return -1;
}
VideoWriter *vid = new VideoWriter(new_vid_frm_path,CV_FOURCC('P', 'I', 'M', '1'),30,Size(vc.get(CV_CAP_PROP_FRAME_WIDTH),vc.get(CV_CAP_PROP_FRAME_HEIGHT)));
Mat line;
vector<Mat> vid_frms;
while ( getline (read_storage,line) ) {
cout << line << '\n';
}
read_storage.close();
if(vid_frms.size() == 0){
printf("\n\n\n\t\t\t(-)FAIL: Error In Frame\n\n\n\t\t\t");
return -1;
}
for(size_t i = 0; i<vid_frms.size(); i++)
(*vid).write(vid_frms[i]);
printf("\n\n\n\t\t\t(+)SUCCESS: Video Processing Complete \n\n\n\t\t\t ");
Do you have ay suggestions how can I cast or convert this line string to Mat obejct?
while ( getline (read_storage,line) ) {
cout << line << '\n';
}
Thanks.
By the way, I looked at this solution, but I couldn't understand.
Convert a string of bytes to cv::mat
I couldn't find the byte type in c++ and I think there might be a direct conversion between String to Mat object.
You can save anything (just about) in OpenCV to a .xml or .yml text file and then read it back in using the OpenCV XML/YAML FileStorage methods.
I highly recomend this over using native C++ methods for file stuff.
It's specifically designed to handle all this legwork for you.

Train_hog.cpp OpenCV 3.1 Example - Cannot pass the proper path parameters

This post describes a very similar problem to mine however I am new here and was told to post a new question. Would very much appreciated anyone's help.
#Franksye I am stuck with the same problem. I am passing the path in this line
{#pd|C:/Cars/|pos_dir}{#p|Pos.lst|pos.lst}{#nd|C:/Cars/|neg_dir} {#n|Neg.lst|neg.lst}");
In the text file Pos.lst I wrote for example image0000.png, image0001.png underneath each other.
However when I run the debugger after build it gives me the below error
The program '[0x3CF0] opencv.exe' has exited with code -1 (0xffffffff).
When creating Brake points i realized that it is exiting on the load_images function when executing file.open((prefix + filename).c_str());
void load_images(const string & prefix, const string & filename, vector< Mat > & img_lst)
{
string line;
ifstream file;
file.open((prefix + filename).c_str());
if (!file.is_open())
{
cerr << "Unable to open the list of images from " << filename << " filename." << endl;
exit(-1);
}
bool end_of_parsing = false;
while (!end_of_parsing)
{
getline(file, line);
if (line.empty()) // no more file to read
{
end_of_parsing = true;
break;
}
Mat img = imread((prefix + line).c_str()); // load the image
if (img.empty()) // invalid image, just skip it.
continue;
#ifdef _DEBUG
imshow("image", img);
waitKey(10);
#endif
img_lst.push_back(img.clone());
}
}
I believe that I am doing something wrong when passing the path of the directory since the load_images function is not able to open the file of the images.
Can someone point me in the right direction or tell me what it is that I am doing wrong please.
Thank you in advance.
Solved it! Such a stupid mistake thanks to Windows.
pos.lst and neg.lst where actually pos.lst.txt and neg.lst.txt because of file extension being hidden. Thanks to This post managed to solve my problem.
Had to switch to Windows because i needed to use Visual Studio will revert back to Ubuntu once this project is over!

ifstream breaks after reading a file 3 times

Im picking up values from a .txt file using ifstream. i am also using windows library to read all files in a folder, that is loop over until the end of folder is reached. In this loop I am reading values from a txt file and adding it to a matrix using push_back.
Here is the section of code under question:
Mat trainme(0, dictionarySize, CV_32FC1);
Mat labels(0, 1, CV_32FC1); //1d matrix with 32fc1 is requirement of normalbayesclassifier class
hTrain = FindFirstFile(full_path, &TrainData);
if (hTrain != INVALID_HANDLE_VALUE)
{
ifstream file("c:\\222\\labels.txt");
string line;
do {
strcpy(loc,DirSpec);
Mat img = imread(strcat(loc,TrainData.cFileName), 0);
cout<<"Processing file: "<<TrainData.cFileName<<endl;
if (!img.data){
cout << "Image data not loaded properly: " <<TrainData.cFileName<< endl;
cin.get();
}
vector<KeyPoint> keypoints;
features->detect(img, keypoints);
if(keypoints.empty()) cout<<"Cannot find keypoints in image: "<<TrainData.cFileName<<endl;
Mat bowDescriptor;
bowDE.compute(img, keypoints, bowDescriptor);
trainme.push_back(bowDescriptor);
getline(file, line);
labels.push_back(line);
strcpy(loc,"");
} while( FindNextFile(hTrain,&TrainData));
}
The problem arises at the line labels.push_back(line); after 3 loops. I mean the file is read 3 times and after that the error: Access violation writing location. And points to this line in memcpy.asm:
mov [edi],al ;U - put byte in destination
I cannot figure out why it fails. I thought it may be a problem transferring string format so I used float value = atof(line) but that gave an error that it cannot convert from string format and it can only take the old c style string.
Here is what is contained in the labels.txt
1
2
2
2
1
2
2
2
Thank you for looking.
Update: I tried moving the file reading out of the main loop and used while(file.good()) But I still get the same error at the same spot. I have no idea why.
string line;
ifstream file("c:\\222\\labels.txt");
if (file.is_open())
{
while (file.good() )
{
getline (file,line);
labels.push_back(line);
}
file.close();
}
Alrighty, I managed to get it solved... =/
The problem was here: labels.push_back(line);
I think adding std::string to Mat using push_back is not possible.
I solved it by converting the string to float using atof.
getline (file,line);
float label = atof(line.c_str());
labels.push_back(label);

Error Using CvMoments to calculate the HU moments

I am doing my FYP and I am a bit new to both OpenCV and C++. I have looked for info regarding CvMoments and all i found (in theory examples that work) do not solve my problem. I want to load a set of images ("1.png" to "5.png") and write the HU moments into a text file. The code is as shows:
CvMoments moments;
CvHuMoments hu_moments;
char filename[80] = "";
ofstream myfile;
myfile.open ("HU_moments.txt");
for (int i=0;i<5;i++){
sprintf(filename,"%u.png",i);
IplImage* image = cvLoadImage(filename);
cvMoments(image,&moments);
cvGetHuMoments(&moments, &hu_moments);
myfile << "Hu1: " << hu_moments.hu1 <<
"Hu2: " << hu_moments.hu2 <<
"Hu3: " << hu_moments.hu3 <<
"Hu4: " << hu_moments.hu4 <<
"Hu5: " << hu_moments.hu5 <<
"Hu6: " << hu_moments.hu6 <<
"Hu7: " << hu_moments.hu7 << ".\n";
cvReleaseImage(&image);
}
myfile.close();
The problem occurs when i get to cvMoments(image,&moments). I get:
Unhandled exception at 0x759fb9bc in Viewer.exe: Microsoft C++ exception: cv::Exception at memory location 0x002fce00..
I have tried declaring moments as a pointer (with its corresponding melloc) but still i get the same error. The funny thing is if i click the option to continue debugging (5 times, one for each loop) i will get results that are printed into my text file. i am using visual studio 2008.
I hope someone knows what is going on here and how to solve.
You are calling it right, but I suspect that your problem is that the previous call is failing:
IplImage* image = cvLoadImage(filename);
You need to check the result of cvLoadImage() and make sure that you are passing a valid argument to cvMoments():
IplImage* image = cvLoadImage(filename);
if (!image)
{
cout << "cvLoadImage() failed!" << endl;
// deal with error! return, exit or whatever
}
cvMoments(image, &moments);
It's also a good idea to check if myfile was successfully opened.
The root of the problem, according to my crystal ball, is a misconception of where you should put the files that the application needs to load when its executed from Visual Studio, and that would be the directory where your source code files are.
If you put the image files on the same directory as the source code, you should be OK.
On the other hand, when you execute your application manually (by double clicking the executable), the image files need to be in the same directory as the executable.
EDIT:
I'm convinced that cvMoments() takes a single-channel image as input. This example doesn't throw any exceptions:
CvMoments moments;
CvHuMoments hu_moments;
IplImage* image = cvLoadImage(argv[1]);
if (!image)
{
std::cout << "Failed cvLoadImage\n";
return -1;
}
IplImage* gray = cvCreateImage(cvSize(image->width, image->height), image->depth, 1);
if (!gray)
{
std::cout << "Failed cvCreateImage\n";
return -1;
}
cvCvtColor(image, gray, CV_RGB2GRAY);
cvMoments(gray, &moments, 0);
cvGetHuMoments(&moments, &hu_moments);
cvReleaseImage(&image);
cvReleaseImage(&gray);
Before converting the colored image to gray, I was getting:
OpenCV Error: Bad argument (Invalid image type) in cvMoments, file OpenCV-2.3.0/modules/imgproc/src/moments.cpp, line 373
terminate called after throwing an instance of 'cv::Exception'
OpenCV-2.3.0/modules/imgproc/src/moments.cpp:373: error: (-5) Invalid image type in function cvMoments