【问题标题】:How to save CV_32F type CV::Mat to a file without loosing precision?如何在不丢失精度的情况下将 CV_32F 类型 CV::Mat 保存到文件中?
【发布时间】:2019-03-11 14:27:47
【问题描述】:

我正在将 cv::PCA 类用于人脸识别项目。我将人脸照片转换为一行向量,将它们连接到一个大数组并输入到 pca,以获得一个新空间,我可以在其中尝试使用距离进行识别。问题是,每次我启动程序时从头开始计算 pca 真的很耗时(几乎五分钟)。我发现我需要将计算出的 pca 保存到硬盘驱动器,并在我再次启动程序时加载它。这就是问题所在。如我所见,cv::PCA 中的所有 cv::Mat 对象都是 CV_32F 类型。当我尝试将其保存为普通图片时,它转换为 8 位图像,并且丢失了一些数据。当我使用 XML/YAML 持久化时,生成的文件非常大,并且数据也丢失了(我已经保存它,加载到另一个结构并运行 cerr<<sum(pca_orginal.mean==pca_loaded.mean)[0]<<endl 以检查差异有多大)。现在我正在尝试将std::ofstream::write 与std::ofstream::binary 标志和istream::read 一起使用,但存在一些类型问题(out.write(_pca.mean.data,_pca.mean.rows*_pca.mean.cols*4/*CV_32F->4*CV_8U*/\); 生成error: no matching function for call to ‘std::basic_ofstream<char, std::char_traits<char> >::write(uchar*&, int)。我还听说过openexr 库及其文件格式,但我宁愿避免使用额外的库。我使用的是 OpenCV 2.3.1 和 OpenCV 2.2。

编辑: 我很抱歉造成混乱。我误读了cv::Mat operator== 的描述,并认为它的工作方式与它相反,所以sum(pca_orginal.mean==pca_loaded.mean)[0] 给出 0 可能是更糟糕的结果,而不是最好的结果。这意味着除了生成巨大的文件之外,XML/YML 可以正常工作。此外,在使用 c 风格转换后,我能够使二进制流工作,但生成的文件也很大(超过 150MB)。

【问题讨论】:

    标签: opencv


    【解决方案1】:

    在 C 接口中,有函数 cvSave 和 cvLoad 用于保存任意矩阵。可能也有对应的 C++ 接口。

    【讨论】:

    • 感谢答案,但正如我已经写过的,xml 函数会生成相当大的文件(因为像素值被写为文本),并且在使用保存的文件时似乎存在精度损失。
    • 我明白了。请发布您遇到问题的代码。绝对可以将data 数组转储到二进制文件并毫无问题地读回它(只要您不在以不同方式表示浮点数的机器之间移动文件)。
    • 抱歉混淆了,xml 不会降低精度。现在,在使用 c-style cast to (const char*) 之后,我能够编写和读取均值矩阵,所以看起来它可能适用于其他人。现在我只需要检查所有数据在写入硬盘后是否有合理的(小于 100MB)大小)。
    • 您始终可以使用 gzip 压缩(保存文件后)以减少数据中的冗余。压缩的有效性当然取决于数据的熵。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-08
    • 2021-09-29
    • 2020-12-02
    • 1970-01-01
    • 2015-12-22
    • 1970-01-01
    相关资源
    最近更新 更多