您的位置:首页 > 运维架构

OpenCV保存成XML(FileStorage)和CSV(重载<<运算符)文件

2015-06-29 20:24 351 查看


XML文件(使用FileStorage类)

使用OpenCV时不仅要保存影像结果,往往也需要保存中间的矩阵结果,而OpenCV的imwrite函数只支持CV8U类型的数据(使用OpenCV保存其他类型Mat的时候,程序不会报错,但是无法生成结果文件),因此会给工作带来很多不便。OpenCV在2.0以后的版本中提供了FileStorage类,供用户直接使用,保存为XML/YAML文件。

保存XML

保存示例如下:
<code class="language-c++ hljs lasso has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">Mat mat <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> Mat<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::eye</span>(Size(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12</span>), CV_8UC1);
FileStorage fs(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"f:\\vocabulary.xml"</span>, FileStorage<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::WRITE</span>);
fs <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><<</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"vocabulary"</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><<</span> mat;
fs<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>release();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

得到结果文件如下所示:
<code class="language-xml hljs  has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-pi" style="color: rgb(0, 102, 102); box-sizing: border-box;"><?xml version="1.0"?></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">opencv_storage</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">vocabulary</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">type_id</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"opencv-matrix"</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">rows</span>></span>12<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">rows</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">cols</span>></span>12<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">cols</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">dt</span>></span>u<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">dt</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">data</span>></span>
1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">data</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">vocabulary</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">opencv_storage</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

需要注意的是,因为保存的结果为xml文件,所以再保存的时候需要给定标签,格式就是下面的形式,先存储标签内容,再存储矩阵:
<code class="language-c++ hljs bash has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">fs << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"vocabulary"</span> << mat;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

读取XML

同样使用FileStorage类可以直接获取保存的xml文件内容。

读取示例如下:
<code class="language-c++ hljs scss has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">FileStorage <span class="hljs-function" style="box-sizing: border-box;">fs(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">".\\vocabulary.xml"</span>, FileStorage::READ)</span>;
Mat mat_vocabulary;
fs<span class="hljs-attr_selector" style="color: rgb(0, 136, 0); box-sizing: border-box;">["vocabulary"]</span> >> mat_vocabulary;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

读取文件的时候同样要给定标签内容,这里通过中括号[]给定:
<code class="language-c++ hljs bash has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">fs[<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"vocabulary"</span>] >> mat_vocabulary;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

CSV文件

很多时候,直接使用CSV文件相比XML更方便,使用XML保存得到的数据,无论是查看(excel查看,XML中矩阵不是格式化的)还是接着使用别的工具处理(例如matlab),都可以快速的读取,而XML需要解析则比较繁琐。那么该如何保存CSV文件呢,对保存的CSV文件又应该如何读取呢,请看下文分解。

保存CSV文件

OpenCV提供了结果保存的格式化函数format,使用format我们就可以根据自己想要的格式打印和保存数据了。
先直接看保存函数,再来分析具体含义吧:
<code class="language-c++ hljs mel has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">ofstream <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"test.csv"</span>);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span> << <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">format</span>(mat, Formatter::FMT_CSV);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span>.close();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

根据上面的代码只用ofstream对象打开要写入的csv文件,再直接写入数据即可,需要注意的是,接入的矩阵用format格式化,format函数第二个参数表示格式类型,这里选择CSV格式即Formatter::FMT_CSV。
保存结果如图所示:



这里保存格式为定义在Formatter类中的枚举类型,总共有6中选项,各位读者可以根据自己的需求选择。
<code class="language-c++ hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">class CV_EXPORTS Formatter
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">enum</span> { FMT_DEFAULT = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,
FMT_MATLAB  = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,
FMT_CSV     = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,
FMT_PYTHON  = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>,
FMT_NUMPY   = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>,
FMT_C       = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>
};

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> ~Formatter();

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> Ptr<Formatted> format(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> Mat& mtx) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> set32fPrecision(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> p = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>) = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> set64fPrecision(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> p = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>) = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> setMultiline(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span> ml = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>) = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> Ptr<Formatter> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">get</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> fmt = FMT_DEFAULT);

};
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>

读取CSV数据

在保存为CSV格式后该如何读取呢,这里可以使用OpenCV中ml模块的TrainData类的函数读取。具体代码如下所示,第二行为加载数据,参数0表示没有标题行,第三行获取得到的数据。
<code class="language-c++ hljs lasso has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">Ptr<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><</span>TrainData<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">></span> train_data;
train_data <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> TrainData<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::loadFromCSV</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"test.csv"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
Mat m <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> train_data<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-></span>getTrainSamples();
cout <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><<</span> format(m, Formatter<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::FMT_CSV</span>) <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><<</span> endl;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

代码运行结果为:



参考链接:

1. OpenCV使用FileStorage保存Mat数据

2. XML/YAML file storages. Writing to a file storage.

版权声明:本文为博主原创文章,未经博主允许不得转载。


XML文件(使用FileStorage类)

使用OpenCV时不仅要保存影像结果,往往也需要保存中间的矩阵结果,而OpenCV的imwrite函数只支持CV8U类型的数据(使用OpenCV保存其他类型Mat的时候,程序不会报错,但是无法生成结果文件),因此会给工作带来很多不便。OpenCV在2.0以后的版本中提供了FileStorage类,供用户直接使用,保存为XML/YAML文件。

保存XML

保存示例如下:
<code class="language-c++ hljs lasso has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">Mat mat <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> Mat<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::eye</span>(Size(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12</span>), CV_8UC1);
FileStorage fs(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"f:\\vocabulary.xml"</span>, FileStorage<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::WRITE</span>);
fs <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><<</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"vocabulary"</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><<</span> mat;
fs<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>release();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

得到结果文件如下所示:
<code class="language-xml hljs  has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-pi" style="color: rgb(0, 102, 102); box-sizing: border-box;"><?xml version="1.0"?></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">opencv_storage</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">vocabulary</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">type_id</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"opencv-matrix"</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">rows</span>></span>12<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">rows</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">cols</span>></span>12<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">cols</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">dt</span>></span>u<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">dt</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">data</span>></span>
1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">data</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">vocabulary</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">opencv_storage</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

需要注意的是,因为保存的结果为xml文件,所以再保存的时候需要给定标签,格式就是下面的形式,先存储标签内容,再存储矩阵:
<code class="language-c++ hljs bash has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">fs << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"vocabulary"</span> << mat;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

读取XML

同样使用FileStorage类可以直接获取保存的xml文件内容。

读取示例如下:
<code class="language-c++ hljs scss has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">FileStorage <span class="hljs-function" style="box-sizing: border-box;">fs(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">".\\vocabulary.xml"</span>, FileStorage::READ)</span>;
Mat mat_vocabulary;
fs<span class="hljs-attr_selector" style="color: rgb(0, 136, 0); box-sizing: border-box;">["vocabulary"]</span> >> mat_vocabulary;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

读取文件的时候同样要给定标签内容,这里通过中括号[]给定:
<code class="language-c++ hljs bash has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">fs[<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"vocabulary"</span>] >> mat_vocabulary;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

CSV文件

很多时候,直接使用CSV文件相比XML更方便,使用XML保存得到的数据,无论是查看(excel查看,XML中矩阵不是格式化的)还是接着使用别的工具处理(例如matlab),都可以快速的读取,而XML需要解析则比较繁琐。那么该如何保存CSV文件呢,对保存的CSV文件又应该如何读取呢,请看下文分解。

保存CSV文件

OpenCV提供了结果保存的格式化函数format,使用format我们就可以根据自己想要的格式打印和保存数据了。
先直接看保存函数,再来分析具体含义吧:
<code class="language-c++ hljs mel has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">ofstream <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"test.csv"</span>);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span> << <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">format</span>(mat, Formatter::FMT_CSV);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">file</span>.close();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

根据上面的代码只用ofstream对象打开要写入的csv文件,再直接写入数据即可,需要注意的是,接入的矩阵用format格式化,format函数第二个参数表示格式类型,这里选择CSV格式即Formatter::FMT_CSV。
保存结果如图所示:



这里保存格式为定义在Formatter类中的枚举类型,总共有6中选项,各位读者可以根据自己的需求选择。
<code class="language-c++ hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">class CV_EXPORTS Formatter
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">enum</span> { FMT_DEFAULT = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,
FMT_MATLAB  = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,
FMT_CSV     = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,
FMT_PYTHON  = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>,
FMT_NUMPY   = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>,
FMT_C       = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>
};

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> ~Formatter();

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> Ptr<Formatted> format(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> Mat& mtx) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> set32fPrecision(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> p = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>) = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> set64fPrecision(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> p = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>) = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> setMultiline(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span> ml = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>) = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> Ptr<Formatter> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">get</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> fmt = FMT_DEFAULT);

};
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>

读取CSV数据

在保存为CSV格式后该如何读取呢,这里可以使用OpenCV中ml模块的TrainData类的函数读取。具体代码如下所示,第二行为加载数据,参数0表示没有标题行,第三行获取得到的数据。
<code class="language-c++ hljs lasso has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">Ptr<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><</span>TrainData<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">></span> train_data;
train_data <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> TrainData<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::loadFromCSV</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"test.csv"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
Mat m <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> train_data<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-></span>getTrainSamples();
cout <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><<</span> format(m, Formatter<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::FMT_CSV</span>) <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><<</span> endl;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

代码运行结果为:



参考链接:

1. OpenCV使用FileStorage保存Mat数据

2. XML/YAML file storages. Writing to a file storage.

版权声明:本文为博主原创文章,未经博主允许不得转载。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: