CXCORE リファレンス マニュアル
- 基本構造体(Basic Structures)
- 配列操作(Operations on Arrays)
- 動的構造体(Dynamic Structures)
- メモリストレージ(Memory Storages)
- シーケンス(Sequences)
- セット(Sets)
- グラフ(Graphs)
- 木(Trees)
- 描画関数(Drawing Functions)
- データ永続性と実行時型情報(Data Persistence and RTTI)
- その他の関数(Miscellaneous Functions)
- エラーハンドリングとシステム関数(Error Handling and System Functions)
動的構造体(Dynamic Structures)
シーケンス(Sequences)
CvSeq
拡張可能な要素のシーケンス
#define CV_SEQUENCE_FIELDS() ¥ int flags; /* 様々なフラグ */ ¥ int header_size; /* シーケンスのヘッダサイズ */ ¥ struct CvSeq* h_prev; /* 一つ前のシーケンスへのポインタ */ ¥ struct CvSeq* h_next; /* 一つ後のシーケンスへのポインタ */ ¥ struct CvSeq* v_prev; /* 一つ前のシーケンスへのポインタ(セカンダリ,構造によって意味が異なる) */ ¥ struct CvSeq* v_next; /* 一つ後のシーケンスへのポインタ(セカンダリ,構造によって意味が異なる) */ ¥ int total; /* 要素の総数 */ ¥ int elem_size;/* シーケンス要素のサイズ(バイト単位) */ ¥ char* block_max;/* 最新のブロックの最大値 */ ¥ char* ptr; /* 現在の書き込みポインタ */ ¥ int delta_elems; /* シーケンスを拡張させる際に,領域確保する要素数(シーケンスの粒度) */ ¥ CvMemStorage* storage; /* seqが保存される領域 */ ¥ CvSeqBlock* free_blocks; /* 空きブロックリスト */ ¥ CvSeqBlock* first; /* 先頭シーケンスブロックへのポインタ */ typedef struct CvSeq { CV_SEQUENCE_FIELDS() } CvSeq;
構造体 CvSeq は,OpenCVの動的データ構造すべての基本となるものである.
上記の補助マクロを介した特殊な定義により,追加パラメータを伴う構造体CvSeq の拡張が容易に行える. CvSeq を拡張するために,新しい構造体を定義し,マクロCV_SEQUENCE_FIELDS()によって列挙される CvSeq のフィールドの後にユーザー定義フィールドをおいてもよい.
シーケンスには,密なシーケンスと疎なシーケンスの2種類が存在する. 密なシーケンスの基本タイプは CvSeq であり,このシーケンスは拡張可能な1次元配列 (ベクトル(vectors),スタック(stacks),キュー(queues),デック(deques))を表現するのに用いられる. これらのタイプにはデータの中間部分に空白部がない.すなわち,シーケンスの中間部分における要素の削除や追加の際には,最も近い終端の要素からシフトされる. 疎なシーケンスは,CvSetをその基本クラスとして持つ.詳細は後述する. それらは,ノードフラグによって「データがある」か「空き」かが示されているノードシーケンスである. このタイプのシーケンスは,要素の集合(sets),グラフ(graph),ハッシュテーブル(hash tables)等の順序のないデータ構造に用いられる.
フィールド header_size は,シーケンスヘッダの実サイズが入っており, そのサイズは,sizeof(CvSeq)より大きいか等しくなけらばならない.
フィールド h_prev, h_next, v_prev, v_next は,別々のシーケンス群から階層構造を生成するために使用できる. フィールド h_prev と h_next は,同一階層での前後のシーケンスを指し, さらに,フィールド v_prev と v_next は縦方向での前後のシーケンス(自分の親と最初の子)を指す. しかし,これらは単に名前にすぎず,これらのポインタを異なる意味で使用することが可能である.
フィールド first は,ブロックの先頭シーケンスを指す.この構造については以下で述べる.
フィールド total は,密なシーケンスでは実要素数,疎なシーケンスでは領域確保されたノード数を示す.
フィールド flags は,上位16ビットで個々の動的特性 (密なシーケンスではCV_SEQ_MAGIC_VAL ,疎なシーケンスではCV_SET_MAGIC_VAL)と, シーケンスに関するその他の雑多な情報を持つ. 下位 CV_SEQ_ELTYPE_BITS ビットは,要素タイプのIDを示す. ほとんどのシーケンス処理関数は要素タイプではなく,elem_sizeに保存された要素サイズを使用する. シーケンスがCvMatタイプの一つであるような数値データからなる場合, シーケンスの要素タイプは対応するCvMatの要素タイプと一致する (例えば,2次元の点データのシーケンスではCV_32SC2が,浮動小数点型のシーケンスにはCV_32FC1が用いられるなど). マクロ CV_SEQ_ELTYPE(seq_header_ptr) は,シーケンスの要素のタイプを取り出す. 数値シーケンスを扱う関数では elem_size が,その要素タイプから計算されたものと等しいかどうかがチェックされる. さらに,CvMat に準拠したタイプでは,ヘッダ cvtypes.h で定義された以下の追加要素タイプが存在する:
標準的なシーケンス要素の種類
#define CV_SEQ_ELTYPE_POINT CV_32SC2 /* (x,y) */ #define CV_SEQ_ELTYPE_CODE CV_8UC1 /* フリーマンコード: 0..7 */ #define CV_SEQ_ELTYPE_GENERIC 0 /* 一般的なシーケンス要素タイプ */ #define CV_SEQ_ELTYPE_PTR CV_USRTYPE1 /* =6 */ #define CV_SEQ_ELTYPE_PPOINT CV_SEQ_ELTYPE_PTR /* &elem: 他のシーケンス要素へのポインタ */ #define CV_SEQ_ELTYPE_INDEX CV_32SC1 /* #elem: 他のシーケンス要素のインデックス */ #define CV_SEQ_ELTYPE_GRAPH_EDGE CV_SEQ_ELTYPE_GENERIC /* &next_o, &next_d, &vtx_o, &vtx_d */ #define CV_SEQ_ELTYPE_GRAPH_VERTEX CV_SEQ_ELTYPE_GENERIC /* 先頭の辺, &(x,y) */ #define CV_SEQ_ELTYPE_TRIAN_ATR CV_SEQ_ELTYPE_GENERIC /* 二分木の頂点(ノード) */ #define CV_SEQ_ELTYPE_CONNECTED_COMP CV_SEQ_ELTYPE_GENERIC /* 接続成分 */ #define CV_SEQ_ELTYPE_POINT3D CV_32FC3 /* (x,y,z) */
次の,CV_SEQ_KIND_BITS ビットは,シーケンスの種類を指定する.
標準的なシーケンスの種類
/* 一般的な(特別な指定無しの)シーケンスの種類 */ #define CV_SEQ_KIND_GENERIC (0 << CV_SEQ_ELTYPE_BITS) /* 密なシーケンスのサブタイプ */ #define CV_SEQ_KIND_CURVE (1 << CV_SEQ_ELTYPE_BITS) #define CV_SEQ_KIND_BIN_TREE (2 << CV_SEQ_ELTYPE_BITS) /* 疎なシーケンス(または集合)のサブタイプ */ #define CV_SEQ_KIND_GRAPH (3 << CV_SEQ_ELTYPE_BITS) #define CV_SEQ_KIND_SUBDIV2D (4 << CV_SEQ_ELTYPE_BITS)
残りのビットは,これ以外のシーケンスの種類や要素タイプを指定するために用いられる. 例えば,点(CV_SEQ_KIND_CURVE|CV_SEQ_ELTYPE_POINT )から構成される曲線では,タイプ CV_SEQ_POLYGON に属するフラグCV_SEQ_FLAG_CLOSED や,他のフラグがそのサブタイプを表現するために用いられる. 多くの輪郭処理関数は,入力シーケンスのタイプをチェックし,そのタイプがサポート外である場合はエラーを発生する. ファイル cvtypes.h には,サポートされている定義済みシーケンスタイプやその他の属性を取得する補助マクロの全リストが記述されている. 以下はシーケンスを構成するための基本要素の定義である.
CvSeqBlock
連続したシーケンスブロック
typedef struct CvSeqBlock { struct CvSeqBlock* prev; /* 前のシーケンスブロック */ struct CvSeqBlock* next; /* 次のシーケンスブロック */ int start_index; /* ブロックの先頭要素のインデックス + sequence->first->start_index */ int count; /* ブロック内の要素数 */ char* data; /* ブロックの先頭要素へのポインタ */ } CvSeqBlock;
シーケンスブロックは,循環双方向リストを構成する. そのためポインタ prev,next は決してNULL にはならず,シーケンス中の前後のシーケンスブロックを指す. つまり,最終ブロックの next は先頭ブロックを,先頭ブロックの prev は最終ブロックをそれぞれ指している. フィールド start_index と count はシーケンスの中でブロックの位置を追跡する際に役立つ. 例えば,シーケンスが10要素からなっており,それが3,5,2要素に分かれており,先頭ブロックがパラメータstart_index = 2で与えられている場合, このシーケンスブロックの (start_index, count) のペアは,それぞれ (2,3), (5, 5), (10, 2) となる. 先頭ブロックのパラメータ start_index は,ある要素がシーケンスの先頭に追加されている場合を除いて,通常 0 である.
CvSlice
シーケンスのスライス
typedef struct CvSlice
{
int start_index;
int end_index;
} CvSlice;
inline CvSlice cvSlice( int start, int end );
#define CV_WHOLE_SEQ_END_INDEX 0x3fffffff
#define CV_WHOLE_SEQ cvSlice(0, CV_WHOLE_SEQ_END_INDEX)
/* シーケンスのスライス長を計算する */
int cvSliceLength( CvSlice slice, const CvSeq* seq );
シーケンスを処理する関数のうちいくつかは,デフォルトでシーケンス全体(CV_WHOLE_SEQ)がセットされているパラメータ CvSlice slice を使用する. start_index か end_index が負かシーケンス長を超えている場合でも, start_indexは境界に含まれ(スライスに含まれる),end_index は境界に含まれない(スライスに含まれない). これらが等しい場合は,スライスは空である(すなわち要素が無い)とみなされる. シーケンスは循環構造として取り扱われるため,シーケンス最後の数個の要素と,それに続くシーケンス最初の数個の要素をスライスとして選択できる. 例えば,10個の要素をもつシーケンスの cvSlice(-2, 3) は,最終の一つ前(8th),最終(9th),先頭(0th), 2番目(1th) そして3番目(2nd)の要素からなる. この関数はスライスの引数を以下の方法で正規化する. まずスライス長を調べるために cvSliceLength を呼び出し, cvGetSeqElem の引数と同様に, スライスの start_index が正規化される(すなわち,負のインデックスが使用できる). 実際のスライスは,正規化された start_index に始まり, cvSliceLength 要素まで処理される(シーケンスが循環構造であると仮定していることに重ねて注意).
スライスを引数としてとらない関数でシーケンスの一部だけ処理したい場合は,関数 cvSeqSlice を用いてサブシーケンスを抽出したり,cvCvtSeqToArray で連続バッファとして保存する事で可能になる(オプションとして,続けて cvMakeSeqHeaderForArray を呼ぶ ).
CreateSeq
シーケンスを生成する
CvSeq* cvCreateSeq( int seq_flags, int header_size,
int elem_size, CvMemStorage* storage );
- seq_flags
- 生成されたシーケンスのフラグ.生成されたシーケンスが,特定のシーケンスタイプを引数にとるような関数に一切渡されない場合は,この値に0を指定してもかまわない.そうでない場合は,定義済みのシーケンスタイプのリストから適切なタイプが選択されなければならない.
- header_size
- シーケンスのヘッダサイズ.sizeof(CvSeq)以上でなければならない. また,特別なタイプかその拡張が指示されている場合,そのタイプは基本タイプのヘッダと合致していなければならない.
- elem_size
- シーケンスの要素サイズ(バイト単位).サイズはシーケンスタイプと合致しなければならない.例えば,点群のシーケンスを作成する場合,要素タイプにCV_SEQ_ELTYPE_POINTを指定し,パラメータ elem_size は sizeof(CvPoint) と等しくなければならない.
- storage
- シーケンスが保存される場所.
関数 cvCreateSeq は,シーケンスを作成し,そのポインタを返す. この関数は,シーケンスヘッダをストレージ内の連続した一つのブロックとして領域確保し, 引数として渡された値を構造体のフィールド flags,elem_size, header_size,storageに引数で渡した値をセットする. そして,delta_elems にデフォルト値(関数 cvSetSeqBlockSize で再設定できる)をセットし,その他のヘッダフィールド(先頭から sizeof(CvSeq) バイト以降のスペースも含む)をクリアする.
SetSeqBlockSize
シーケンスのブロックサイズを設定する
void cvSetSeqBlockSize( CvSeq* seq, int delta_elems );
- seq
- シーケンス.
- delta_elems
- シーケンス要素のブロックサイズ.
関数 cvSetSeqBlockSize は,メモリ確保サイズを指定する. シーケンスバッファ上の空き領域を使い果たした場合,関数は delta_elems シーケンス要素分の領域確保を行う. 確保したブロックが前のブロックの直後になる場合,二つのブロックは接続されるが,それ以外では,新しいシーケンスブロックが生成される. そのため,このパラメータを大きくすることによってシーケンスブロックの断片化は押さえられるものの, ストレージ中の多くのスペースが浪費されることになる. シーケンス生成時に,パラメータ delta_elems にはデフォルト値≈1K がセットされる. シーケンス生成後,この関数をいつでも呼ぶことができ,以降の領域確保の際にその値が使われる. この関数によって,渡されたパラメータ値をメモリストレージの制限に合わせるために変更することができる.
SeqPush
シーケンスの末尾に要素を追加する
char* cvSeqPush( CvSeq* seq, void* element=NULL );
- seq
- シーケンス.
- element
- 追加される要素.
関数 cvSeqPush は,シーケンスの末尾に要素を追加し,割り付けられた要素へのポインタを返す. 入力の element が NULL の場合,この関数は単に要素一つ分の領域を確保する.
以下のコードは,この関数を用いて新しいシーケンスを作成する方法を示す.
CvMemStorage* storage = cvCreateMemStorage(0); CvSeq* seq = cvCreateSeq( CV_32SC1, /* 整数型要素のシーケンス */ sizeof(CvSeq), /* ヘッダサイズ - 拡張フィールド無し */ sizeof(int), /* 要素サイズ */ storage /* 保存領域 */ ); int i; for( i = 0; i < 100; i++ ) { int* added = (int*)cvSeqPush( seq, &i ); printf( "%d is added¥n", *added ); } ... /* 最後にメモリストレージを解放する */ cvReleaseMemStorage( &storage );
関数 cvSeqPush の計算量はO(1)であるが,大規模なシーケンスデータの書き込みにはより高速な手法が存在する (cvStartWriteSeqと関連する関数を参照).
SeqPop
シーケンスの末尾から要素を削除する
void cvSeqPop( CvSeq* seq, void* element=NULL );
- seq
- シーケンス.
- element
- オプションパラメータ.ポインタが非0の場合,削除した要素をこの場所にコピーする.
関数 cvSeqPop はシーケンスから一つの要素を削除する.シーケンスが既に空の場合は,エラーを返す.この関数の計算量は O(1) である.
SeqPushFront
シーケンスの先頭に要素を追加する.
char* cvSeqPushFront( CvSeq* seq, void* element=NULL );
- seq
- シーケンス.
- element
- 追加される要素.
関数 cvSeqPushFront は cvSeqPush と同様であるが, 新しい要素はシーケンスの先頭に追加される.この関数の計算量は O(1) である.
SeqPopFront
シーケンスの先頭から要素を削除する
void cvSeqPopFront( CvSeq* seq, void* element=NULL );
- seq
- シーケンス.
- element
- オプションパラメータ.ポインタが非0の場合,削除要素をこの場所にコピーする.
関数 cvSeqPopFront はシーケンスの先頭から,一つの要素を削除する.シーケンスが既に空の場合は,エラーを返す.この関数の計算量は O(1) である.
SeqPushMulti
複数の要素をシーケンスのどちらかの端(先頭か末尾)に追加する
void cvSeqPushMulti( CvSeq* seq, void* elements, int count, int in_front=0 );
- seq
- シーケンス.
- elements
- 追加される要素群.
- count
- 追加される要素数.
- in_front
- 変更するシーケンスの端を指定するフラグ.
CV_BACK (=0) - 要素をシーケンスの末尾に追加する
CV_FRONT(!=0) - 要素をシーケンスの先頭に追加する
関数 cvSeqPushMulti は,複数の要素をシーケンスのどちらかの端に追加する. 要素群は入力配列中の順番どおりにシーケンスに追加されるが,違うシーケンスブロックに分割されることもある.
SeqPopMulti
複数の要素をシーケンスのどちらかの端(先頭か末尾)から削除する
void cvSeqPopMulti( CvSeq* seq, void* elements, int count, int in_front=0 );
- seq
- シーケンス.
- elements
- 削除される要素.
- count
- 削除される要素数.
- in_front
- 変更するシーケンスの端を指定するフラグ.
CV_BACK (=0) - シーケンスの末尾から要素を削除する
CV_FRONT(!=0) - シーケンスの先頭から要素を削除する
関数 cvSeqPopMulti は,複数の要素をシーケンスのどちらかの端から削除する. 削除される要素数がシーケンス中の要素数より大きい場合は,関数はできるだけ多くの要素を削除する.
SeqInsert
シーケンスの中に要素を挿入する
char* cvSeqInsert( CvSeq* seq, int before_index, void* element=NULL );
- seq
- シーケンス.
- before_index
- 要素が挿入されるインデックス(このインデックスの前に挿入される). 0(指定可能なパラメータの最小値)の前への挿入は cvSeqPushFront と同じ意味であり, seq->total(指定可能なパラメータの最大値)の前への挿入は cvSeqPush と同じ意味である.
- element
- 挿入される要素.
関数 cvSeqInsert は(elementへの)ポインタがNULLでない場合, シーケンス内の要素を指定した挿入位置から近い側のシーケンスの端にシフトし, element の内容をその位置にコピーする.この関数は,挿入された要素へのポインタを返す.
SeqRemove
シーケンスの中から要素を削除する
void cvSeqRemove( CvSeq* seq, int index );
- seq
- シーケンス.
- index
- 削除される要素のインデックス.
関数 cvSeqRemove は,与えられたインデックスをもつ要素を削除する. インデックスが範囲外の場合,この関数はエラーを発生する.空のシーケンスから要素を削除しようとすることは,この状況の一例である. この関数は,近い側のシーケンスの端とindex 番目(これは削除されない)の位置の間に存在するシーケンス要素をシフトする事によって, 要素を削除する.
ClearSeq
シーケンスをクリアする
void cvClearSeq( CvSeq* seq );
- seq
- シーケンス.
関数 cvClearSeq は,シーケンスの全ての要素をクリアする. この関数はメモリをストレージに返さないが,後で新しい要素がシーケンスに追加された時,このメモリを再利用する. この関数の時間計算量は, O(1) である..
GetSeqElem
インデックスで指定されたシーケンス要素のポインタを返す
char* cvGetSeqElem( const CvSeq* seq, int index );
#define CV_GET_SEQ_ELEM( TYPE, seq, index ) (TYPE*)cvGetSeqElem( (CvSeq*)(seq), (index) )
- seq
- シーケンス.
- index
- 要素のインデックス.
関数 cvGetSeqElem は,与えられたインデックスを持つ要素をシーケンスの中から求め,そのポインタを返す. 要素が見つからない場合,0を返す. この関数では,負のインデックスの指定も可能である.例えば,-1はシーケンスの最後の要素,-2は最後の一つ前を指す等. シーケンスが一つのシーケンスブロックで構成されているか,目的の要素が先頭のブロックにある場合は,マクロ CV_GET_SEQ_ELEM( elemType, seq, index ) を使用した方がよい.このマクロのパラメータ elemTypeはシーケンス要素のタイプ(例えば,CvPoint),seq はシーケンス, index は目的の要素のインデックスである. マクロは,先ず最初に指定された要素が先頭のブロック内にあるかどうかをチェックし,あればその位置を返し, なければマクロからメイン関数 GetSeqElem を呼び出す. 負のインデックスに対しては,常に cvGetSeqElem を呼び出す. ブロック数が要素数より非常に小さいと仮定した場合は,関数の時間計算量はO(1)になる.
SeqElemIdx
ポインタで指定されたシーケンスの要素のインデックスを返す
int cvSeqElemIdx( const CvSeq* seq, const void* element, CvSeqBlock** block=NULL );
- seq
- シーケンス.
- element
- シーケンス要素へのポインタ.
- block
- オプションの引数.NULL でない場合,要素を含むシーケンスブロックのアドレスがこの場所に保存される.
関数 cvSeqElemIdx は,指定されたシーケンス要素のインデックスを返す.その要素が存在しない場合は負の値を返す.
CvtSeqToArray
シーケンスをメモリ内の連続した一つのブロックにコピーする
void* cvCvtSeqToArray( const CvSeq* seq, void* elements, CvSlice slice=CV_WHOLE_SEQ );
- seq
- シーケンス.
- elements
- 十分に大きな領域を持つ出力配列へのポインタ.データへのポインタであり,行列のヘッダではない.
- slice
- 配列へコピーするシーケンス内の部分.
関数 cvCvtSeqToArray は,シーケンスの全体または一部を指定されたバッファにコピーし,そのバッファへのポインタを返す.
MakeSeqHeaderForArray
配列からシーケンスを生成する
CvSeq* cvMakeSeqHeaderForArray( int seq_type, int header_size, int elem_size,
void* elements, int total,
CvSeq* seq, CvSeqBlock* block );
- seq_type
- 生成するシーケンスのタイプ.
- header_size
- シーケンスヘッダのサイズ.パラメータseqは,このヘッダと同じサイズか,これより大きい構造体へのポインタを指していなければならない.
- elem_size
- シーケンス要素のサイズ.
- elements
- シーケンスを構成する要素.
- total
- シーケンス内の要素数.配列の要素数はこのパラメータ値と等しくなければならない.
- seq
- シーケンスヘッダとして用いられるローカル変数へのポインタ.
- block
- 単一シーケンスブロックのヘッダを示すローカル変数へのポインタ.
関数 cvMakeSeqHeaderForArray は,配列用にシーケンスヘッダを初期化する. シーケンスヘッダもシーケンスブロックも両方とも,ユーザによって領域確保される(例えば,スタック上に). この関数ではデータのコピーは行われない. 結果として得られるシーケンスは,単一ブロックで構成され,ストレージポインタとしてNULLを持つ. そのため,その要素を読むことは可能であるが,このシーケンスに要素を追加しようとすると,多くの場合はエラーになる.
SeqSlice
シーケンススライスのための別のヘッダを作成する
CvSeq* cvSeqSlice( const CvSeq* seq, CvSlice slice,
CvMemStorage* storage=NULL, int copy_data=0 );
- seq
- シーケンス.
- slice
- 抽出するシーケンスの一部分.
- storage
- 新しいシーケンスヘッダとコピーされたデータ(もしデータがあれば)を保存する出力ストレージ. NULLの場合,この関数は入力シーケンスに含まれるストレージを使用する.
- copy_data
- 抽出されたスライスの要素をコピーする(copy_data!=0)か,しない(copy_data=0)かを示すフラグ.
関数 cvSeqSlice は,入力シーケンスの指定したスライスに相当する新しいシーケンスを作成する. 新しいシーケンスでは,その要素を元のシーケンスと共有するか,独自でそのコピーを持つかのいずれかである. シーケンスの一部だけを処理する必要があるが,その処理関数がスライスパラメータを持たない場合に,必要なサブシーケンスをこの関数で抽出することができる.
CloneSeq
シーケンスのコピーを作成する
CvSeq* cvCloneSeq( const CvSeq* seq, CvMemStorage* storage=NULL );
- seq
- シーケンス.
- storage
- 新しいシーケンスヘッダとコピーされたデータ(もしデータがあれば)を保存する出力ストレージ. NULLの場合,入力シーケンスに含まれるストレージを使用する.
関数 cvCloneSeq は,入力シーケンスの完全なコピーを作成し,そのポインタを返す. cvCloneSeq(seq, storage)は cvSeqSlice(seq, CV_WHOLE_SEQ, storage, 1) に等しい.
SeqRemoveSlice
シーケンススライスを削除する
void cvSeqRemoveSlice( CvSeq* seq, CvSlice slice );
- seq
- シーケンス.
- slice
- 削除するシーケンスの一部分.
関数 cvSeqRemoveSlice は,指定されたシーケンスからスライスを削除する.
SeqInsertSlice
シーケンス内に配列を挿入する
void cvSeqInsertSlice( CvSeq* seq, int before_index, const CvArr* from_arr );
- seq
- シーケンス.
- slice
- 配列が挿入される場所へのインデックス(インデックスの前に挿入される).
- from_arr
- 追加される要素の配列.
関数 cvSeqInsertSlice は, from_arr 配列の全ての要素をシーケンスの指定された位置に挿入する. 配列 from_arr は,行列あるいは,他のシーケンスでもよい.
SeqInvert
シーケンス要素の順序を反転させる
void cvSeqInvert( CvSeq* seq );
- seq
- シーケンス.
関数 cvSeqInvert は,シーケンス内の順序を反転させる(先頭の要素は末尾に,末尾の要素は先頭へ,という風に).
SeqSort
シーケンスの要素を,指定した比較関数を用いてソートする
/* a < b ? -1 : a > b ? 1 : 0 */
typedef int (CV_CDECL* CvCmpFunc)(const void* a, const void* b, void* userdata);
void cvSeqSort( CvSeq* seq, CvCmpFunc func, void* userdata=NULL );
- seq
- ソートされるシーケンス
- func
- 要素の関係に応じて,負・0・正の値を返す比較関数(上記の宣言と,下の例を参照.). 最後の引数userdataが使われない事を除けば同様の関数が,Cの関数 qsort でも使われる.
- userdata
- 比較関数に渡されるユーザパラメータ.グローバル変数の使用を避けるために有効である.
関数 cvSeqSort は,指定した基準を用いてシーケンスをソートする.以下に,この関数の使用例を示す.
/* 2次元の点を上から下,左から右へソートする */ static int cmp_func( const void* _a, const void* _b, void* userdata ) { CvPoint* a = (CvPoint*)_a; CvPoint* b = (CvPoint*)_b; int y_diff = a->y - b->y; int x_diff = a->x - b->x; return y_diff ? y_diff : x_diff; } ... CvMemStorage* storage = cvCreateMemStorage(0); CvSeq* seq = cvCreateSeq( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage ); int i; for( i = 0; i < 10; i++ ) { CvPoint pt; pt.x = rand() % 1000; pt.y = rand() % 1000; cvSeqPush( seq, &pt ); } cvSeqSort( seq, cmp_func, 0 /* ここではユーザーデータは使用しない */ ); /* ソートされたデータを出力 */ for( i = 0; i < seq->total; i++ ) { CvPoint* pt = (CvPoint*)cvSeqElem( seq, i ); printf( "(%d,%d)¥n", pt->x, pt->y ); } cvReleaseMemStorage( &storage );
SeqSearch
シーケンスから指定要素を検索する
/* a < b ? -1 : a > b ? 1 : 0 */
typedef int (CV_CDECL* CvCmpFunc)(const void* a, const void* b, void* userdata);
char* cvSeqSearch( CvSeq* seq, const void* elem, CvCmpFunc func,
int is_sorted, int* elem_idx, void* userdata=NULL );
- seq
- シーケンス.
- elem
- 検索する要素.
- func
- 要素の関係に応じて,負・0・正の値を返す比較関数(cvSeqSort も参照).
- is_sorted
- シーケンスがソート済みか否かを示すフラグ.
- elem_idx
- 出力パラメータ.見つかった要素のインデックス.
- userdata
- 比較関数に渡されるユーザーパラメータ.グローバル変数の使用を避けるために有効である.
関数 cvSeqSearch はシーケンスの中から要素を検索する. シーケンスがソートされていれば,O(log(N))の二分探索法が用いられる. その他の場合は,単純な線形探索が用いられる. 要素が見つからない場合,この関数はNULLポインタを返し,インデックスにはシーケンスの要素数をセットする. 線形探索を用いて要素を見つけた場合,インデックスにはseq(i)>elemである最小のインデックスiがセットされる.
StartAppendToSeq
シーケンスへのデータ書き込み処理を初期化する
void cvStartAppendToSeq( CvSeq* seq, CvSeqWriter* writer );
- seq
- シーケンスへのポインタ.
- writer
- ライタ(Writer)の状態.この関数で初期化される.
関数 cvStartAppendToSeq は,シーケンスへのデータ書き込み処理を初期化する. 書き込まれる要素は,マクロ CV_WRITE_SEQ_ELEM(written_elem, writer) によってシーケンスの最後に追加される. 書き込み処理の間にシーケンスに対する他の処理が行われると,誤った結果が引き起こされたり,シーケンス自体が壊れる可能性があることに注意 (これらの問題を回避するには cvFlushSeqWriter の説明を参照のこと).
StartWriteSeq
新しいシーケンスを作成し,ライタ(writer)を初期化する
void cvStartWriteSeq( int seq_flags, int header_size, int elem_size,
CvMemStorage* storage, CvSeqWriter* writer );
- seq_flags
- 作成されたシーケンスのフラグ. 生成されたシーケンスが,特定のシーケンスタイプを引数にとるような関数に一切渡されない場合は,この値に0を指定してもかまわない. そうでない場合は,定義済みのシーケンスタイプのリストから適切なタイプが選択されなければならない.
- header_size
- シーケンスヘッダのサイズ.sizeof(CvSeq)以上でなければならない. また,特別なタイプか拡張が指示されている場合,そのタイプは基本タイプのヘッダサイズと合致しなければならない.
- elem_size
- シーケンスの要素サイズ(バイト単位).サイズはシーケンスタイプと合致しなければならない. 例えば,点群のシーケンス(要素タイプは CV_SEQ_ELTYPE_POINT)を作成する場合, パラメータ elem_size は sizeof(CvPoint) と等しくなければならない.
- storage
- シーケンスの位置.
- writer
- ライタの状態.この関数で初期化される.
関数 cvStartWriteSeq は,cvCreateSeq と cvStartAppendToSeq の組み合わせである. 生成されたシーケンスへのポインタは writer->seq に保存され, 最後に呼び出されるべき関数 cvEndWriteSeq から返される.
EndWriteSeq
シーケンス書き込み処理を終了する
CvSeq* cvEndWriteSeq( CvSeqWriter* writer );
- writer
- ライタの状態.
関数 cvEndWriteSeq は書き込み処理を終了し,書き込まれたシーケンスへのポインタを返す. この関数は空きブロックをメモリストレージに返すために最後の不完全なシーケンスブロックを切り捨てる. この処理によって,シーケンスは安全に読み書きできるようになる.
FlushSeqWriter
ライタの状態からシーケンスヘッダを更新する
void cvFlushSeqWriter( CvSeqWriter* writer );
- writer
- ライタの状態.
関数 cvFlushSeqWriter は,書き込みプロセス中でも要求(例えば,特定の状態をチェックするなど)があればいつでも,ユーザーがシーケンス要素を読み出せるようにする.この関数は,シーケンスからの読み出しを可能にするためにヘッダを更新する. しかし,ライタを閉じないので,いつでも書き込み処理を続けることができる. 頻繁に flush を使用するようなアルゴリズムにおいては,代わりにcvSeqPushを用いることも考慮する.
StartReadSeq
シーケンスからの連続読み出し処理を初期化する
void cvStartReadSeq( const CvSeq* seq, CvSeqReader* reader, int reverse=0 );
- seq
- シーケンス.
- reader
- リーダ(reader)の状態.この関数で初期化される.
- reverse
- シーケンス走査方向の指定.reverse が 0 の場合,リーダは先頭のシーケンス要素に位置する.それ以外は最後の要素に位置する.
関数 cvStartReadSeq は,リーダの状態を初期化する. この後,先頭から末尾までの全シーケンス要素は,続いて呼ばれるマクロCV_READ_SEQ_ELEM( read_elem, reader )(順方向読み出しの場合)あるいは, マクロ CV_REV_READ_SEQ_ELEM( read_elem, reader )(逆方向読み出しの場合)を用いて,読み出しが可能になる. どちらのマクロもシーケンス要素を read_elem にセットし,読み出しポインタを次の要素位置に移動させる. シーケンスブロックの循環構造は,読み出し処理にも適用される. これはマクロ CV_READ_SEQ_ELEM によってシーケンス末尾の要素が既に読み出された後, マクロが再度呼ばれるとシーケンス先頭の要素が読み出されるということである.CV_REV_READ_SEQ_ELEM においても同様である. 読み出し処理はシーケンスの変更もテンポラリバッファの生成もしないので,この処理を終了させる関数は存在しない. リーダ構造体のフィールド ptr は,次に読み出されるシーケンスの現在の要素を指している. 以下のコードは,シーケンスのライタとリーダの使用例である.
CvMemStorage* storage = cvCreateMemStorage(0); CvSeq* seq = cvCreateSeq( CV_32SC1, sizeof(CvSeq), sizeof(int), storage ); CvSeqWriter writer; CvSeqReader reader; int i; cvStartAppendToSeq( seq, &writer ); for( i = 0; i < 10; i++ ) { int val = rand()%100; CV_WRITE_SEQ_ELEM( val, writer ); printf("%d is written¥n", val ); } cvEndWriteSeq( &writer ); cvStartReadSeq( seq, &reader, 0 ); for( i = 0; i < seq->total; i++ ) { int val; #if 1 CV_READ_SEQ_ELEM( val, reader ); printf("%d is read¥n", val ); #else /* 代わりの方法.シーケンスの要素数が大きい場合や,コンパイル時に サイズやタイプがわからない場合はこちらの使用が望ましい */ printf("%d is read¥n", *(int*)reader.ptr ); CV_NEXT_SEQ_ELEM( seq->elem_size, reader ); #endif } ... cvReleaseStorage( &storage );
GetSeqReaderPos
現在のリーダの位置を返す
int cvGetSeqReaderPos( CvSeqReader* reader );
- reader
- リーダの状態.
関数 cvGetSeqReaderPos は,現在のリーダの位置(0 ... reader->seq->total - 1 の範囲)を返す.
SetSeqReaderPos
リーダを指定の位置に移動する
void cvSetSeqReaderPos( CvSeqReader* reader, int index, int is_relative=0 );
- reader
- リーダの状態.
- index
- 移動先の位置.位置決めモード(次のパラメータis_relativeを参照)が使用されている場合, 実際の位置は index を reader->seq->totalで割った剰余になる.
- is_relative
- 非0の場合,index は現在位置からの相対値.
関数 cvSetSeqReaderPos は,読み込み位置を絶対位置か相対位置で表された位置に移動する.