Actualmente estoy usando FileStorage clase para almacenar matrices XML, YAML usando OpenCV C++ API.

Sin embargo, tengo que escribir una secuencia de Comandos de Python que lee los XML, YAML archivos.

Estoy buscando existente OpenCV API de Python que puede leer la XML, YAML los archivos generados por OpenCV API de C++

InformationsquelleAutor garak | 2012-06-21

5 Comentarios

  1. 21

    Puede utilizar PyYAML para analizar los archivos YAML.

    Desde PyYAML no entiende OpenCV tipos de datos, es necesario especificar un constructor para cada OpenCV tipo de datos que está intentando cargar. Por ejemplo:

    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)

    Una vez que hayas hecho esto, la carga de los archivos yaml es simple:

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

    Resultado será un diccionario, donde las claves son los nombres de lo guardó en el archivo YAML.

    • ¿sabes por qué se da esta advertencia? comparison to 'None' will result in an elementwise object comparison in the future. if data in [None, ()]:
    • Agregar @vishal consejo acerca de eliminar la primera línea, y esta respuesta sería perfecto. De lo contrario, python no será capaz de leer el archivo.
    • Además, el conjunto de tipos de datos. Afortunadamente, la colección de datos-tipo de códigos son los mismos que OpenCV es, al menos para los tipos simples como float y double.
    • Esto no funciona para mí. Yo escribo .yml con c++ y leer por encima. El resultado numpy matriz no es el mismo que el original (multidimensional) cv::Mat
    • Por favor, ver @TimSC la respuesta de la respuesta correcta – la pregunta pide específicamente el de Python OpenCV API, esta respuesta da una extraña PyYAML manera de hacerlo.
  2. 8

    Además a @misha respuesta, OpenCV YAML son algo incompatibles con Python.

    Algunas de las razones de incompatibilidad son:

    1. Yaml creado por OpenCV no tiene un espacio después de «:». Mientras que Python lo requiere. [Ex: debe ser a: 2, y no a:2 para Python]
    2. Primera línea de YAML archivo creado por OpenCV está mal. Convertir «%YAML:1.0» a «%YAML 1.0». O saltar a la primera línea, mientras que la lectura.

    La siguiente función se encarga de proveer de que:

    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': ', yamlFileOut)
            ret = yaml.load(yamlFileOut)
        return ret
    
    outDict = readYAMLFile("file.yaml")

    NOTA: la respuesta Anterior es aplicable sólo para los yaml es. XML tienen su propia cuota de problemas, algo que no he explorado completamente.

    • Consejo útil. He intentado cambiar la línea a «YAML 1.0» a pesar de, y no funciona. Así que usted tiene a la franja de la primera línea.
    • Había que poner el % antes de YAML?
    • Sí. Lo siento, eso fue sólo una errata en mi comentario. Con %YAML 1.0 tengo un ParseError. Esto es con PyYAML 3.12 para Python 3.6.
    • Por favor, ver @TimSC la respuesta de la respuesta correcta – la pregunta pide específicamente el de Python OpenCV API, que funciona bien con el C++ generado YAMLs.
  3. 6

    El uso de la FileStorage funciones disponibles en OpenCV 3.2, la he usado con éxito:

    import cv2
    fs = cv2.FileStorage("calibration.xml", cv2.FILE_STORAGE_READ)
    fn = fs.getNode("Camera_Matrix")
    print (fn.mat())
    • ¿Sabe usted cómo obtener la lista de todos los nodos disponibles?
  4. 4

    Escribí un pequeño fragmento de código para leer y escribir FileStorage-compatible YAMLs en Python:

    # 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)
  5. 1

    Para mejorar la respuesta anterior por @Roy_Shilkrot he añadido soporte para numpy vectores así como matrices:

    # 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)

    Ejemplo:

    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)

    De salida:

    a matrix: !!opencv-matrix
    cols: 10
    data: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0]
    dt: d
    rows: 10
    another_one: !!opencv-matrix
    cols: 1
    data: [0.0, 0.0, 0.0, 0.0, 0.0]
    dt: d
    rows: 5

    A pesar de que yo no podía controlar el orden de las filas, columnas, dt, datos.

Dejar respuesta

Please enter your comment!
Please enter your name here