【问题标题】:How to read/write a matrix from a persistent XML/YAML file in OpenCV 3 with python?如何使用 python 从 OpenCV 3 中的持久 XML/YAML 文件读取/写入矩阵?
【发布时间】:2017-10-18 19:21:36
【问题描述】:

我一直在尝试使用 anaconda 当前的 cv2(我相信它实际上是 OpenCV 3.x)来读取和写入矩阵到持久文件存储(例如 XML)。我在网上查看了解决方案,人们参考了这样的做法:

object = cv2.cv.Load(file)
object = cv2.cv.Save(file)

source。这不适用于当前的 anaconda python cv2。人们提出像this yaml example 这样的解决方案,但我很困惑为什么这个简单的功能需要这么多样板代码,我不认为这是一个可接受的解决方案。我想要一些与旧解决方案一样简单的东西。

【问题讨论】:

    标签: python xml opencv persistence opencv3.0


    【解决方案1】:

    在我问这个问题之前我就知道如何解决这个问题,但我知道如何解决这个问题的唯一原因是因为我也在学习如何在 C++ 中同时执行此操作。在 opencv 的最新更新中如何做到这一点是not stated at all in the documentation。我无法在网上找到任何解决此问题的方法,所以希望你们中那些不使用 C++ 的人能够毫不费力地理解如何在 python 中做到这一点。

    这个最小的示例应该足以向您展示该过程的工作原理。实际上,当前用于 opencv 的 python 包装器看起来更像 c++ 版本,您现在直接使用 cv2.FileStorage 而不是 cv2.cv.Savecv2.cv.Load

    python cv2.FileStorage 现在是它自己的文件处理程序,就像它在 C++ 中一样。在 c++ 中,如果您想使用 FileStorage 将文件写入,您可以执行以下操作:

    cv::FileStorage opencv_file("test.xml", cv::FileStorage::WRITE);
    cv::Mat file_matrix;
    file_matrix = (cv::Mat_<int>(3, 3) << 1, 2, 3,
                                          3, 4, 6,
                                          7, 8, 9); 
    opencv_file << "my_matrix" << file_matrix
    opencv_file.release();
    

    阅读,您需要执行以下操作:

    cv::FileStorage opencv_file("test.xml", cv::FileStorage::READ);
    cv::Mat file_matrix;
    opencv_file["my_matrix"] >> file_matrix;
    opencv_file.release();
    

    在python中,如果你想写你必须做以下事情

    #notice how its almost exactly the same, imagine cv2 is the namespace for cv 
    #in C++, only difference is FILE_STORGE_WRITE is exposed directly in cv2
    cv_file = cv2.FileStorage("test.xml", cv2.FILE_STORAGE_WRITE)
    #creating a random matrix
    matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    print("write matrix\n", matrix)
    # this corresponds to a key value pair, internally opencv takes your numpy 
    # object and transforms it into a matrix just like you would do with << 
    # in c++
    cv_file.write("my_matrix", matrix)
    # note you *release* you don't close() a FileStorage object
    cv_file.release()
    

    如果你想读取矩阵,那就有点做作了。

    # just like before we specify an enum flag, but this time it is 
    # FILE_STORAGE_READ
    cv_file = cv2.FileStorage("test.xml", cv2.FILE_STORAGE_READ)
    # for some reason __getattr__ doesn't work for FileStorage object in python
    # however in the C++ documentation, getNode, which is also available, 
    # does the same thing
    #note we also have to specify the type to retrieve other wise we only get a 
    # FileNode object back instead of a matrix
    matrix = cv_file.getNode("my_matrix").mat()
    print("read matrix\n", matrix)
    cv_file.release()
    

    读写python示例的输出应该是:

    write matrix
     [[1 2 3]
     [4 5 6]
     [7 8 9]]
    
    read matrix
     [[1 2 3]
     [4 5 6]
     [7 8 9]]
    

    XML 看起来像这样:

    <?xml version="1.0"?>
    <opencv_storage>
    <my_matrix type_id="opencv-matrix">
      <rows>3</rows>
      <cols>3</cols>
      <dt>i</dt>
      <data>
        1 2 3 4 5 6 7 8 9</data></my_matrix>
    </opencv_storage>
    

    【讨论】:

    • 多么精细而全面的详细答案。有用!如果我自己尝试,这将需要大量的试验和错误,这会消耗大量时间。谢谢
    • 请注意,用于读取矩阵的python代码适用于opencv 3.4.2而不是3.4.0
    • 这个答案是在 3.4.0 存在之前创建的,它适用于所有以前的版本。你能告诉我有什么问题吗?我没有看到它如何无法与 3.4 一起使用,并且我无法使用 3.4 进行测试
    • 错误是关于getNode(),是这样的:"cv2.error: /io/opencv/modules/core/src/persistence.cpp:4785: error: (-2) Too complex format for the matrix in function icvDecodeSimpleFormat"。当我切换到 3.4.2 时,该功能运行良好。
    • @ScottYang 很奇怪,这可能是他们后来修复的回归。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多