XML/YAML 永続性 ======================== .. index:: CvFileStorage .. _CvFileStorage: CvFileStorage ------------- ファイルストレージ :: typedef struct CvFileStorage { ... // 隠しフィールド } CvFileStorage; 構造体 :ref:`CvFileStorage` は,ディスク上のファイルと関連付けられたファイルストレージの,「ブラックボックス」的な表現です.後述されるいくつかの関数は,引数として :ctype:`CvFileStorage` をとり,スカラー値や標準的なCXCoreオブジェクト(行列やシーケンス,グラフ),ユーザ定義オブジェクトなどから構成される階層的コレクションに対して,読み書きを可能にします. CXCoreの関数では,XML( http://www.w3c.org/XML )や YAML( http://www.yaml.org )形式のデータの読み書きが可能です.以下は,浮動小数点型の :math:`$3 \times 3$` 単位行列 ``A`` を,CxCore 関数を用いて XML および YAML 形式のファイルに保存したものです: XML: :: \begin{verbatim} 3 3
f
1. 0. 0. 0. 1. 0. 0. 0. 1.
\end{verbatim} YAML: :: \begin{verbatim} %YAML:1.0 A: !!opencv-matrix rows: 3 cols: 3 dt: f data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1.] \end{verbatim} この例から分かるように,階層構造を表現するために,XMLではネスト(入れ子)されたタグを利用し,YAMLでは(Pythonと似た)インデントを利用します. 同じCXCore関数で,どちらのデータ形式の読み書きが可能で,オープンされたファイルの拡張子(XMLでは .xml,YAMLでは .yaml)によって形式を判別します. .. index:: CvFileNode .. _CvFileNode: CvFileNode ---------- ファイルストレージノード. :: /* ファイルノードの種類 */ #define CV_NODE_NONE 0 #define CV_NODE_INT 1 #define CV_NODE_INTEGER CV_NODE_INT #define CV_NODE_REAL 2 #define CV_NODE_FLOAT CV_NODE_REAL #define CV_NODE_STR 3 #define CV_NODE_STRING CV_NODE_STR #define CV_NODE_REF 4 /* not used */ #define CV_NODE_SEQ 5 #define CV_NODE_MAP 6 #define CV_NODE_TYPE_MASK 7 /* オプションフラグ */ #define CV_NODE_USER 16 #define CV_NODE_EMPTY 32 #define CV_NODE_NAMED 64 #define CV_NODE_TYPE(tag) ((tag) & CV_NODE_TYPE_MASK) #define CV_NODE_IS_INT(tag) (CV_NODE_TYPE(tag) == CV_NODE_INT) #define CV_NODE_IS_REAL(tag) (CV_NODE_TYPE(tag) == CV_NODE_REAL) #define CV_NODE_IS_STRING(tag) (CV_NODE_TYPE(tag) == CV_NODE_STRING) #define CV_NODE_IS_SEQ(tag) (CV_NODE_TYPE(tag) == CV_NODE_SEQ) #define CV_NODE_IS_MAP(tag) (CV_NODE_TYPE(tag) == CV_NODE_MAP) #define CV_NODE_IS_COLLECTION(tag) (CV_NODE_TYPE(tag) >= CV_NODE_SEQ) #define CV_NODE_IS_FLOW(tag) (((tag) & CV_NODE_FLOW) != 0) #define CV_NODE_IS_EMPTY(tag) (((tag) & CV_NODE_EMPTY) != 0) #define CV_NODE_IS_USER(tag) (((tag) & CV_NODE_USER) != 0) #define CV_NODE_HAS_NAME(tag) (((tag) & CV_NODE_NAMED) != 0) #define CV_NODE_SEQ_SIMPLE 256 #define CV_NODE_SEQ_IS_SIMPLE(seq) (((seq)->flags & CV_NODE_SEQ_SIMPLE) != 0) typedef struct CvString { int len; char* ptr; } CvString; /* 読み込んだファイルストレージに含まれる要素の全てのキー(names)は, ルックアップ処理の高速化のためハッシュに記憶されます. */ typedef struct CvStringHashNode { unsigned hashval; CvString str; struct CvStringHashNode* next; } CvStringHashNode; /* ファイルストレージの基本要素 - スカラー,またはコレクション */ typedef struct CvFileNode { int tag; struct CvTypeInfo* info; /* 型情報 (ユーザ定義オブジェクトでのみ利用する,そうでない場合は0) */ union { double f; /* 浮動小数点型のスカラー値 */ int i; /* 整数型のスカラー値 */ CvString str; /* 文字列 */ CvSeq* seq; /* シーケンス(順序付きファイルノードのコレクション) */ struct CvMap* map; /* マップ(名前付きファイルノードのコレクション) */ } data; } CvFileNode; この構造体は,ファイルストレージからデータを取り出す(例えば,ファイルからのデータ読み込み)ためだけに用いられます.ファイルへのデータ書き込みは,最小限のバッファを使い逐次的に実行されます.ファイルストレージには,データは保存されません. 逆にファイルからデータを読み出す場合,ファイル全体がパースされ,メモリ内に木構造として表現されます.また,木構造の各ノードは, :ref:`CvFileNode` によって表現されます.ファイルノード ``N`` の種類は, :cmacro:`CV_NODE_TYPE(N->tag)` として取得できます.いくつかのファイルノード(葉)は,文字列や,整数,浮動小数点数などのスカラーです.そして,それ以外のファイルノードには,ファイルノードのコレクション,スカラーのコレクション,あるいはコレクションのコレクション,などがあります.コレクションには,シーケンスとマップの2種類があります(ここでは YAML表記を用いるが,XTLでも同様である).シーケンス( :ref:`CvSeq` と混同しないように!)は,名前なしファイルノードの順序付きコレクションであり,マップは,名前付きファイルノードの順序なしコレクションです.したがって,シーケンスの要素にはインデックスでアクセスできますし( :ref:`GetSeqElem` )し,マップの要素には名前でアクセスできます( :ref:`GetFileNodeByName` ).次の表は,ファイルノードの種類について説明したものです: +------------------+-------------------------------------+----------------------------------+ | Type | :cmacro:`CV_NODE_TYPE(node->tag)` | Value | +------------------+-------------------------------------+----------------------------------+ | Integer | :cmacro:`CV_NODE_INT` | ``node->data.i`` | +------------------+-------------------------------------+----------------------------------+ | Floating-point | :cmacro:`CV_NODE_REAL` | ``node->data.f`` | +------------------+-------------------------------------+----------------------------------+ | Text string | :cmacro:`CV_NODE_STR` | ``node->data.str.ptr`` | +------------------+-------------------------------------+----------------------------------+ | Sequence | :cmacro:`CV_NODE_SEQ` | ``node->data.seq`` | +------------------+-------------------------------------+----------------------------------+ | Map | :cmacro:`CV_NODE_MAP` | ``node->data.map`` (see below) | +------------------+-------------------------------------+----------------------------------+ この ``map`` フィールドに直接アクセスする必要はありません(ちなみに :ctype:`CvMap` は隠しフィールドです).このマップの要素は,この「マップ」ファイルノードへのポインタを引数にとる関数 :ref:`GetFileNodeByName` で取得できます. ユーザ(独自の)オブジェクトは, :ref:`CvMat` や :ref:`CvSeq` などの CxCore の標準的な型のインスタンス,あるいは,関数 :ref:`RegisterTypeInfo` で登録された任意の型のインスタンスです.このようなオブジェクトは,オープンされたファイルストレージがパースされた後,初期状態では(前述のXMLやYAMLの例のように)ファイル内のマップとして表現されます.そして,ユーザが関数 :ref:`Read` や :ref:`ReadByName` を呼び出すと,その要求に従いオブジェクトがデコード(ネイティブな表現に変換)されます. .. index:: CvAttrList .. _CvAttrList: CvAttrList ---------- 属性のリスト. :: typedef struct CvAttrList { const char** attr; /* (attribute\_name,attribute\_value) ペアの配列.終端は NULL */ struct CvAttrList* next; /* 属性リストの次のチャンクへのポインタ */ } CvAttrList; /* 構造体 CvAttrList を初期化します */ inline CvAttrList cvAttrList( const char** attr=NULL, CvAttrList* next=NULL ); /* 存在すれば属性値を,なければ 0 (NULL) を返します */ const char* cvAttrValue( const CvAttrList* attr, const char* attr\_name ); 現在の実装では,属性値は,ユーザオブジェクトを書き込む際の追加パラメータを渡すために利用されます( :ref:`Write` を参照してください).オブジェクト型指定( ``type_id`` 属性 )を除けば,タグ内部のXML属性はサポートされません. .. index:: CvTypeInfo .. _CvTypeInfo: CvTypeInfo ---------- 型情報. :: typedef int (CV_CDECL *CvIsInstanceFunc)( const void* structPtr ); typedef void (CV_CDECL *CvReleaseFunc)( void** structDblPtr ); typedef void* (CV_CDECL *CvReadFunc)( CvFileStorage* storage, CvFileNode* node ); typedef void (CV_CDECL *CvWriteFunc)( CvFileStorage* storage, const char* name, const void* structPtr, CvAttrList attributes ); typedef void* (CV_CDECL *CvCloneFunc)( const void* structPtr ); typedef struct CvTypeInfo { int flags; /* 使用されません */ int header_size; /* sizeof(CvTypeInfo) */ struct CvTypeInfo* prev; /* リスト内で一つ前に登録された型 */ struct CvTypeInfo* next; /* リスト内で一つ後に登録された型 */ const char* type_name; /* ファイルストレージに書き込まれる型の名前 */ /* メソッド */ CvIsInstanceFunc is_instance; /* 渡されたオブジェクトが,この型のインスタンスであるかをチェックします */ CvReleaseFunc release; /* オブジェクトを解放します(メモリなど) */ CvReadFunc read; /* ファイルストレージからオブジェクトを読み込みます */ CvWriteFunc write; /* ファイルストレージにオブジェクトを書き込みます */ CvCloneFunc clone; /* オブジェクトのコピーを作成します */ } CvTypeInfo; 構造体 :ref:`CvTypeInfo` は,標準型またはユーザ定義型に属する,ある1つの型の型情報を保持します.その型のインスタンスは,対応する構造体 :ref:`CvTypeInfo` へのポインタを持つこともあれば,持たないこともあります.どちらの場合でも,関数 :ref:`TypeOf` を用いて,与えられたオブジェクトの型情報構造体を取得できます.別の手段として, :ref:`FindType` を利用して,型の名前から型情報を得ることも可能で,これは,ファイルストレージからオブジェクトを読み込む際に利用されます.また,型情報構造体を型リストの先頭に追加する関数 :ref:`RegisterType` を用いて,新しい型を登録することができます.つまり,一般的な標準型から特別な型を作成し,基本メソッドをオーバーライドすることが可能です. .. index:: Clone .. _Clone: Clone ----- .. cfunction:: void* cvClone( const void* structPtr ) オブジェクトを複製します. :param structPtr: 複製されるオブジェクト この関数は,与えられたオブジェクトの型を求め, オブジェクトへのポインタを引数に ``clone`` を呼び出します. .. index:: EndWriteStruct .. _EndWriteStruct: EndWriteStruct -------------- .. cfunction:: void cvEndWriteStruct(CvFileStorage* fs) 構造体の書き込みを終了します. :param fs: ファイルストレージ この関数は,現在の構造体の書き込みを終了します. .. index:: FindType .. _FindType: FindType -------- .. cfunction:: CvTypeInfo* cvFindType(const char* typeName) 名前から型を求めます. :param typeName: 形の名前 この関数は,登録された型の中から,指定された名前を持つものを見つけます.その名前をもつ型が存在しない場合,NULLが返されます. .. index:: FirstType .. _FirstType: FirstType --------- .. cfunction:: CvTypeInfo* cvFirstType(void) 型リストの先頭要素へのポインタを返します. この関数は,登録型リストの先頭の型を返します.あとは,構造体 :ref:`CvTypeInfo` のフィールド ``prev`` と ``next`` を介して,このリスト全体を走査できます. .. index:: GetFileNode .. _GetFileNode: GetFileNode ----------- .. cfunction:: CvFileNode* cvGetFileNode( CvFileStorage* fs,CvFileNode* map,const CvStringHashNode* key,int createMissing=0 ) マップあるいはファイルストレージから,ノードを見つけます. :param fs: ファイルストレージ :param map: 親であるマップ.これがNULLの場合,この関数はトップレベルノードを探索します. ``map`` と ``key`` が共にNULLの場合,トップレベルノードを含むマップであるルートファイルノードが返されます :param key: 関数 :ref:`GetHashedKey` によって取得できる,ノードの名前に対する固有のポインタ :param createMissing: 対応ノードが存在しないキーを,ハッシュテーブルに追加するかどうかを指定するフラグ この関数は,ファイルノードを見つけます.これは,関数 :ref:`GetFileNodeByName` の高速バージョンです( :ref:`GetHashedKey` の説明を参照してください).また,存在しないノードを指定すれば,マップに新しいノードを追加することもできます. .. index:: GetFileNodeByName .. _GetFileNodeByName: GetFileNodeByName ----------------- .. cfunction:: CvFileNode* cvGetFileNodeByName( const CvFileStorage* fs,const CvFileNode* map,const char* name) マップあるいはファイルストレージから,ノードを見つけます. :param fs: ファイルストレージ :param map: 親であるマップ.これがNULLの場合,この関数は全てのトップレベルノード(ストリーム)を探索します :param name: ノードの名前 この関数は,名前 ``name`` を元にファイルノードを見つけます.ノードの探索は, ``map`` 内で行われますが,そのポインタがNULLの場合はファイルストレージのトップレベルノード全体が探索されます.マップに対してはこの関数を,シーケンスに対しては :ref:`GetSeqElem` (あるいは,シーケンスリーダ)を用いることで,ファイルストレージ内を走査することができます.ある1つのキーに対する複数のクエリ(例えば,構造体の配列を探索する場合)をより高速に処理するためには, :ref:`GetHashedKey` と :ref:`GetFileNode` を組み合わせて使用することもできます. .. index:: GetFileNodeName .. _GetFileNodeName: GetFileNodeName --------------- .. cfunction:: const char* cvGetFileNodeName( const CvFileNode* node ) ファイルノードの名前を返します. :param node: ファイルノード この関数は,ファイルノードの名前を返します.ファイルノードが名前を持たない場合や, ``node`` が ``NULL`` の場合は,NULLを返します. .. index:: GetHashedKey .. _GetHashedKey: GetHashedKey ------------ .. cfunction:: CvStringHashNode* cvGetHashedKey( CvFileStorage* fs,const char* name,int len=-1,int createMissing=0 ) 与えられた名前に対する固有のポインタを返します. :param fs: ファイルストレージ :param name: ノードの名前 :param len: (もし,事前に分かっている場合の)名前の長さ.-1 にすると,この関数内で計算されます :param createMissing: 対応ノードが存在しないキーを,ハッシュテーブルに追加するかどうかを指定するフラグ この関数は,各ファイルノードの名前に固有なポインタを返します.このポインタは,関数 :ref:`GetFileNode` に渡すことができます.関数 :ref:`GetFileNode` は,文字列の内容ではなくポインタを利用して文字列同士を比較するので,関数 :ref:`GetFileNodeByName` よりも高速に動作します. 次の例では,点座標の配列が,2エントリのマップのシーケンスとしてエンコードされています: :: %YAML:1.0 points: - { x: 10, y: 10 } - { x: 20, y: 20 } - { x: 30, y: 30 } # ... また,ハッシュ化された"x"と"y"のポインタを取得することで,点座標のデコードを高速化することが可能です. .. index:: Example: Reading an array of structures from file storage .. _Example: Reading an array of structures from file storage: Example: Reading an array of structures from file storage --------------------------------------------------------- :: #include "cxcore.h" int main( int argc, char** argv ) { CvFileStorage* fs = cvOpenFileStorage( "points.yml", 0, CV\_STORAGE\_READ ); CvStringHashNode* x\_key = cvGetHashedNode( fs, "x", -1, 1 ); CvStringHashNode* y\_key = cvGetHashedNode( fs, "y", -1, 1 ); CvFileNode* points = cvGetFileNodeByName( fs, 0, "points" ); if( CV\_NODE\_IS\_SEQ(points->tag) ) { CvSeq* seq = points->data.seq; int i, total = seq->total; CvSeqReader reader; cvStartReadSeq( seq, &reader, 0 ); for( i = 0; i < total; i++ ) { CvFileNode* pt = (CvFileNode*)reader.ptr; #if 1 /* 高速バージョン */ CvFileNode* xnode = cvGetFileNode( fs, pt, x\_key, 0 ); CvFileNode* ynode = cvGetFileNode( fs, pt, y\_key, 0 ); assert( xnode && CV\_NODE\_IS\_INT(xnode->tag) && ynode && CV\_NODE\_IS\_INT(ynode->tag)); int x = xnode->data.i; // or x = cvReadInt( xnode, 0 ); int y = ynode->data.i; // or y = cvReadInt( ynode, 0 ); #elif 1 /* 低速バージョン.x_key と y_keyを利用しません */ CvFileNode* xnode = cvGetFileNodeByName( fs, pt, "x" ); CvFileNode* ynode = cvGetFileNodeByName( fs, pt, "y" ); assert( xnode && CV\_NODE\_IS\_INT(xnode->tag) && ynode && CV\_NODE\_IS\_INT(ynode->tag)); int x = xnode->data.i; // or x = cvReadInt( xnode, 0 ); int y = ynode->data.i; // or y = cvReadInt( ynode, 0 ); #else /* 超低速ですが使いやすいバージョン */ int x = cvReadIntByName( fs, pt, "x", 0 /* デフォルト値 */ ); int y = cvReadIntByName( fs, pt, "y", 0 /* デフォルト値 */ ); #endif CV\_NEXT\_SEQ\_ELEM( seq->elem\_size, reader ); printf("%d: (%d, %d)\n", i, x, y ); } } cvReleaseFileStorage( &fs ); return 0; } マップヘのアクセス方法に関わらず,単純なシーケンスを使うものに比べて,これはまだかなり遅いことに注意してください.例えば,上述の例で言えば,点座標を(マップのシーケンスではなく)複数の整数値のペアから成る1つのシーケンスとしてエンコードする方が,より効率的です. .. index:: GetRootFileNode .. _GetRootFileNode: GetRootFileNode --------------- .. cfunction:: CvFileNode* cvGetRootFileNode( const CvFileStorage* fs,int stream_index=0 ) ファイルストレージのトップレベルノードの1つを取得します. :param fs: ファイルストレージ :param stream_index: ストリームのインデックス,0が基準. :ref:`StartNextStream` を参照してください.多くの場合,ファイルにはストリームが1つだけ存在しますが,複数存在する事もあり得ます この関数は,ファイルストレージのトップレベルノードの1つを取得します.トップレベルノードは名前を持たず,これはファイルストレージに1つずつ順番に保存されているストリームに相当します.インデックスが範囲外だった場合,この関数は NULL ポインタを返します.つまり, ``stream_index=0,1,...`` を順に指定しながら,NULLポインタが返されるまで関数を繰り返し呼び出すことで,すべてのトップレベルノードを取得することができます.この関数は,ファイルストレージの再帰的な走査のために利用されます. .. index:: Load .. _Load: Load ---- .. cfunction:: void* cvLoad( const char* filename,CvMemStorage* memstorage=NULL,const char* name=NULL,const char** realName=NULL ) ファイルからオブジェクトを読み出します. :param filename: ファイル名 :param memstorage: :ref:`CvSeq` や :ref:`CvGraph` などの動的構造体のためのメモリストレージ.行列や画像の場合は利用されません :param name: オプションであるオブジェクト名.NULLの場合,ストレージ内の最初のトップレベルオブジェクトが読み出されます :param realName: オプション.読み出されたオブジェクトの実際の名前が書き込まれる出力パラメータ( ``name=NULL`` の場合に有用) この関数は,ファイルからオブジェクトを読み出します.これは, :ref:`Read` の簡単なインタフェースです.オブジェクトが読み出された後,ファイルストレージはクローズされ,テンポラリバッファは全て削除されます.よって,シーケンスや輪郭,グラフなどの動的構造体を読み出すためには,有効な出力先となるメモリストレージを関数に渡す必要があります. .. index:: OpenFileStorage .. _OpenFileStorage: OpenFileStorage --------------- .. cfunction:: CvFileStorage* cvOpenFileStorage(const char* filename,CvMemStorage* memstorage,int flags) データを読み書きするために,ファイルストレージをオープンします. :param filename: ストレージに関連付けられたファイルの名前 :param memstorage: 一時的なデータや, :ref:`CvSeq` , :ref:`CvGraph` などの動的構造体を格納するために使われるメモリストレージ.これがNULLの場合,一時的なメモリストレージが作成,使用されます :param flags: 以下の値のいずれか: * **CV_STORAGE_READ** - ストレージが読み込み用にオープンされます * **CV_STORAGE_WRITE** - ストレージが書き込み用にオープンされます この関数は,データを読み書きするためにファイルストレージをオープンします.書き込みの場合,新しいファイルが作成されるか,既に存在するファイルに再び書き込まれます.ファイルの読み書きの種類は,ファイル名の拡張子によって決まります: ``.xml`` は ``XML`` , ``.yml`` や ``.yaml`` は ``YAML`` となります.また,この関数は, :ref:`CvFileStorage` へのポインタを返します. .. index:: Read .. _Read: Read ---- .. cfunction:: void* cvRead( CvFileStorage* fs,CvFileNode* node,CvAttrList* attributes=NULL ) オブジェクトをデコードし,そのポインタを返します. :param fs: ファイルストレージ :param node: ルートオブジェクトノード :param attributes: 使用されないパラメータ この関数は,ユーザオブジェクト(オブジェクトは,ファイルストレージの部分木の固有表現から作成される)をデコードし,それを返します.デコードされるオブジェクトは,``read`` メソッド( :ref:`CvTypeInfo` を参照してください)をサポートする,登録済みの型のインスタンスでなければいけません.オブジェクトの型は,ファイルからエンコードされて得られる型名によって決まります.オブジェクトが動的構造体である場合,そのオブジェクトはメモリストレージ内に作成され,関数 :ref:`OpenFileStorage` に渡されます.NULLポインタが渡された場合は,一時的なメモリストレージ内に作成され,これは,関数 :ref:`ReleaseFileStorage` が呼ばれたときに解放されます.また,オブジェクトが動的構造体ではない場合は,オブジェクトはヒープ内に作成されます.これは,それ専用の関数か,あるいは一般的な関数 :ref:`Release` を用いて解放されます. .. index:: ReadByName .. _ReadByName: ReadByName ---------- .. cfunction:: void* cvReadByName( CvFileStorage* fs,const CvFileNode* map,const char* name,CvAttrList* attributes=NULL ) 指定された名前のオブジェクトを見つけ,それをデコードします. :param fs: ファイルストレージ :param map: 親であるマップ.これがNULLの場合,この関数はトップレベルノードを探索します :param name: ノードの名前 :param attributes: 使用されないパラメータ この関数は, :ref:`GetFileNodeByName` と :ref:`Read` の単純な合成です. .. index:: ReadInt .. _ReadInt: ReadInt ------- .. cfunction:: int cvReadInt( const CvFileNode* node,int defaultValue=0 ) ファイルノードから整数型の値を読み込みます. :param node: ファイルノード :param defaultValue: ``node`` がNULLの場合に返される値 この関数は,ファイルノードによって表される整数値を返します.ファイルノードがNULLの場合, ``defaultValue`` が返されます(つまり,関数 :ref:`GetFileNode` の直後にこの関数を呼ぶ場合,NULLポインタのチェックを行わずに良いので便利です).ファイルノードの型が :cmacro:`CV_NODE_INT` である場合は, ``node->data.i`` が返されます.また,ファイルノードの型が :cmacro:`CV_NODE_REAL` である場合は, ``node->data.f`` が整数に変換されて返されます.その他の場合は,戻り値は不定です. .. index:: ReadIntByName .. _ReadIntByName: ReadIntByName ------------- .. cfunction:: int cvReadIntByName( const CvFileStorage* fs,const CvFileNode* map,const char* name,int defaultValue=0 ) 指定された名前のファイルノードを見つけ,そこから整数値を読み込みます. :param fs: ファイルストレージ :param map: 親であるマップ.これがNULLの場合,この関数はトップレベルノードを探索します :param name: ノードの名前 :param defaultValue: ファイルノードが見つからない場合に返される値 この関数は, :ref:`GetFileNodeByName` と :ref:`ReadInt` の単純な合成です. .. index:: ReadRawData .. _ReadRawData: ReadRawData ----------- .. cfunction:: void cvReadRawData(const CvFileStorage* fs,const CvFileNode* src,void* dst,const char* dt) 複数の数値を読み込みます. :param fs: ファイルストレージ :param src: ファイルノード(シーケンス).ここから値を読み込みます :param dst: 出力配列へのポインタ :param dt: 各配列要素の指定. :ref:`WriteRawData` の場合と同じフォーマットです この関数は,スカラー値のシーケンスを表すファイルノードから値を読み込みます. .. index:: ReadRawDataSlice .. _ReadRawDataSlice: ReadRawDataSlice ---------------- .. cfunction:: void cvReadRawDataSlice( const CvFileStorage* fs,CvSeqReader* reader,int count,void* dst,const char* dt ) シーケンスリーダからデータを読み込みます. :param fs: ファイルストレージ :param reader: シーケンスリーダ. :ref:`StartReadRawData` で初期化されます :param count: 読み込む要素の数 :param dst: 出力配列へのポインタ :param dt: 各配列要素の指定. :ref:`WriteRawData` の場合と同じフォーマットです この関数は,シーケンスを表すファイルノードから1つあるいは複数の要素を読み込み,ユーザが指定した配列に書き出します.読み込まれるシーケンス要素の総数は, ``count`` と各配列要素に含まれる値の個数の積となります.例えば,dt= ``2if`` の場合だと,この関数は, :math:`$\texttt{count} \times 3$` 個のシーケンス要素を読み出します.また, :ref:`SetSeqReaderPos` によってリーダが移動されると,シーケンスの種類に関わらず,ファイルノードの一部が読み飛ばされたり,繰り返し読まれたりする場合があります. .. index:: ReadReal .. _ReadReal: ReadReal -------- .. cfunction:: double cvReadReal( const CvFileNode* node,double defaultValue=0. ) ファイルノードから浮動小数点型の値を読み込みます. :param node: ファイルノード :param defaultValue: ``node`` がNULLの場合に返される値 この関数は,ファイルノードによって表される浮動小数点数を返します.ファイルノードがNULLの場合, ``defaultValue`` が返されます(つまり,関数 :ref:`GetFileNode` の直後にこの関数を呼ぶ場合,NULLポインタのチェックを行わずに良いので便利です).ファイルノードの型が :cmacro:`CV_NODE_REAL` である場合は, ``node->data.f`` が返されます.また,ファイルノードの型が :cmacro:`CV_NODE_INT` である場合は, ``node->data.i`` が浮動小数点数に変換されて返されます.その他の場合は,戻り値は不定です. .. index:: ReadRealByName .. _ReadRealByName: ReadRealByName -------------- .. cfunction:: double cvReadRealByName(const CvFileStorage* fs,const CvFileNode* map,const char* name,double defaultValue=0.) 指定された名前のファイルノードを見つけ,そこから浮動小数点値を読み込みます. :param fs: ファイルストレージ :param map: 親であるマップ.これがNULLの場合,この関数はトップレベルノードを探索します :param name: ノードの名前 :param defaultValue: ファイルノードが見つからない場合に返される値 この関数は, :ref:`GetFileNodeByName` と :ref:`ReadReal` の単純な合成です. .. index:: ReadString .. _ReadString: ReadString ---------- .. cfunction:: const char* cvReadString( const CvFileNode* node,const char* defaultValue=NULL ) ファイルノードから文字列を読み込みます. :param node: ファイルノード :param defaultValue: ``node`` がNULLの場合に返される値 この関数は,ファイルノードによって表される文字列を返します.ファイルノードがNULLの場合, ``defaultValue`` が返されます(つまり,関数 :ref:`GetFileNode` の直後にこの関数を呼ぶ場合,NULLポインタのチェックを行わずに良いので便利です).ファイルノードの型が :cmacro:`CV_NODE_STR` である場合は, ``node->data.str.ptr`` が返されます.その他の場合の戻り値は,不定です. .. index:: ReadStringByName .. _ReadStringByName: ReadStringByName ---------------- .. cfunction:: const char* cvReadStringByName( const CvFileStorage* fs,const CvFileNode* map,const char* name,const char* defaultValue=NULL ) 指定された名前のファイルノードを見つけ,そこから文字列を読み込みます. :param fs: ファイルストレージ :param map: 親であるマップ.これがNULLの場合,この関数はトップレベルノードを探索します :param name: ノードの名前 :param defaultValue: ファイルノードが見つからない場合に返される値 この関数は, :ref:`GetFileNodeByName` と :ref:`ReadString` の単純な合成です. .. index:: RegisterType .. _RegisterType: RegisterType ------------ .. cfunction:: void cvRegisterType(const CvTypeInfo* info) 新しい型を登録します. :param info: 型情報構造体 この関数は,構造体 ``info`` によって記述される新しい型を登録します.この関数は,その構造体のコピーを作成するので,ユーザは関数呼び出し後に元の構造体を削除するべきです. .. index:: Release .. _Release: Release ------- .. cfunction:: void cvRelease( void** structPtr ) オブジェクトを解放します. :param structPtr: オブジェクトへのダブルポインタ この関数は,与えられたオブジェクトの型を見つけ,ダブルポインタを引数に ``release`` を呼び出します. .. index:: ReleaseFileStorage .. _ReleaseFileStorage: ReleaseFileStorage ------------------ .. cfunction:: void cvReleaseFileStorage(CvFileStorage** fs) フィルストレージを解放します. :param fs: 解放されるファイルストレージへのダブルポインタ この関数は,そのストレージに関連付けられているファイルをクローズし,すべての一時的な構造体を解放します.この関数を呼び出す場合は,必ずそのストレージに関する全ての入出力処理が終了していなければいけません. .. index:: Save .. _Save: Save ---- .. cfunction:: void cvSave( const char* filename,const void* structPtr,const char* name=NULL,const char* comment=NULL,CvAttrList attributes=cvAttrList()) オブジェクトをファイルに保存します. :param filename: ファイル名 :param structPtr: 保存されるオブジェクト :param name: オプションであるオブジェクト名.NULLの場合, ``filename`` から作成されます :param comment: オプション.ファイル先頭に書き込まれるコメント :param attributes: オプションである :ref:`Write` に渡される属性 この関数は,オブジェクトをファイルに保存します.これは,関数 :ref:`Write` の簡単なインタフェースです. .. index:: StartNextStream .. _StartNextStream: StartNextStream --------------- .. cfunction:: void cvStartNextStream(CvFileStorage* fs) 次のストリームを開始します. :param fs: ファイルストレージ この関数は,ファイルストレージの次のストリームを開始します.YAMLとXMLは両方とも,複数の「ストリーム」をサポートしています.これは,ファイルの連結や書き込み処理の再開の際に役立ちます. .. index:: StartReadRawData .. _StartReadRawData: StartReadRawData ---------------- .. cfunction:: void cvStartReadRawData( const CvFileStorage* fs,const CvFileNode* src,CvSeqReader* reader) ファイルノードシーケンスリーダを初期化します. :param fs: ファイルストレージ :param src: ファイルノード(シーケンス).ここから値を読み込みます :param reader: シーケンスリーダへのポインタ 関数 :cfunc:`cvStartReadRawData()` は,ファイルノードからデータを読み込むためにシーケンスリーダを初期化します.そして,初期化されたリーダは,関数 :ref:`ReadRawDataSlice` に渡すことができます. .. index:: StartWriteStruct .. _StartWriteStruct: StartWriteStruct ---------------- .. cfunction:: void cvStartWriteStruct( CvFileStorage* fs,const char* name,int struct_flags,const char* typeName=NULL,CvAttrList attributes=cvAttrList( )) 新しい構造体の書き込みを開始します. :param fs: ファイルストレージ :param name: 書き込まれる構造体の名前.読み込む場合は,この名前で構造体にアクセスできます :param struct_flags: 以下の値の組み合わせ: * **CV_NODE_SEQ** - 書き込まれる構造体がシーケンス( :ref:`CvFileStorage` の説明を参照してください).つまり,その要素は名前を持ちません * **CV_NODE_MAP** - 書き込まれる構造体がマップ( :ref:`CvFileStorage` の説明を参照してください).つまり,すべての要素が名前を持ちます.これら2つのフラグは,排他的に利用されます * **CV_NODE_FLOW** - オプション:YAMLストリームに対してのみ意味があります.構造体は,(blockではなく)よりコンパクトな flow として保存されます.すべての要素がスカラーである構造体では,このフラグを利用することが推奨されます :param typeName: オプションパラメータ.オブジェクトの型名.XMLの場合,構造体開始タグの ``type_id`` 属性として記述されます.YAMLの場合,構造体名の後にコロンに続いて記述されます( :ref:`CvFileStorage` の説明を参照してください).これは,主にユーザオブジェクトで利用されます.つまり,ストレージを読む場合に,エンコードされた型名を利用してオブジェクトの型を判別します( :ref:`CvTypeInfo` と :ref:`FindTypeInfo` を参照してください) :param attributes: 現在の実装では,このパラメータは利用されていません この関数は,マップやシーケンスの複合構造体(コレクション)の書き込みを開始します.構造体の,スカラーや構造体からなる全フィールドが書き込まれた後で, :ref:`EndWriteStruct` が実行されるべきです.この関数は,オブジェクトをグループ化する場合や,ユーザオブジェクトに対して ``write`` を実装する場合などに用いられます( :ref:`CvTypeInfo` を参照してください). .. index:: TypeOf .. _TypeOf: TypeOf ------ .. cfunction:: CvTypeInfo* cvTypeOf( const void* structPtr ) オブジェクトの型を返します. :param structPtr: オブジェクトへのポインタ この関数は,与えられたオブジェクトの型を求めます.登録された型のリストを順に走査し,リスト内のそれぞれの型情報構造体に対して,このオブジェクトを引数として関数/メソッド ``is_instance``を呼び出します.この処理を,0ではない値が返されるか,リストを走査し終えるまで繰り返します.後者の場合,この関数はNULLを返します. .. index:: UnregisterType .. _UnregisterType: UnregisterType -------------- .. cfunction:: void cvUnregisterType( const char* typeName ) 型の登録を解除します. :param typeName: 登録解除される型の名前 この関数は,指定された名前をもつ型の登録を解除します.不明な名前であれば, :ref:`TypeOf` にその型のインスタンスを渡すか,あるいは :ref:`FirstType` から順に型リストを探索して型情報を得ます.それから, :cfunc:`cvUnregisterType(info->type_name)` を呼び出します. .. index:: Write .. _Write: Write ----- .. cfunction:: void cvWrite( CvFileStorage* fs,const char* name,const void* ptr,CvAttrList attributes=cvAttrList() ) ユーザオブジェクトを書き込みます. :param fs: ファイルストレージ :param name: 書き込まれるオブジェクトの名前.親構造体がシーケンスの場合にのみ,NULLにするべきです :param ptr: オブジェクトへのポインタ :param attributes: オブジェクトの属性.この属性は,型ごとに固有のものです(後述の説明を参照してください) この関数は,ファイルストレージにオブジェクトを書き込みます.まず, :ref:`TypeOf` を用いて適切な型情報を求め,それから,その型に関連する ``write`` メソッドが呼び出されます. 属性は,書き込み手続きをカスタマイズするために利用されます.標準の型では,以下の属性をサポートしています(すべての ``*dt`` 属性は, :ref:`WriteRawData` の引数 dt と同じフォーマットです): * CvSeq * **header_dt** - シーケンスヘッダ内のユーザフィールドの記述.ユーザフィールドは,CvSeq,CvChain(そのシーケンスが,フリーマンチェーンの場合),CvContour(そのシーケンスが輪郭か点列の場合)に続いて書かれます * **dt** - シーケンス要素の記述 * **recursive** - この値が "0" でも "false" でも無い場合,シーケンス(輪郭)の木全体が保存されます * Cvgraph * **header_dt** - グラフヘッダ内で CvGraph に続いて書かれるユーザフィールドの記述 * **vertex_dt** - グラフ頂点のユーザフィールドの記述 * **edge_dt** - グラフ辺のユーザフィールドの記述(辺の重みは常に書き込まれるので,明示的にそれを指定する必要はありません) 以下は, :ctype:`CvFileStorage` の説明にある YAML ファイルを作成するコードです: :: #include "cxcore.h" int main( int argc, char** argv ) { CvMat* mat = cvCreateMat( 3, 3, CV_32F ); %修正 CvFileStorage* fs = cvOpenFileStorage( "example.yml", 0, CV_STORAGE_WRITE );%修正 cvSetIdentity( mat ); cvWrite( fs, "A", mat, cvAttrList(0,0) ); cvReleaseFileStorage( &fs ); cvReleaseMat( &mat ); return 0; } .. index:: WriteComment .. _WriteComment: WriteComment ------------ .. cfunction:: void cvWriteComment(CvFileStorage* fs,const char* comment,int eolComment) コメントを書き込みます. :param fs: ファイルストレージ :param comment: 書き込まれる,1行あるいは複数行のコメント :param eolComment: 0以外の場合,現在の行の最後にコメントが書き込まれます.0 の場合で,コメントが複数行,あるいは現在の行内に収まらないときは,新しい行にコメントが書き込まれます この関数は,ファイルストレージにコメントを書き込みます.ストレージを読み込む際にはコメントは読み飛ばされるので,これはデバッグや説明を記述する目的でのみ利用します. .. index:: WriteFileNode .. _WriteFileNode: WriteFileNode ------------- .. cfunction:: void cvWriteFileNode( CvFileStorage* fs,const char* new_node_name,const CvFileNode* node,int embed ) ファイルノードを,他のファイルストレージに書き込みます. :param fs: 書き込み先のファイルストレージ :param new_file_node: 書き込み先ファイルストレージにおけるファイルノードの新しい名前.元の名前をそのまま使うには, :ref:`cvGetFileNodeName` を利用します :param node: 書き込まれるファイルノード :param embed: 書き込まれるファイルノードがコレクションで,この値が 0ではない場合,新たな階層レベルは作成されません.その代わりに, ``node`` の全ての要素が,現在の構造体に書き込まれます.当然ながら,マップ要素はマップにのみ,シーケンス要素はシーケンスにのみ書き込まれます この関数は,ファイルノードのコピーをファイルストレージに書き込みます.これは,複数のファイルストレージを1つにマージしたり,XMLとYAML形式を変換したりする場合に利用できます. .. index:: WriteInt .. _WriteInt: WriteInt -------- .. cfunction:: void cvWriteInt(CvFileStorage* fs,const char* name,int value) 整数型の値を書き込みます. :param fs: ファイルストレージ :param name: 書き込まれる値の名前.親構造体がシーケンスの場合にのみ,NULLにするべきです :param value: 書き込まれる値 この関数は,1つの整数値(名前あり,または名前なし)をファイルストレージに書き込みます. .. index:: WriteRawData .. _WriteRawData: WriteRawData ------------ .. cfunction:: void cvWriteRawData( CvFileStorage* fs,const void* src,int len,const char* dt ) 複数の数値を書き込みます. :param fs: ファイルストレージ :param src: 書き込まれる配列へのポインタ :param len: 書き込まれる配列の要素数 :param dt: 以下のフォーマットに従い各配列要素を指定します ``([count]{'u'|'c'|'w'|'s'|'i'|'f'|'d')...`` これらの記号は,C言語の組み込み型に対応します: * **u** - 8ビット符号なし * **c** - 8ビット符号あり * **w** - 16ビット符号なし * **s** - 16ビット符号あり * **i** - 32ビット符号あり * **f** - 単精度浮動小数点数 * **d** - 倍精度浮動小数点数 * **r** - ポインタ.下位32ビットが,符号あり整数として書き込まれます.この型は,互いへのリンクをもつ複数の構造体を保存する場合などに利用されます.また, ``count`` は,与えられた型のカウンタ(オプション)です.例えば, ``2if`` は,各配列要素が,2つの整数とそれに続く単精度浮動小数点数からなる構造体であることを意味します.これと等価な表記として, '``iif``' や '``2i1f``' などがあります.また,別の例として, ``u`` はバイト配列, ``2d`` は倍精度浮動小数点数2つのペアから構成される配列,を表します この関数は,1つあるいは複数の数値で構成される要素をもつ配列を書き込みます.この関数は, :ref:`WriteInt` と :ref:`WriteReal` を繰り返し呼び出すことで代用可能ですが,1度だけこの関数を呼び出す方が効率的です.また,これらの要素は名前を持たないため,マップではなくシーケンスに書き込まれるべきものであることに注意してください. .. index:: WriteReal .. _WriteReal: WriteReal --------- .. cfunction:: void cvWriteReal( CvFileStorage* fs,const char* name,double value ) 浮動小数点型の値を書き込みます. :param fs: ファイルストレージ :param name: 書き込まれるオブジェクトの名前.親構造体がシーケンスの場合にのみ,NULLにするべきです :param value: 書き込まれる値 この関数は,単精度浮動小数点型の値(名前あり,または名前なし)をファイルに書き込みます.また,特殊な値は次のようにエンコードされます:NaN (Not A Number) は .NaN, :math:`$ \pm \infty $` は +.Inf(-.Inf) . 以下の例では,新たな型を登録することなく,停止基準構造体などの独自の構造体に値を格納するための,低レベル書き込み関数の使い方を示します. :: void write_termcriteria( CvFileStorage* fs, const char* struct_name, CvTermCriteria* termcrit ) { cvStartWriteStruct( fs, struct_name, CV_NODE_MAP, NULL, cvAttrList(0,0)); cvWriteComment( fs, "termination criteria", 1 ); // 単なる説明コメント if( termcrit->type & CV_TERMCRIT_ITER ) cvWriteInteger( fs, "max_iterations", termcrit->max_iter ); if( termcrit->type & CV_TERMCRIT_EPS ) cvWriteReal( fs, "accuracy", termcrit->epsilon ); cvEndWriteStruct( fs ); } .. index:: WriteString .. _WriteString: WriteString ----------- .. cfunction:: void cvWriteString( CvFileStorage* fs,const char* name,const char* str,int quote=0 ) 文字列を書き込みます. :param fs: ファイルストレージ :param name: 書き込まれるオブジェクトの名前.親構造体がシーケンスの場合にのみ,NULLにするべきです :param str: 書き込まれる文字列 :param quote: 0ではない場合,必要かどうかに関わらず,書き込まれる文字列は引用符で挟まれます.0の場合,必要なとき(例えば,文字列の先頭が数字,文字列に空白が含まれているなど)にのみ引用符が用いられます この関数は,ファイルストレージに文字列を書き込みます.