現在、OpenCV C++ APIを使用して行列XML/YAMLを格納するためにFileStorageクラスを使用しています。
ただし、これらのXML/YAMLファイルを読み取る Python スクリプトを作成する必要があります。
OpenCV C++ APIによって生成されたXML/YAMLファイルを読み取ることができる既存の OpenCV Python APIを探しています
現在、OpenCV C++ APIを使用して行列XML/YAMLを格納するためにFileStorageクラスを使用しています。
ただし、これらのXML/YAMLファイルを読み取る Python スクリプトを作成する必要があります。
OpenCV C++ APIによって生成されたXML/YAMLファイルを読み取ることができる既存の OpenCV Python APIを探しています
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())
結果は dict になります。キーは、YAML に保存したものの名前です。
@misha の応答に加えて、OpenCV YAML は Python と互換性がありません。
非互換性のいくつかの理由は次のとおりです。
a: 2
なく、 である必要があります]a:2
次の関数は、それを提供します。
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 にのみ適用されます。XML には独自の問題がありますが、これは私が完全に調査したわけではありません。
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)
@Roy_Shilkrot による以前の回答を改善するために、numpy ベクトルと行列のサポートを追加しました。
# 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)
出力:
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
行、列、dt、データの順序を制御できませんでしたが。