How can I read from an XML-string in OpenCV? - c++

I know how to load/save a cv::Mat instance into a XML-file (See this question).
But what I really need, is to parse a std::string (or char *) that contains the XML, and get the cv::Mat. Say I get the XML out of a database, and not from a file.
Is that possible?

You can do it since OpenCV 2.4.1.
Here is a code sample from release notes:
//==== storing data ====
FileStorage fs(".xml", FileStorage::WRITE + FileStorage::MEMORY);
fs << "date" << date_string << "mymatrix" << mymatrix;
string buf = fs.releaseAndGetString();
//==== reading it back ====
FileStorage fs(buf, FileStorage::READ + FileStorage::MEMORY);
fs["date"] >> date_string;
fs["mymatrix"] >> mymatrix;

Related

C++ OpenCV Read string instead of loadFromCSV

I am using OPENCV 3.0.0 and C++.
I need to read a csv type string instead of reading a csv file.
In the sample code , it uses
Ptr<TrainData> data = TrainData::loadFromCSV(filename, 0, response_idx, response_idx+1, typespec);
How could I read a csv type string like this
string str1 = " 0,31,29,82,1,0,0,0,2,normal " ;
then can use it to TrainData ?
Thanks!!

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.

Write cv::Mat to binary files? [duplicate]

This question already has answers here:
How to write a Float Mat to a file in OpenCV
(6 answers)
Closed 7 years ago.
I am using openCV and I have a 95,1 mat object of type CV_32F, which I would like to write to a binary file. I am using the code below however I cannot cast a 32F to an char type. Are there any suggestions? I also want to perform the reverse procedure of reading a binary file and storing the values into a mat object of the same type.
try{
ofstream posBinary;
posBinary.open("C:/Users/Dr.Mollica/Documents/TSR Datasets/signDatabasePublicFramesOnly/posSamps.bin", ios::out | ios::binary);
posBinary.write((char *)featureVector, sizeof(featureVector);
}
catch (exception X){ cout << "Error! Could not write Binary file" << endl; }
Also to note, the reason I want to do it in a binary file is I will be writing a large number of these vectors to the file which will be read in to a machine learning algorithm. And from my understanding reading and writing to a binary file is the fastest way possible.
I recommend you to use OpenCV APIs to write cv::Mat to xml or yml files, which you can later read the cv::Mat back from them easily.
For example:
cv::Mat yourMatData;
// write Mat to file
cv::FileStorage fs("file.yml", cv::FileStorage::WRITE);
fs << "yourMat" << yourMatData;
// read Mat from file
cv::FileStorage fs2("file.yml", FileStorage::READ);
fs2["yourMat"] >> yourMatData;
Updated: If you prefer to write/read them to/from binary files, you can first convert cv::Mat to array/vector. And then write the array/vector to files.
To read on, check out Convert Mat to Array/Vector in OpenCV.

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.

Save/Read Matrix from OpenCV FileNodeIterator

I am having trouble saving and reading a cv::Mat saved into a cv::FileNode through which I am iterating. I can write the matrix to a file using
// Data to save
std::vector<cv::Mat> masks;
masks.push_back(cv::Mat::ones(3,3,CV_8UC1));
masks.push_back(cv::Mat::zeros(2,2,CV_8UC1));
// Open file for writing
cv::FileStorage fs(file, cv::FileStorage::WRITE);
// Create node
fs << "data" << "[";
for (size_t i=0; i<masks.size(); ++i)
{
// Fill each node with data
fs << "{:";
// Write other data...
fs << "mask" << masks.at(i);
fs << "}";
}
fs << "]";
Writing a file in this way causes no problems. However, subsequently opening this file causes an unhandled exception which prints:
Reading OpenCV Error: Parsing error (testPR.yml(7): Missing , between
the elemen ts) in unknown function, file
......\modules\core\src\persistence.cpp, line 12 63
To read the matrix I attempt to do this:
// Open file for reading
cv::FileStorage fs(file, cv::FileStorage::READ); ///< This causes an exception
// Open node
cv::FileNode d = fs["data"];
cv::FileNodeIterator it = d.begin(), it_end = d.end();
for( ; it!= it_end; ++it)
{
// Read other data...
cv::Mat mask;
(*it)["mask"] >> mask;
}
Surely it's possible to save/read a matrix to a node in this manner, isn't it?
It turns out that the solution to this was to save the data in an .xml rather than a .yml file, although I am none the wiser as to why that might be.
When I look at http://docs.opencv.org/modules/core/doc/xml_yaml_persistence.html
In YAML (but not XML), mappings and sequences can be written in a compact Python-like inline form. In the sample above matrix elements, as well as each feature, including its lbp value, is stored in such inline form. To store a mapping/sequence in a compact form, put ”:” after the opening character, e.g. use “{:” instead of “{“ and “[:” instead of “[“. When the data is written to XML, those extra ”:” are ignored.
Maybe {: can't be used without [:, but I couldn't find another documentation on this features. But regarding to your solution to store it in XML: The extra ":" is ignored...
From my opinion, storing to YAML should also work when deleting the ":".