diff --git a/doc/opencv1refman_c.pdf b/doc/opencv1refman_c.pdf index 2e132c8204..19bcd2bb88 100644 Binary files a/doc/opencv1refman_c.pdf and b/doc/opencv1refman_c.pdf differ diff --git a/doc/opencv1refman_py.pdf b/doc/opencv1refman_py.pdf index 2214cbf95f..83bef668b3 100644 Binary files a/doc/opencv1refman_py.pdf and b/doc/opencv1refman_py.pdf differ diff --git a/doc/opencv2refman_cpp.pdf b/doc/opencv2refman_cpp.pdf index 29858ca375..ccf5f28743 100644 Binary files a/doc/opencv2refman_cpp.pdf and b/doc/opencv2refman_cpp.pdf differ diff --git a/doc/opencv2refman_py.pdf b/doc/opencv2refman_py.pdf index c53198cd65..67efa5c53a 100644 Binary files a/doc/opencv2refman_py.pdf and b/doc/opencv2refman_py.pdf differ diff --git a/doc/opencv_tutorials.pdf b/doc/opencv_tutorials.pdf index 34c4490e71..34f5a0a1a6 100644 Binary files a/doc/opencv_tutorials.pdf and b/doc/opencv_tutorials.pdf differ diff --git a/doc/opencv_user.pdf b/doc/opencv_user.pdf index 362ba66d23..0a1aff299d 100644 Binary files a/doc/opencv_user.pdf and b/doc/opencv_user.pdf differ diff --git a/modules/core/doc/xml_yaml_persistence.rst b/modules/core/doc/xml_yaml_persistence.rst index ce73a664db..e08a0277f8 100644 --- a/modules/core/doc/xml_yaml_persistence.rst +++ b/modules/core/doc/xml_yaml_persistence.rst @@ -3,149 +3,164 @@ XML/YAML Persistence .. highlight:: cpp -.. index:: FileStorage +XML/YAML file storages. Writing to a file storage. +-------------------------------------------------- + +You can store and then restore various OpenCV data structures to/from XML (http://www.w3c.org/XML) or YAML +(http://www.yaml.org) formats. Also, it is possible store and load arbitrarily complex data structures, which include OpenCV data structures, as well as primitive data types (integer and floating-point numbers and text strings) as their elements. + +Use the following procedure to write something to XML or YAML: + #. Create new :ocv:class:`FileStorage` and open it for writing. It can be done with a single call to :ocv:func:`FileStorage::FileStorage` constructor that takes a filename, or you can use the default constructor and then call :ocv:class:`FileStorage::open`. Format of the file (XML or YAML) is determined from the filename extension (".xml" and ".yml"/".yaml", respectively) + #. Write all the data you want using the streaming operator ``>>``, just like in the case of STL streams. + #. Close the file using :ocv:func:`FileStorage::release`. ``FileStorage`` destructor also closes the file. + +Here is an example: :: + + #include "opencv2/opencv.hpp" + #include + + using namespace cv; + + int main(int, char** argv) + { + FileStorage fs("test.yml", FileStorage::WRITE); + + fs << "frameCount" << 5; + time_t rawtime; time(&rawtime); + fs << "calibrationDate" << asctime(localtime(&rawtime)); + Mat cameraMatrix = (Mat_(3,3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1); + Mat distCoeffs = (Mat_(5,1) << 0.1, 0.01, -0.001, 0, 0); + fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs; + fs << "features" << "["; + for( int i = 0; i < 3; i++ ) + { + int x = rand() % 640; + int y = rand() % 480; + uchar lbp = rand() % 256; + + fs << "{:" << "x" << x << "y" << y << "lbp" << "[:"; + for( int j = 0; j < 8; j++ ) + fs << ((lbp >> j) & 1); + fs << "]" << "}"; + } + fs << "]"; + fs.release(); + return 0; + } + +The sample above stores to XML and integer, text string (calibration date), 2 matrices, and a custom structure "feature", which includes feature coordinates and LBP (local binary pattern) value. Here is output of the sample: + +.. code-block:: yaml + + %YAML:1.0 + frameCount: 5 + calibrationDate: "Fri Jun 17 14:09:29 2011\n" + cameraMatrix: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 1000., 0., 320., 0., 1000., 240., 0., 0., 1. ] + distCoeffs: !!opencv-matrix + rows: 5 + cols: 1 + dt: d + data: [ 1.0000000000000001e-01, 1.0000000000000000e-02, + -1.0000000000000000e-03, 0., 0. ] + features: + - { x:167, y:49, lbp:[ 1, 0, 0, 1, 1, 0, 1, 1 ] } + - { x:298, y:130, lbp:[ 0, 0, 0, 1, 0, 0, 1, 1 ] } + - { x:344, y:158, lbp:[ 1, 1, 0, 0, 0, 0, 1, 0 ] } + +As an exercise, you can replace ".yml" with ".xml" in the sample above and see, how the corresponding XML file will look like. + +Several things can be noted by looking at the sample code and the output: + * + The produced YAML (and XML) consists of heterogeneous collections that can be nested. There are 2 types of collections: named collections (mappings) and unnamed collections (sequences). In mappings each element has a name and is accessed by name. This is similar to structures and ``std::map`` in C/C++ and dictionaries in Python. In sequences elements do not have names, they are accessed by indices. This is similar to arrays and ``std::vector`` in C/C++ and lists, tuples in Python. "Heterogeneous" means that elements of each single collection can have different types. + + Top-level collection in YAML/XML is a mapping. Each matrix is stored as a mapping, and the matrix elements are stored as a sequence. Then, there is a sequence of features, where each feature is represented a mapping, and lbp value in a nested sequence. + + * + When you write to a mapping (a structure), you write element name followed by its value. When you write to a sequence, you simply write the elements one by one. OpenCV data structures (such as cv::Mat) are written in absolutely the same way as simple C data structures - using **``<<``** operator. + + * + To write a mapping, you first write the special string **"{"** to the storage, then write the elements as pairs (``fs << << ``) and then write the closing **"}"**. + + * + To write a sequence, you first write the special string **"["**, then write the elements, then write the closing **"]"**. + + * + 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. + + +Reading data from a file storage. +--------------------------------- + +To read the previously written XML or YAML file, do the following: + + #. + Open the file storage using :ocv:func:`FileStorage::FileStorage` constructor or :ocv:func:`FileStorage::open` method. In the current implementation the whole file is parsed and the whole representation of file storage is built in memory as a hierarchy of file nodes (see :ocv:class:`FileNode`) + + #. + Read the data you are interested in. Use :ocv:func:`FileStorage::operator []`, :ocv:func:`FileNode::operator []` and/or :ocv:class:`FileNodeIterator`. + + #. + Close the storage using :ocv:func:`FileStorage::release`. + +Here is how to read the file created by the code sample above: :: + + FileStorage fs2("test.yml", FileStorage::READ); + + // first method: use (type) operator on FileNode. + int frameCount = (int)fs2["frameCount"]; + + std::string date; + // second method: use FileNode::operator >> + fs2["calibrationDate"] >> date; + + Mat cameraMatrix2, distCoeffs2; + fs2["cameraMatrix"] >> cameraMatrix2; + fs2["distCoeffs"] >> distCoeffs2; + + cout << "frameCount: " << frameCount << endl + << "calibration date: " << date << endl + << "camera matrix: " << cameraMatrix2 << endl + << "distortion coeffs: " << distCoeffs2 << endl; + + FileNode features = fs2["features"]; + FileNodeIterator it = features.begin(), it_end = features.end(); + int idx = 0; + std::vector lbpval; + + // iterate through a sequence using FileNodeIterator + for( ; it != it_end; ++it, idx++ ) + { + cout << "feature #" << idx << ": "; + cout << "x=" << (int)(*it)["x"] << ", y=" << (int)(*it)["y"] << ", lbp: ("; + // you can also easily read numerical arrays using FileNode >> std::vector operator. + (*it)["lbp"] >> lbpval; + for( int i = 0; i < (int)lbpval.size(); i++ ) + cout << " " << (int)lbpval[i]; + cout << ")" << endl; + } + fs.release(); FileStorage ----------- .. ocv:class:: FileStorage -XML/YAML file storage class. :: - - class FileStorage - { - public: - enum { READ=0, WRITE=1, APPEND=2 }; - enum { UNDEFINED=0, VALUE_EXPECTED=1, NAME_EXPECTED=2, INSIDE_MAP=4 }; - // the default constructor - FileStorage(); - // the constructor that opens a file for reading - // (flags=FileStorage::READ) or writing (flags=FileStorage::WRITE) - FileStorage(const string& filename, int flags); - // wraps the already opened CvFileStorage* - FileStorage(CvFileStorage* fs); - // the destructor; closes the file if needed - virtual ~FileStorage(); - - // opens the specified file for reading (flags=FileStorage::READ) - // or writing (flags=FileStorage::WRITE) - virtual bool open(const string& filename, int flags); - // checks if the storage is opened - virtual bool isOpened() const; - // closes the file - virtual void release(); - - // returns the first top-level node - FileNode getFirstTopLevelNode() const; - // returns the root file node - // (it is the parent of the first top-level node) - FileNode root(int streamidx=0) const; - // returns the top-level node by name - FileNode operator[](const string& nodename) const; - FileNode operator[](const char* nodename) const; - - // returns the underlying CvFileStorage* - CvFileStorage* operator *() { return fs; } - const CvFileStorage* operator *() const { return fs; } - - // writes the certain number of elements of the specified format - // (see DataType) without any headers - void writeRaw( const string& fmt, const uchar* vec, size_t len ); - - // writes an old-style object (CvMat, CvMatND, etc.) - void writeObj( const string& name, const void* obj ); - - // returns the default object name from the filename - // (used by cvSave() with the default object name, etc.) - static string getDefaultObjectName(const string& filename); - - Ptr fs; - string elname; - vector structs; - int state; - }; - -.. index:: FileNode +XML/YAML file storage class that incapsulates all the information necessary for writing or reading data to/from file. FileNode -------- .. ocv:class:: FileNode -XML/YAML file node class. :: - - class CV_EXPORTS FileNode - { - public: - enum { NONE=0, INT=1, REAL=2, FLOAT=REAL, STR=3, - STRING=STR, REF=4, SEQ=5, MAP=6, TYPE_MASK=7, - FLOW=8, USER=16, EMPTY=32, NAMED=64 }; - FileNode(); - FileNode(const CvFileStorage* fs, const CvFileNode* node); - FileNode(const FileNode& node); - FileNode operator[](const string& nodename) const; - FileNode operator[](const char* nodename) const; - FileNode operator[](int i) const; - int type() const; - int rawDataSize(const string& fmt) const; - bool empty() const; - bool isNone() const; - bool isSeq() const; - bool isMap() const; - bool isInt() const; - bool isReal() const; - bool isString() const; - bool isNamed() const; - string name() const; - size_t size() const; - operator int() const; - operator float() const; - operator double() const; - operator string() const; - - FileNodeIterator begin() const; - FileNodeIterator end() const; - - void readRaw( const string& fmt, uchar* vec, size_t len ) const; - void* readObj() const; - - // do not use wrapper pointer classes for better efficiency - const CvFileStorage* fs; - const CvFileNode* node; - }; - -.. index:: FileNodeIterator +The class ``FileNode`` represents each element of the file storage, be it a matrix, a matrix element or a top-level node, containing all the file content. That is, a file node may contain either a singe value (integer, floating-point value or a text string), or it can be a sequence of other file nodes, or it can be a mapping. Type of the file node can be determined using :ocv:func:`FileNode::type` method. FileNodeIterator ---------------- .. ocv:class:: FileNodeIterator -XML/YAML file node iterator class. :: +The class ``FileNodeIterator`` is used to iterate through sequences and mappings. A standard STL notation, with ``node.begin()``, ``node.end()`` denoting the beginning and the end of a sequence, stored in ``node``. See the data reading sample in the beginning of the section. - class CV_EXPORTS FileNodeIterator - { - public: - FileNodeIterator(); - FileNodeIterator(const CvFileStorage* fs, - const CvFileNode* node, size_t ofs=0); - FileNodeIterator(const FileNodeIterator& it); - FileNode operator *() const; - FileNode operator ->() const; - - FileNodeIterator& operator ++(); - FileNodeIterator operator ++(int); - FileNodeIterator& operator --(); - FileNodeIterator operator --(int); - FileNodeIterator& operator += (int); - FileNodeIterator& operator -= (int); - - FileNodeIterator& readRaw( const string& fmt, uchar* vec, - size_t maxCount=(size_t)INT_MAX ); - - const CvFileStorage* fs; - const CvFileNode* container; - CvSeqReader reader; - size_t remaining; - }; - -..