FileStorage for OpenCV Python API

时间:2012-06-21 15:18:00

标签: c++ python image-processing opencv

我目前正在使用 FileStorage 类来使用OpenCV C ++ API存储矩阵 XML / YAML

但是,我必须编写一个读取 XML / YAML 文件的Python脚本。

我正在寻找可以读取 OpenCV C ++ API 生成的 XML / YAML 文件的现有OpenCV Python API

6 个答案:

答案 0 :(得分:22)

您可以使用PyYAML来解析YAML文件。

由于PyYAML不了解OpenCV数据类型,因此需要为要加载的每个OpenCV数据类型指定构造函数。例如:

import yaml
def opencv_matrix(loader, node):
    mapping = loader.construct_mapping(node, deep=True)
    mat = np.array(mapping["data"])
    mat.resize(mapping["rows"], mapping["cols"])
    return mat
yaml.add_constructor(u"tag:yaml.org,2002:opencv-matrix", opencv_matrix)

完成后,加载yaml文件很简单:

with open(file_name) as fin:
    result = yaml.load(fin.read())

结果将是一个字典,其中的键是你在YAML中保存的任何名称。

答案 1 :(得分:9)

除了@ misha的回复之外,OpenCV YAML与Python有些不兼容。

不兼容的几个原因是:

  1. 由OpenCV创建的Yaml在"之后没有空格:"。而Python需要它。 [例如:它应该是a: 2,而不是a:2对于Python]
  2. OpenCV创建的第一行YAML文件错误。转换"%YAML:1.0"到"%YAML 1.0"。或者在阅读时跳过第一行。
  3. 以下功能负责提供:

    import yaml
    import re
    def readYAMLFile(fileName):
        ret = {}
        skip_lines=1    # Skip the first line which says "%YAML:1.0". Or replace it with "%YAML 1.0"
        with open(scoreFileName) as fin:
            for i in range(skip_lines):
                fin.readline()
            yamlFileOut = fin.read()
            myRe = re.compile(r":([^ ])")   # Add space after ":", if it doesn't exist. Python yaml requirement
            yamlFileOut = myRe.sub(r': \1', yamlFileOut)
            ret = yaml.load(yamlFileOut)
        return ret
    
    outDict = readYAMLFile("file.yaml")
    

    注意:以上回复仅适用于yaml' s。 XML有自己的问题,我还没有完全探索过。

答案 2 :(得分:6)

使用OpenCV 3.2中提供的FileStorage功能,我成功​​地使用了它:

 导入cv2
fs = cv2.FileStorage(“calibration.xml”,cv2.FILE_STORAGE_READ)
fn = fs.getNode(“Camera_Matrix”)
print(fn.mat())
 

答案 3 :(得分:4)

我写了一个小片段来读取和编写Python中与FileStorage兼容的YAML:

# A yaml constructor is for loading from a yaml node.
# This is taken from @misha 's answer: http://stackoverflow.com/a/15942429
def opencv_matrix_constructor(loader, node):
    mapping = loader.construct_mapping(node, deep=True)
    mat = np.array(mapping["data"])
    mat.resize(mapping["rows"], mapping["cols"])
    return mat
yaml.add_constructor(u"tag:yaml.org,2002:opencv-matrix", opencv_matrix_constructor)

# A yaml representer is for dumping structs into a yaml node.
# So for an opencv_matrix type (to be compatible with c++'s FileStorage) we save the rows, cols, type and flattened-data
def opencv_matrix_representer(dumper, mat):
    mapping = {'rows': mat.shape[0], 'cols': mat.shape[1], 'dt': 'd', 'data': mat.reshape(-1).tolist()}
    return dumper.represent_mapping(u"tag:yaml.org,2002:opencv-matrix", mapping)
yaml.add_representer(np.ndarray, opencv_matrix_representer)

#examples 

with open('output.yaml', 'w') as f:
    yaml.dump({"a matrix": np.zeros((10,10)), "another_one": np.zeros((2,4))}, f)

with open('output.yaml', 'r') as f:
    print yaml.load(f)

答案 4 :(得分:1)

为了改进@Roy_Shilkrot之前的答案,我添加了对numpy向量和矩阵的支持:

@Html.DropDownListFor(model => model.guests, new List<SelectListItem>()
            {
                new SelectListItem{ Text="0", Value="0"},
                new SelectListItem{ Text="1", Value="1"},
                new SelectListItem{ Text="2", Value="2"}

            }, "")

示例:

# A yaml constructor is for loading from a yaml node.
# This is taken from @misha 's answer: http://stackoverflow.com/a/15942429
def opencv_matrix_constructor(loader, node):
    mapping = loader.construct_mapping(node, deep=True)
    mat = np.array(mapping["data"])
    if mapping["cols"] > 1:
        mat.resize(mapping["rows"], mapping["cols"])
    else:
        mat.resize(mapping["rows"], )
    return mat
yaml.add_constructor(u"tag:yaml.org,2002:opencv-matrix", opencv_matrix_constructor)


# A yaml representer is for dumping structs into a yaml node.
# So for an opencv_matrix type (to be compatible with c++'s FileStorage) we save the rows, cols, type and flattened-data
def opencv_matrix_representer(dumper, mat):
    if mat.ndim > 1:
        mapping = {'rows': mat.shape[0], 'cols': mat.shape[1], 'dt': 'd', 'data': mat.reshape(-1).tolist()}
    else:
        mapping = {'rows': mat.shape[0], 'cols': 1, 'dt': 'd', 'data': mat.tolist()}
    return dumper.represent_mapping(u"tag:yaml.org,2002:opencv-matrix", mapping)
yaml.add_representer(np.ndarray, opencv_matrix_representer)

输出:

with open('output.yaml', 'w') as f:
    yaml.dump({"a matrix": np.zeros((10,10)), "another_one": np.zeros((5,))}, f)

with open('output.yaml', 'r') as f:
    print yaml.load(f)

虽然我无法控制行,列,dt,数据的顺序。

答案 5 :(得分:0)

pip install opencv-contrib-python支持安装特定版本的视频,请使用pip install opencv-contrib-python