ifstream breaks after reading a file 3 times - c++

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

Related

Make sense of PGM data and load PGM data into vector/array

Let me preface this by saying this is my first time working with the PGM file format in C++, so I have multiple questions.
I'm currently using P2 PGM files, but I read that P5 is much simpler to work with. How can I convert a P2 to a P5?
With the P2, I am trying to take the image and transfer the pixel values to a 2D vector or array or anything remotely index-able. I'm using a very basic image (white background with a black rectangle in the foreground). Here's my code so far:
fstream img;
img.open(PATH_NAME, ios::in | ios::binary | ios::out);
string line;
getline(img, line); //header part that says "P2"
//stores column and row values
getline(img, line);
istringstream iss(line);
string row_string, col_string;
iss >> row_string;
iss >> col_string;
int original_rows = stoi(row_string);
int original_cols = stoi(col_string);
getline(img, line);//collects maxval
//now I am collecting actual image/pixel data
getline(img, line);
cout << line;
The problem with that last part is that when I cout << line; , this is the output:
\377\377\377\377\377\377\377\377\377\377\377\377\
and on and on and on for much longer than a single line should be (there are 162 columns in my sample photo and this code outputs much more than 162 377s). The maxval is 255, so I'm not really sure what the problem is.
As for actually transferring these values into something indexable, how do I go about that? So far, my idea is to take each string line, detect for '\' and collect the individual values that way and store it in an array; convert each string to int and then store it in a vector. Might be easier said than done, so I am open to more efficient options.
The problem is that you are confusing text I/O with binary I/O. As I understand the image data in a P5 file is held as binary byte values. Therefore you should be reading it into a byte vector (or similar) using read, instead of reading it using getline which is for text I/O.
Like this
vector<unsigned char> raster(original_rows*original_cols);
img.read(raster.data(), original_rows*original_cols);
raster is your something indexable.

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.

Vector mat in txt

I ve got a vector Mat file and I want to store it in txt file. Every mat file has size 1x4500 and I ve got in total 5000 vectors. I tried to store in txtfile with the above code:
void writeMatToFile(cv::Mat& m, const char* filename){
ofstream fout(filename);
for(int i=0; i<m.rows; i++){
for(int j=0; j<m.cols; j++){
fout<<m.at<float>(i,j)<<"\t";
}
fout<<endl;
}
fout.close();
}
In main:
string file = "output.txt";
writeMatToFile(image,file.c_str());
However, I got unhandled exception errors.
Write your data in binary mode using your own format. Something like : mat_count|shape1|data1(row_first)|shape2...
std::fstream will do the harder job for you in text mode or binary mode. You should try both to see the final size.
If your Mat data is something like uint8, uint16, the binary mode will be much better. The problem with text-mode is that you need a separator for each single data which add additional bytes to your file. However text-mode can compress data : "1.5" 3 vs 8 bytes (double).
Last thing, if you want absolutely a file in text-mode, you can zip it at the end of your process and see the ratio.

How to use "PASCAL Annotation" files to train SVM with C++

I need to test my selfwritten person detector using Hog Descriptor (Dalal paper) on a Scientific dataset (INRIA person dataset). I have thousands of pos and neg Images in my Folder to train a Support Vector Machine (SVM). However to label the Images as positive (1.0) or negative (-1.0) I need to read the information from a text file that is provided with the dataset in a so called "PASCAL Annotation" format.
My problem is that I don't know how to read this format efficiently. I'm using C++ and OpenCV. Does anyone know how to do this efficiently? Are there already code snippets for C++?
In the end I need a loop that goes through a file "Annotations.lst" where all the picture filenames are listed. The program loads the picture and the corresponding annotation file (picturename.txt) to see if this picture belongs to a positive or negative training data (or later when actually detecting: if the tested picture belongs to a detected person or not)
Thanks for your help!
Maybe it's not the best implementation but works fine, hope it becomes useful even today! You will need filesystem library in order to work with files.
string line,value; //Line stores lines of the file and value stores characters of the line
int i=0; //Iterate through lines
int j=0; //Iterate through characters
int n=0; //Iterate through ,()-...
char v; //Stores variable value as a char to be able to make comparisions easily
vector <Rect> anotations; //Stores rectangles for each image
vector <int> bbValues; //Bounding box values (xmin,ymin,xmax,ymax)
fs::path anotationsFolder = "THE FOLDER PATH OF ANOTATIONS"; //Path of anotations folder
fs::path anotationsParsedFolder = "THE FOLDER PATH TO STORE PARSED ANOTATIONS"; //Path to store new anotations
fs::recursive_directory_iterator it(anotationsFolder); //Iteradores of files
fs::recursive_directory_iterator endit;
cout<<"Loading anotations from "<<anotationsFolder<<endl;
while((it != endit)) //Until end of folder
{
if((fs::is_regular_file(*it))) //Good practice
{
fs::path imagePath(it->path()); //Complete path of the image
cout<<"Reading anotations from"<<it->path().filename()<<endl;
ifstream inputFile; //Declare input file with image path
inputFile.open(imagePath.string().data(), std::ios_base::in);
i=0;
while (! inputFile.eof() ){ //Until end of file
getline (inputFile,line);//Get lines one by one
if ((i>=17) && ((i-17)%7==0)){ //In lines numer 17,24,31,38...where bounding boxes coordinates are
j=69;
v=line[j]; //Start from character num 69 corresponding to first value of Xmin
while (j<line.size()){ //Until end of line
if (v=='(' || v==',' || v==')' || v==' ' || v=='-'){ //if true, push back acumulated value unless previous value wasn't a symbol also
if (n==0){
bbValues.push_back(stoi(value)); //stoi converts string in to integer ("567"->567)
value.clear();
}
n++;
}
else{
value+=v; //Append new number
n=0;//Reset in order to know that a number has been read
}
j++;
v=line[j];//Read next character
}
Rect rect(bbValues[0],bbValues[1],bbValues[2]-bbValues[0],bbValues[3]-bbValues[1]); //Build a rectangle rect(xmin,ymin,xmax-xmin,ymax-ymin)
anotations.push_back(rect);
bbValues.clear();
}
i++;//Next line
}
inputFile.close();
cout<<"Writing..."<<endl;
//Save the anotations to a file
ofstream outputFile; //Declare file
fs::path outputPath(anotationsParsedFolder / it->path().filename());// Complete path of the file
outputFile.open(outputPath.string().data(), ios_base::trunc);
// Store anotations as x y width heigth
for (int i=0; i<anotations.size(); i++){
outputFile<<anotations[i].x<<" ";
outputFile<<anotations[i].y<<" ";
outputFile<<anotations[i].width<<" ";
outputFile<<anotations[i].height<<endl;
}
anotations.clear();
outputFile.close();
}
++it;//Next file in anotations folder
}

OpenCV: Eigenfaces with CSV file

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.