2

I am trying to read the parameters of a trained Expectation Maximation model from an XML file for later use. In order to store the model I call

cv::FileStorage fs("model.xml",cv::FileStorage::WRITE);
classifier.write(fs);  //classifier is of type cv::EM

this creates the file containing what looks like the data of the model. Here is what the files looks like (first few lines from the start):

StatModel.EM 1
<_ type_id="opencv-matrix"> 3 3 d
1.2159868951764311e+01 0. 0. 0. 1.9776824566023249e-01 0. 0. 0.  .2204460492503131e-16     
<_ type_id="opencv-matrix"> 3 3 d
3.2869203526862529e+00 0. 0. 0. 1.1631692248472096e+00 0. 0. 0. 2.2204460492503131e-16     
<_ type_id="opencv-matrix"> 3 3 d
2.9815870012055705e+00 0. 0. 0. 6.5049770685681069e+03 0. 0. 0. 6.8510191786605528e+03 
<_ type_id="opencv-matrix"> 3 3 d 
4.6608996548002040e+00 0. 0. 0. 3.7558131457318683e+02 0. 0. 0. 2.2204460492503131e-16 

Note, that the XML header is missing. Now in order to read the data I am using

cv::FileStorage fs("model.xml",cv::FileStorage::READ);

the cv::Algorithm::read() function has to be called with a filenode as parameter. I am not sure what node to use. Since I would expect there to be only one node in the file I tried

classifier.read(fs[0]);

But the algorithm is not trained afterwards. What do I need to do in order to restore the original parameters?

Herr von Wurst
  • 2,571
  • 5
  • 32
  • 53

3 Answers3

4

I simply use

        const FileStorage fs(filename, FileStorage::READ);
        EM model;
        if (fs.isOpened()) {
            const FileNode& fn = fs["StatModel.EM"];
            model.read(fn);
        } 

It works.

wl2776
  • 4,099
  • 4
  • 35
  • 77
  • Thank you. I don't have time to validate this at the moment though. – Herr von Wurst Nov 27 '12 at 08:36
  • It works indeed, but it is interesting to note that fs["StatModel.EM"] returns a null FileNode(pointing to 0x0), so you could actually put any string there. Moreover, it does not work if you get the filenode using fs.getFirstTopLevelNode() as I would have expected – remi Jan 31 '14 at 10:30
3

Instead, of using 'write' you can do:

fs<<"my_model"<<classifier;

and then after you open a FileStorage for reading, read it like that:

cv::EM EModel;
fs["my_model"] >> EModel;

EDIT: The above will not work with cv::EM since it is not included in the overloads.

This link provides a very good example about how you write and read a custom class to/from an XML/YAML file. According to that, you create the "write" and "read" methods for your class, so you are the one who defines and names the nodes.

If you haven't written those methods yourself and they are part of cv::Algorithm (probably this is new, I couldn't find it in 2.2 that I am using) , then I would suggest to check the xml file to see the names of the nodes that were created and then get them either using the >> operator or doing:

FileNode myFilenode = fs["node_name"];
classifier.read(myFilenode);

From the StatModel.EM 1 <_ type_id="opencv-matrix"> that you provide and the xml example in the link, I would guess that this node's name is actually "_" (maybe this is the default if you don't provide any name when you write it)

Sassa
  • 3,294
  • 2
  • 28
  • 42
  • That gives me a compiler error: `no matching function for call to ‘write(cv::FileStorage&, std::string&, const cv::EM&)’` – Herr von Wurst Sep 06 '12 at 19:33
  • 1
    You are right, I just checked and the overloads don't cover EM. You implement "write" yourself, right? – Sassa Sep 06 '12 at 20:09
  • No, I called the write function of the `cv::EM` classifier object after I had trained it. So do I understand this correctly: The `cv::Algorithm::write()` function get's called, since there is no implementation specific to EM? – Herr von Wurst Sep 06 '12 at 20:55
  • I haven't used it myself and I could not find more info about cv::Algorithm, but this is my understanding too. You could probably subclass cv::EM and write them the way you want, however it seems to me that there should be a simpler solution. Are you aware if this write() accepts any other arguments? Also, could you post that xml file or is it too large? – Sassa Sep 06 '12 at 21:48
  • Your help is greatly appreciated! I edited the question in order to show the XML file. The docu states, that the EM model is described by read only parameters. I am clueless how to restore them from a file, since they are read only. – Herr von Wurst Sep 07 '12 at 08:52
  • 1
    I am just making guesses now, but I am really curious about this thing. Some things to try: 1. The missing headers seems a little strange. Try writing a dummy Mat with the << operator before writing the model and check if the headers are ok. 2. Are [those](http://docs.opencv.org/modules/ml/doc/expectation_maximization.html#em-get-em-set) parameters mentioned anywhere later in the XML file? They seem like legit node names. Try using FileNode myFilenode = fs["nclusters"]; classifier.read(myFilenode); for example (well, doesn't hurt to try!). Let me know how it goes – Sassa Sep 07 '12 at 15:38
  • I didn't find the time yet to look into this any further. If there's an update I'll let you know. For now I'll accpect your answer for the "this will not work" part. ;) – Herr von Wurst Sep 17 '12 at 09:22
1

an alternative syntax is

    FileStorage fs(filename, FileStorage::READ);
    Mat mat;
    if (fs.isOpened()) {
        fs["mat_name"]>>mat;
    }
    fs.release();
Vlad
  • 4,425
  • 1
  • 30
  • 39