2018年8月16日木曜日

OpenCVのcv::FileStorageをPythonで扱う

OpenCVでXML/YAML/JSONのデータ構造を扱う

OpenCVでcvパラメータを扱う場合、cv::FileStorageクラスが用意されている。XML, YAML, JSONの各フォーマットのファイルからパラメータの読み書きができる。

利点は、
  • C++で簡単にパラメータのファイルを扱うことができる
  • cv::Mat, cv::Size等のOpenCVの形式でパラメータを読み書きできること

カメラキャリブレーションのopencv_interactive-calibrationもXML形式のファイルを出力するので、パラメータを読む際は、cv::FileStorageクラスが利用できる。

自作中のPaspberry Piの3Dスキャナーでもcv::FileStorageクラスを利用してパラメータの読み込みを行う予定。


cv::FileStorageをPythonで使う

手書きでパラメータのファイルを作成するより、ファイルを自動生成できたほうが良いと考え、Pythonでツールを作成したのだが、思ったように使えないことが判明した。
(Pythonでサクッと作ってしまえば良いと思っていた)


Pythonで扱う場合の問題(デメリット)

配列(シーケンス)のデータを出力できない

例えば、C++で解像度などcv::Sizeで保持されるデータを出力した場合、シーケンスとして出力される。

<cameraResolution>
  640 480</cameraResolution>

しかし、Pythonにはcv::Sizeはなく、タプルで扱うことになるが、タプルはcv::Matに変換されてしまうため、シーケンスとして出力されず、以下のように出力されてしまう。

<cameraResolution type_id="opencv-matrix">
  <rows>2</rows>
  <cols>1</cols>
  <dt>d</dt>
  <data>
    640. 480.</data></cameraResolution>

これは、Pythonの場合、タプル、リストはすべてcv::Matにバインディングされるためである。読み込み時もPythonであれば、問題はないのだが、C++の場合、cv::Matにしか使えなくなってしまう。


マッピングのデータを出力できない

C++では<< operatorで"{", "}"を出力することで、マッピングされたデータを出力できる。
(同じように"[", "]"でシーケンスのデータを出力できる)
詳細は、OpenCVのドキュメントを参照。

しかし、Pythonには<< operatorはバインディングされていないため出力できない。


代替え方法

もともと、cv::FileStorageはC++でパラメータを扱いやすくするためであり、Pythonで扱うこと自体があまり良い考えでないと思う。
Pythonで扱うのであれば、PyYAMLを使ったほうが良く、Pythonで出力したデータをC++のcv::FileStorageで読み込むこともできるはず。
ただし、PyYAMLではcv::Matの形式では出力できなくなるが、その場合は自作してしまえば良いとなる。

0 件のコメント:

コメントを投稿