CXCORE リファレンス マニュアル
- 基本構造体(Basic Structures)
- 配列操作(Operations on Arrays)
- 動的構造体(Dynamic Structures)
- 描画関数(Drawing Functions)
- データ永続性と実行時型情報(Data Persistence and RTTI)
- その他の関数(Miscellaneous Functions)
- エラーハンドリングとシステム関数(Error Handling and System Functions)
基本構造体(Basic Structures)
CvPoint
整数座標系による2次元の点
typedef struct CvPoint
{
int x; /* x 座標.通常は0が原点 */
int y; /* y 座標.通常は0が原点 */
}
CvPoint;
/* コンストラクタ */
inline CvPoint cvPoint( int x, int y );
/* CvPoint2D32f からの変換 */
inline CvPoint cvPointFrom32f( CvPoint2D32f point );
CvPoint2D32f
浮動小数点型(単精度)座標系による2次元の点
typedef struct CvPoint2D32f
{
float x; /* x 座標.通常は0が原点 */
float y; /* y 座標.通常は0が原点 */
}
CvPoint2D32f;
/* コンストラクタ */
inline CvPoint2D32f cvPoint2D32f( double x, double y );
/* CvPoint からの変換 */
inline CvPoint2D32f cvPointTo32f( CvPoint point );
CvPoint3D32f
浮動小数点型(単精度)座標系による3次元の点
typedef struct CvPoint3D32f
{
float x; /* x 座標.通常は0が原点 */
float y; /* y 座標.通常は0が原点 */
float z; /* z 座標.通常は0が原点 */
}
CvPoint3D32f;
/* コンストラクタ */
inline CvPoint3D32f cvPoint3D32f( double x, double y, double z );
CvPoint2D64f
浮動小数点型(倍精度)座標系による2次元の点
typedef struct CvPoint2D64f
{
double x; /* x 座標.通常は0が原点 */
double y; /* y 座標.通常は0が原点 */
}
CvPoint2D64f;
/* コンストラクタ */
inline CvPoint2D64f cvPoint2D64f( double x, double y );
/* CvPoint からの変換 */
inline CvPoint2D64f cvPointTo64f( CvPoint point );
CvPoint3D64f
浮動小数点型(倍精度)座標系による3次元の点
typedef struct CvPoint3D64f
{
double x; /* x 座標.通常は0が原点 */
double y; /* y 座標.通常は0が原点 */
double z; /* z 座標.通常は0が原点 */
}
CvPoint3D64f;
/* コンストラクタ */
inline CvPoint3D64f cvPoint3D64f( double x, double y, double z );
CvSize
矩形のピクセル精度でのサイズ
typedef struct CvSize
{
int width; /* 矩形の幅 */
int height; /* 矩形の高さ */
}
CvSize;
/* コンストラクタ */
inline CvSize cvSize( int width, int height );
CvSize2D32f
矩形のサブピクセル精度でのサイズ
typedef struct CvSize2D32f
{
float width; /* 矩形の幅 */
float height; /* 矩形の高さ */
}
CvSize2D32f;
/* コンストラクタ */
inline CvSize2D32f cvSize2D32f( double width, double height );
CvRect
矩形のオフセットとサイズ
typedef struct CvRect
{
int x; /* 矩形の左角の x 座標 */
int y; /* 矩形の上角(あるいは下角)の y 座標 */
int width; /* 矩形の幅 */
int height; /* 矩形の高さ */
}
CvRect;
/* コンストラクタ */
inline CvRect cvRect( int x, int y, int width, int height );
CvScalar
4個までの数を納めるコンテナ
typedef struct CvScalar
{
double val[4];
}
CvScalar;
/* コンストラクタ:val[0] を val0 で初期化.val[1] を val1 で初期化.… */
inline CvScalar cvScalar( double val0, double val1=0,
double val2=0, double val3=0 );
/* コンストラクタ:val[0]...val[3] を val0123 で初期化 */
inline CvScalar cvScalarAll( double val0123 );
/* コンストラクタ:val[0] を val0 で初期化.val[1]...val[3] を 0 で初期化 */
inline CvScalar cvRealScalar( double val0 );
CvTermCriteria
反復アルゴリズムのための終了条件
#define CV_TERMCRIT_ITER 1
#define CV_TERMCRIT_NUMBER CV_TERMCRIT_ITER
#define CV_TERMCRIT_EPS 2
typedef struct CvTermCriteria
{
int type; /* CV_TERMCRIT_ITER と CV_TERMCRIT_EPS の組合せ */
int max_iter; /* 反復数の最大値 */
double epsilon; /* 目標精度 */
}
CvTermCriteria;
/* コンストラクタ */
inline CvTermCriteria cvTermCriteria( int type, int max_iter, double epsilon );
/* 終了条件をチェックし,type=CV_TERMCRIT_ITER+CV_TERMCRIT_EPS に設定し,
反復数の max_iterとeprilon の両方が有効になるように変換する */
CvTermCriteria cvCheckTermCriteria( CvTermCriteria criteria,
double default_eps,
int default_max_iters );
CvMat
多重行列
typedef struct CvMat
{
int type; /* CvMat シグネチャ (CV_MAT_MAGIC_VAL).要素の型とフラグ */
int step; /* 全行のバイト長 */
int* refcount; /* 内部的に利用されるデータ参照カウンタ */
union
{
uchar* ptr;
short* s;
int* i;
float* fl;
double* db;
} data; /* データポインタ */
#ifdef __cplusplus
union
{
int rows;
int height;
};
union
{
int cols;
int width;
};
#else
int rows; /* 行の数 */
int cols; /* 列の数 */
#endif
} CvMat;
CvMatND
多次元,多チャンネルの密な行列
typedef struct CvMatND
{
int type; /* CvMatND シグネチャ (CV_MATND_MAGIC_VAL).要素の型とフラグ */
int dims; /* 配列の次元数 */
int* refcount; /* 内部的に利用されるデータ参照カウンタ */
union
{
uchar* ptr;
short* s;
int* i;
float* fl;
double* db;
} data; /* データポインタ */
/* 各次元での(要素数,要素間のバイト距離)の組 */
struct
{
int size;
int step;
}
dim[CV_MAX_DIM];
} CvMatND;
CvSparseMat
多次元,多チャンネルの疎な行列
typedef struct CvSparseMat
{
int type; /* CvSparseMat シグネチャ(CV_SPARSE_MAT_MAGIC_VAL).要素の型とフラグ */
int dims; /* 次元数 */
int* refcount; /* 参照カウンタ - 使用されない */
struct CvSet* heap; /* ハッシュテーブルノードの保存領域(プール) */
void** hashtable; /* ハッシュテーブル:各エントリは,同じ「hashvalue の hashsize を法とする剰余」
をノードのリストとして持つ */
int hashsize; /* ハッシュテーブルのサイズ */
int total; /* 粗な配列ノードの総数 */
int valoffset; /* 配列ノードの値のオフセット(バイト単位) */
int idxoffset; /* 配列ノードのインデックスのオフセット(バイト単位) */
int size[CV_MAX_DIM]; /* 次元サイズの配列 */
} CvSparseMat;
IplImage
IPL 画像ヘッダ
typedef struct _IplImage
{
int nSize; /* sizeof(IplImage) */
int ID; /* バージョン (=0)*/
int nChannels; /* OpenCV のほとんどの関数が,1,2,3および4チャンネルをサポートする */
int alphaChannel; /* OpenCV では無視される */
int depth; /* ピクセルの色深度のビット数:
IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,
IPL_DEPTH_16S, IPL_DEPTH_32S,
IPL_DEPTH_32F, IPL_DEPTH_64F がサポートされる */
char colorModel[4]; /* OpenCV では無視される */
char channelSeq[4]; /* 同上 */
int dataOrder; /* 0 - インタリーブカラーチャンネル.1 - 分離カラーチャンネル,
cvCreateImage が作成できるのは,インタリーブ画像のみ.*/
int origin; /* 0 - 左上原点,
1 - 左下原点(Windowsのビットマップ形式) */
int align; /* 画像の行のアライメント(4 あるいは 8).
OpenCV はこれを無視して,代わりに widthStep を使用する. */
int width; /* 画像のピクセル幅 */
int height; /* 画像のピクセル高さ */
struct _IplROI *roi;/* 画像 ROI.これが NULL でない場合,この特定の領域が処理の対象となる */
struct _IplImage *maskROI; /* OpenCV では必ずNULL */
void *imageId; /* 同上 */
struct _IplTileInfo *tileInfo; /* 同上 */
int imageSize; /* 画像データのバイトサイズ
(インタリーブデータの場合は,=image->height*image->widthStep) */
char *imageData; /* アライメントが調整された画像データへのポインタ */
int widthStep; /* アライメントが調整された画像の行のバイトサイズ */
int BorderMode[4]; /* 画像境界の設定.OpenCV では無視される */
int BorderConst[4]; /* 同上 */
char *imageDataOrigin; /* オリジナル画像データへのポインタ
(アライメントが調整されているとは限らない)
- これは画像を正しく解放するために必要. */
}
IplImage;
IplImage 構造体は元々,Intel Image Processing Library 固有のものであった. OpenCVでは IplImage フォーマットの一部のみをサポートしている.
- alphaChannel はOpenCVでは無視される.
- colorModel と channelSeq はOpenCV では無視される. OpenCV の色空間を変換する関数cvCvtColor は,変換元と変換先の色空間をパラメータとする.
- dataOrder は IPL_DATA_ORDER_PIXEL でなければならない(色チャンネルはインタリーブされる). しかし,COI(channel of interest)が設定されている場合,そのチャンネルが処理の対象となる.
- align はOpenCV では無視され,画像の行方向への連続的なアクセスに widthStep が利用される.
- maskROI はサポートされない.マスクを利用する関数は,それを別のパラメータとして扱う. OpenCV ではマスクも 8 ビットであるが,IPL では 1 ビットとなっている.
- tileInfo はサポートされない.
- BorderMode と BorderConst はサポートされない. OpenCV の各関数は,予め決められた一つの境界設定(多くの場合は,複製境界モード)で近傍のピクセルを処理する.
CvArr
任意の配列
typedef void CvArr;
メタ型 CvArr* は,1種類以上の配列(例えば IplImage*,CvMat*,CvSeq*など)を引数にとる関数を記述するための仮引数としてのみ利用される. 個々の配列型は,実行時にヘッダの最初の4バイトを分析することで決定される.
配列操作(Operations on Arrays)
初期化(Initialization)
CreateImage
ヘッダの作成とデータ領域の確保
IplImage* cvCreateImage( CvSize size, int depth, int channels );
- size
- 画像の幅と高さ.
- depth
- 画像要素のビットデプス.以下の内のいずれか.
IPL_DEPTH_8U - 符号無し 8 ビット整数
IPL_DEPTH_8S - 符号有り 8 ビット整数
IPL_DEPTH_16U - 符号無し 16 ビット整数
IPL_DEPTH_16S - 符号有り 16 ビット整数
IPL_DEPTH_32S - 符号有り 32 ビット整数
IPL_DEPTH_32F - 単精度浮動小数点数
IPL_DEPTH_64F - 倍精度浮動小数点数
- channels
- 要素(ピクセル)毎のチャンネル数.1, 2, 3, 4 のいずれか.このチャンネルはインタリーブされる.例えば,通常のカラー画像のデータレイアウトは,
b0 g0 r0 b1 g1 r1 ...
となっている.一般的な IPL 画像フォーマットはノンインタリーブ画像を格納することができ,これを処理することができる OpenCV の関数も存在するが,この関数はインタリーブ画像しか作成できない.
関数 cvCreateImage はヘッダを作成し,データ領域を確保する.これは,以下の形式を短縮したものである.
header = cvCreateImageHeader(size,depth,channels);
cvCreateData(header);
CreateImageHeader
メモリ確保と初期化を行い,IplImage 構造体を返す
IplImage* cvCreateImageHeader( CvSize size, int depth, int channels );
- size
- 画像の幅と高さ.
- depth
- 画像のカラーデプス(CreateImage を参照).
- channels
- チャンネル数(CreateImage を参照).
関数 cvCreateImageHeader は,メモリ確保と初期化を行い, IplImage 構造体を返す.これは,
iplCreateImageHeader( channels, 0, depth,
channels == 1 ? "GRAY" : "RGB",
channels == 1 ? "GRAY" : channels == 3 ? "BGR" :
channels == 4 ? "BGRA" : "",
IPL_DATA_ORDER_PIXEL, IPL_ORIGIN_TL, 4,
size.width, size.height,
0,0,0,0);
と似ているが,この関数はデフォルトでは IPL の関数を用いない(マクロ CV_TURN_ON_IPL_COMPATIBILITY も参照すること).
ReleaseImageHeader
ヘッダを解放する
void cvReleaseImageHeader( IplImage** image );
- image
- 確保したヘッダへのポインタのポインタ.
関数 cvReleaseImageHeader は,ヘッダを解放する.これは,
if( image )
{
iplDeallocate( *image, IPL_IMAGE_HEADER | IPL_IMAGE_ROI );
*image = 0;
}
と似ているが,この関数はデフォルトでは IPL の関数を用いない(マクロ CV_TURN_ON_IPL_COMPATIBILITY も参照すること).
ReleaseImage
ヘッダと画像データを解放する
void cvReleaseImage( IplImage** image );
- image
- 確保した画像ヘッダへのポインタのポインタ.
関数 cvReleaseImage は,ヘッダと画像データを解放する. これは,以下の形式を短縮したものである.
if( *image )
{
cvReleaseData( *image );
cvReleaseImageHeader( image );
}
InitImageHeader
ユーザによって確保された画像ヘッダを初期化する
IplImage* cvInitImageHeader( IplImage* image, CvSize size, int depth,
int channels, int origin=0, int align=4 );
- image
- 初期化される画像ヘッダ.
- size
- 画像の幅と高さ.
- depth
- 画像のカラーデプス(CreateImage を参照).
- channels
- チャンネル数(CreateImage を参照).
- origin
- IPL_ORIGIN_TL または IPL_ORIGIN_BL.
- align
- 画像の行のアライメント,通常は4,あるいは 8 バイト.
関数 cvInitImageHeader は, ユーザから渡されたポインタが指す画像のヘッダ構造体を初期化し,そのポインタを返す.
CloneImage
画像の完全なコピーを作成する
IplImage* cvCloneImage( const IplImage* image );
- image
- オリジナル画像.
関数 cvCloneImage は,ヘッダ,ROI,データを含む画像の完全なコピー を作成する.
SetImageCOI
与えられた値を channel of interest(COI)としてセットする
void cvSetImageCOI( IplImage* image, int coi );
- image
- 画像ヘッダ.
- coi
- COI(Channel of interest).
関数 cvSetImageCOI は,与えられた値を COI(channel of interest)としてセットする. 値 0 は全てのチャンネルが選択されている事を意味し,値 1 は最初のチャンネルが選択されている事を意味する. もしCOI が NULL かつ,パラメータが coi != 0 の場合には,COI が確保される. OpenCV の関数の多くは COI をサポートしていないことに注意すること. 別々の画像/行列チャンネルを処理するには,(cvCopy や cvSplit によって)別々の画像/行列へチャンネルをコピーし, それを処理してから,必要ならばその結果を(cvCopy や cvCvtPlaneToPix によって)もう一度コピーし直して返す.
GetImageCOI
COI のインデックスを戻す
int cvGetImageCOI( const IplImage* image );
- image
- 画像ヘッダ.
関数 cvGetImageCOI は,画像の COI(channel of interest)を返す(全チャンネルが選択される場合には,0 が返される).
SetImageROI
与えられた矩形を画像の ROI としてセットする
void cvSetImageROI( IplImage* image, CvRect rect );
- image
- 画像ヘッダ.
- rect
- ROI を表す矩形.
関数 cvSetImageROI は,与えられた矩形を画像の ROI としてセットする. もし,ROI が NULL で,パラメータ rect の値が画像全体ではない場合には,ROI が確保される. COI とは異なり,OpenCV の関数の多くが ROI をサポートしている. そして,ROI はある意味,別の画像として扱われる(例えば,全てのピクセル座標は ROI の左上あるいは左下(画像の原点に依存)からカウントされる).
ResetImageROI
画像の ROI を解放する
void cvResetImageROI( IplImage* image );
- image
- 画像ヘッダ.
関数 cvResetImageROI は,画像の ROI を解放する. 解放後は全画像が選択されている状態と同じになる. 以下のようにしても,同じように全選択ができるが,この方法では image->roi は解放されない.
cvSetImageROI( image, cvRect( 0, 0, image->width, image->height )); cvSetImageCOI( image, 0 );
GetImageROI
画像の ROI 座標を返す
CvRect cvGetImageROI( const IplImage* image );
- image
- 画像ヘッダ.
関数 cvGetImageROI は,画像の ROI 座標を返す. ROI が存在しない場合には,矩形 cvRect(0,0,image->width,image->height) が返される.
CreateMat
新たな行列を作成する
CvMat* cvCreateMat( int rows, int cols, int type );
- rows
- 行列の行数.
- cols
- 行列の列数.
- type
- 行列要素の種類.通常,次のような指定形式になる.
CV_<bit_depth>(S|U|F)C<number_of_channels>.例えば,
CV_8UC1 は,符号無し 8 ビット 1 チャンネル行列, CV_32SC2 は,符号有り 32 ビット 2 チャンネル行列を意味する.
関数 cvCreateMat は,新たな行列とその内部データのためのヘッダを確保し,作成された行列へのポインタを返す.これは以下の省略形である.
CvMat* mat = cvCreateMatHeader( rows, cols, type );
cvCreateData( mat );
行列は行単位で保存され,すべての行は4バイトでアライメントされる.
CreateMatHeader
新たな行列のヘッダを作成する
CvMat* cvCreateMatHeader( int rows, int cols, int type );
- rows
- 行列の行数.
- cols
- 行列の列数.
- type
- 行列要素の種類(cvCreateMatを参照).
関数 cvCreateMatHeaderは,新たな行列のヘッダを作成し,そのポインタを返す. さらに,cvCreateData を用いるか,cvSetData により,ユーザが確保したデータ領域を明示的にセットすることで,行列データが確保される.
ReleaseMat
行列を解放する
void cvReleaseMat( CvMat** mat );
- mat
- 行列へのポインタのポインタ.
関数 cvReleaseMat は,行列データの参照カウンタをデクリメントして,行列ヘッダを解放する.
if( *mat )
cvDecRefData( *mat );
cvFree( (void**)mat );
InitMatHeader
行列ヘッダを初期化する
CvMat* cvInitMatHeader( CvMat* mat, int rows, int cols, int type,
void* data=NULL, int step=CV_AUTOSTEP );
- mat
- 初期化する行列のヘッダへのポインタ.
- rows
- 行列の行数.
- cols
- 行列の列数.
- type
- 行列要素の種類.
- data
- 行列のヘッダで指定されるデータへのポインタ(オプション).
- step
- 割り当てられたデータの行長をバイト単位で表す. デフォルトでは,stepには可能な限り小さい値が用いられる.つまり,行列の連続する行間にギャップが存在しない.
関数 cvInitMatHeader は,既に確保された構造体 CvMat を初期化する. これは,OpenCV の行列関数で生データを処理するために用いることもできる.
例えば,以下のコードは二つの行列の積を計算し,通常の行列として格納する.
二つの行列の積の計算
double a[] = { 1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12 };
double b[] = { 1, 5, 9,
2, 6, 10,
3, 7, 11,
4, 8, 12 };
double c[9];
CvMat Ma, Mb, Mc ;
cvInitMatHeader( &Ma, 3, 4, CV_64FC1, a );
cvInitMatHeader( &Mb, 4, 3, CV_64FC1, b );
cvInitMatHeader( &Mc, 3, 3, CV_64FC1, c );
cvMatMulAdd( &Ma, &Mb, 0, &Mc );
// この行列 c には,行列 a(3×4) と 行列 b(4×3) の積が入っている
Mat
行列ヘッダを初期化する(軽量版)
CvMat cvMat( int rows, int cols, int type, void* data=NULL );
- rows
- 行列の行数.
- cols
- 行列の列数.
- type
- 行列要素の種類(CreateMat を参照).
- data
- 行列のヘッダで指定されるデータへのポインタ(オプション).
関数 cvMat は, cvInitMatHeader の高速なインライン置換である.つまり,これは以下と等価である.
CvMat mat;
cvInitMatHeader( &mat, rows, cols, type, data, CV_AUTOSTEP );
CloneMat
行列のコピーを作成する
CvMat* cvCloneMat( const CvMat* mat );
- mat
- 入力行列.
関数 cvCloneMat は,入力行列のコピーを作成し,そのポインタを返す.
CreateMatND
多次元の密な配列を作成する
CvMatND* cvCreateMatND( int dims, const int* sizes, int type );
- dims
- 配列の次元数.CV_MAX_DIM(デフォルトでは32.ビルド時に変更される可能性もある)を超えてはいけない.
- sizes
- 次元サイズの配列.
- type
- 配列要素の種類.CvMat のものと同じ.
関数 cvCreateMatND は,多次元の密な配列のヘッダとその内部データを確保し,作成された配列のポインタを返す. これは以下の省略形である.
CvMatND* mat = cvCreateMatNDHeader( dims, sizes, type );
cvCreateData( mat );
配列データは行単位で保存される.全ての行は4バイトでアライメントされる.
CreateMatNDHeader
新たな行列のヘッダを作成する
CvMatND* cvCreateMatNDHeader( int dims, const int* sizes, int type );
- dims
- 配列の次元数.
- sizes
- 次元サイズの配列.
- type
- 配列要素の種類.CvMat のものと同じ.
関数 cvCreateMatND は,多次元の密な配列のヘッダを確保する. さらに,cvCreateData を用いるか, cvSetData により,ユーザが確保したデータ領域を明示的にセットすることで,配列データが確保される.
ReleaseMatND
多次元配列を解放する
void cvReleaseMatND( CvMatND** mat );
- mat
- 配列へのポインタのポインタ.
関数 cvReleaseMatND は,配列データの参照カウンタをデクリメントして,配列ヘッダを解放する.
if( *mat )
cvDecRefData( *mat );
cvFree( (void**)mat );
InitMatNDHeader
多次元配列のヘッダを初期化する
CvMatND* cvInitMatNDHeader( CvMatND* mat, int dims, const int* sizes, int type, void* data=NULL );
- mat
- 初期化する配列のヘッダへのポインタ.
- dims
- 配列の次元数.
- sizes
- 次元サイズの配列.
- type
- 配列要素の種類.CvMat のものと同じ.
- data
- 行列のヘッダで指定されるデータへのポインタ(オプション).
関数 cvInitMatNDHeader は,ユーザによって確保された構造体 CvMatND を初期化する.
CloneMatND
多次元配列の完全なコピーを作成する
CvMatND* cvCloneMatND( const CvMatND* mat );
- mat
- 入力配列.
関数 cvCloneMatND は,入力配列のコピーを作成し,そのポインタを返す.
DecRefData
配列データの参照カウンタをデクリメントする
void cvDecRefData( CvArr* arr );
- arr
- 配列ヘッダ.
関数 cvDecRefData は, 参照カウンタのポインタが NULL ではない場合に
CvMat あるいは CvMatND のデータの参照カウンタをデクリメントし,
さらにカウンタが 0 になった場合にはデータを解放する.
現在の実装では,データが関数 cvCreateData によって確保された場合にのみ,
参照カウンタは NULL ではなくなる. その他の場合として,以下のものがある.
cvSetData によって,外部データがヘッダに割り当てられた.
行列ヘッダが,より大きな行列あるいは画像の一部になっている.
行列ヘッダが,画像あるいは n 次元行列ヘッダから変換された.
このような場合,参照カウンタは NULL にセットされ,デクリメントされない.
データが解放されるか否かに関わらず,データポインタと参照カウンタポインタはこの関数によってクリアされる.
IncRefData
配列データの参照カウンタをインクリメントする
int cvIncRefData( CvArr* arr );
- arr
- 配列ヘッダ.
関数 cvIncRefData は, 参照カウンタポインタが NULL ではない場合に, CvMat あるいは CvMatND のデータの参照カウンタをインクリメントし,新たなカウンタ値を返す. そうでない場合は 0 を返す.
CreateData
配列データを確保する
void cvCreateData( CvArr* arr );
- arr
- 配列ヘッダ.
関数 cvCreateData は,画像,行列あるいは多次元配列のデータを確保する. 行列の場合は OpenCV の確保関数が用いられる.IplImage の場合も OpenCV の関数が用いられる. ただし,CV_TURN_ON_IPL_COMPATIBILITY が呼ばれた場合は例外的に,データを確保するために IPL 関数が用いられる.
ReleaseData
配列データを解放する
void cvReleaseData( CvArr* arr );
- arr
- 配列ヘッダ.
関数 cvReleaseData は,配列データを解放する. CvMat あるいは CvMatND の場合, これは単に cvDecRefData() を呼ぶだけである.つまり,この関数は外部データを解放することができない. cvCreateData の注意事項も参照すること.
SetData
ユーザデータを配列ヘッダに割り当てる
void cvSetData( CvArr* arr, void* data, int step );
- arr
- 配列ヘッダ.
- data
- ユーザデータ.
- step
- バイト単位で表された行の長さ.
関数 cvSetData は,ユーザデータを配列のヘッダに割り当てる. ヘッダは,関数 cvCreate*Header,関数 cvInit*Header あるいは 関数 cvMat(行列の場合)を用いて,あらかじめ初期化されるべきである.
GetRawData
配列の低レベル情報を取り出す
void cvGetRawData( const CvArr* arr, uchar** data,
int* step=NULL, CvSize* roi_size=NULL );
- arr
- 配列ヘッダ.
- data
- 出力である全画像の原点へのポインタ,あるいは ROI が設定されている場合は ROI の原点へのポインタ.
- step
- 出力であるバイト単位で表された行の長さ.
- roi_size
- 出力であるROI サイズ.
関数 cvGetRawData は,配列データに関する低レベル情報を変数に出力する. すべての出力パラメータは任意であり,いくつかのポインタは NULL にセットされる場合がある. 配列が ROI をもつ IplImage である場合,ROI のパラメータが返される.
以下に,この関数を用いて配列の要素にアクセスする例を示す.
GetRawData を用いて,シングルチャンネル浮動小数点型数配列の要素の絶対値を計算する.
float* data;
int step;
CvSize size;
int x, y;
cvGetRawData( array, (uchar**)&data, &step, &size );
step /= sizeof(data[0]);
for( y = 0; y < size.height; y++, data += step )
for( x = 0; x < size.width; x++ )
data[x] = (float)fabs(data[x]);
GetMat
任意の配列に対する行列ヘッダを返す
CvMat* cvGetMat( const CvArr* arr, CvMat* header, int* coi=NULL, int allowND=0 );
- arr
- 入力配列.
- header
- テンポラリバッファとして用いられる構造体 CvMat へのポインタ.
- coi
- COIを記憶するための,オプションの出力パラメータ.
- allowND
- これが 0 でない場合,この関数は多次元の密な配列(CvMatND*)を扱うことが可能で, 2次元行列(CvMatND が2次元の場合)あるいは 1次元行列(CvMatNDが 1次元,あるいは 2次元より大きい場合)を返す. 配列は連続でなければならない.
関数 cvGetMat は,入力配列に対する行列ヘッダを返す. 入力配列になり得るものは,行列 - CvMat,画像 - IplImage あるいは,多次元の密な配列 - CvMatND*(最後の例は,allowND != 0 の場合のみ)である. 行列の場合,この関数は単に入力ポインタを返す. IplImage* あるいは CvMatND* の場合は, 現在の画像の ROI のパラメータで構造体 header を初期化し,このテンポラリ構造体へのポインタを返す. COI は CvMat ではサポートされないので,これは別に返される.
この関数は,同じコードで 2種類の配列 - IplImage および CvMat - を扱う簡単な方法を提供する. 関数 cvGetImage によって,CvMat から IplImage への逆変換が可能である.
入力配列は,確保あるいは添付された内部データを持たなければならず,そうでない場合は,この関数は失敗する.
入力配列が,平面(二次元)データレイアウトおよび COI を持つ IplImage の場合, この関数は選択された平面へのポインタおよび COI = 0 を返す. OpenCV の関数を用いて,平面データレイアウトを持つマルチチャンネル画像を平面毎に処理する事が可能である.GetImage
任意の配列に対する画像ヘッダを返す
IplImage* cvGetImage( const CvArr* arr, IplImage* image_header );
- arr
- 入力配列.
- image_header
- テンポラリバッファとして用いられる構造体 IplImage へのポインタ.
関数 cvGetImage は,入力配列, 行列 - CvMat*,画像 - IplImage*,に対する画像ヘッダを返す. 画像の場合は,この関数は単に入力ポインタを返す.CvMat* の場合は,入力行列のパラメータで構造体 image_header を初期化する. ROI がセットされている場合,IplImage から CvMat へ変換した後に,その CvMat から IplImage に戻すと,異なったヘッダになる可能性がある. 従って,画像の長さをその幅とアライメントから計算するような IPL 関数は,この関数の結果として得られる画像に対しては失敗する可能性がある.
CreateSparseMat
疎な配列を作成する
CvSparseMat* cvCreateSparseMat( int dims, const int* sizes, int type );
- dims
- 配列の次元数.密な行列とは逆に,次元数は実質的には無制限である(216 まで).
- sizes
- 次元サイズの配列.
- type
- 配列要素の種類.CvMat のものと同じ.
関数 cvCreateSparseMat は,多次元の疎な配列を確保する. 初期状態では配列は要素を持たない. つまり,cvGet*D あるいは cvGetReal*D は, 全インデックスに対して 0 を返す.
ReleaseSparseMat
疎な配列を解放する
void cvReleaseSparseMat( CvSparseMat** mat );
- mat
- 配列へのポインタのポインタ.
関数 cvReleaseSparseMat は,疎な配列を解放し,終了時に配列ポインタをクリアする.
CloneSparseMat
疎な配列の完全なコピーを作成する
CvSparseMat* cvCloneSparseMat( const CvSparseMat* mat );
- mat
- 入力配列.
関数 cvCloneSparseMat は,入力配列のコピーを作成し,そのポインタを返す.
要素へのアクセスと部分配列(Accessing Elements and sub-Arrays)
GetSubRect
入力画像または行列の矩形部分配列に相当するヘッダを返す
CvMat* cvGetSubRect( const CvArr* arr, CvMat* submat, CvRect rect );
- arr
- 入力配列.
- submat
- 結果として得られる部分配列のヘッダへのポインタ.
- rect
- 着目する矩形領域の,0 を基準とした座標.
関数 cvGetSubRectは,入力配列中の指定した矩形領域に相当するヘッダを返す. つまり,入力配列の一部の矩形領域を,独立した配列として扱えるようにする. この関数では ROI を考慮し,実際には ROI の部分配列が取り出される.
GetRow, GetRows
配列中の1行または,指定された範囲の行(複数行)を返す
CvMat* cvGetRow( const CvArr* arr, CvMat* submat, int row ); CvMat* cvGetRows( const CvArr* arr, CvMat* submat, int start_row, int end_row, int delta_row=1 );
- arr
- 入力配列.
- submat
- 結果として得られる部分配列のヘッダへのポインタ.
- row
- 選択した行の,0を基準としたインデックス.
- start_row
- 範囲の最初の(この値を含む)行の,0を基準としたインデックス.
- end_row
- 範囲の最後の(この値を含まない)行の,0を基準としたインデックス.
- delta_row
- 行の範囲のインデックス間隔. この関数は,start_rowからend_row(は含まない)まで,delta_row毎に行を抽出する.
関数GetRowとGetRowsは,入力配列中の指定した1行,あるいは範囲の複数行に相当するヘッダを返す.注釈:GetRowはcvGetRowsのショートカットである.
cvGetRow( arr, submat, row ); // ~ cvGetRows( arr, submat, row, row + 1, 1 );
GetCol, GetCols
配列中の1列または,指定された範囲の列(複数列)を返す
CvMat* cvGetCol( const CvArr* arr, CvMat* submat, int col ); CvMat* cvGetCols( const CvArr* arr, CvMat* submat, int start_col, int end_col );
- arr
- 入力配列.
- submat
- 結果として得られる部分配列のヘッダへのポインタ.
- col
- 選択した列の,0を基準としたインデックス.
- start_col
- 範囲の最初の(この値を含む)列の,0を基準としたインデックス
- end_col
- 範囲の最後の(この値を含まない)列の,0を基準としたインデックス.
関数GetColとGetColsは入力配列中の指定した1列,あるいは範囲の複数列に相当するヘッダを返す.注釈:GetColはcvGetColsのショートカットである.
cvGetCol( arr, submat, col ); // ~ cvGetCols( arr, submat, col, col + 1 );
GetDiag
配列の対角列の一つを返す
CvMat* cvGetDiag( const CvArr* arr, CvMat* submat, int diag=0 );
- arr
- 入力配列.
- submat
- 結果として得られる部分配列のヘッダへのポインタ.
- diag
- 対角配列.0はメインの対角列に対応し,-1はメイン対角列の一つ上の斜め列,1はメイン対角列の一つ下の斜め列,という様に対応する.
関数cvGetDiagは,入力配列中の指定された対角列に相当するヘッダを返す.
GetSize
行列または画像の ROI のサイズを返す
CvSize cvGetSize( const CvArr* arr );
- arr
- 配列のヘッダ.
関数cvGetSizeは,入力行列または画像の行数(CvSize::height)と列数(CvSize::width)を返す.画像の場合は ROI のサイズが返される.
InitSparseMatIterator
疎な配列要素のイテレータを初期化する
CvSparseNode* cvInitSparseMatIterator( const CvSparseMat* mat,
CvSparseMatIterator* mat_iterator );
- mat
- 入力配列.
- mat_iterator
- 初期化されるイテレータ.
関数cvInitSparseMatIteratorは,疎な配列要素のイテレータを初期化し,先頭要素へのポインタを返す.配列が空の時はNULLを返す.
GetNextSparseNode
疎な配列において次の要素のポインタを返す
CvSparseNode* cvGetNextSparseNode( CvSparseMatIterator* mat_iterator );
- mat_iterator
- 疎な配列のイテレータ.
関数cvGetNextSparseNodeは,イテレータを次の疎な行列要素へ動かし,そこへのポインタを返す. 現在のバージョンでは,個々の要素はハッシュテーブルに保存されているので,それらに特別な順番はない. 疎な行列内をどのように繰り返し処理していくかを,以下のサンプルに示す.
cvInitSparseMatIterator と cvGetNextSparseNode を用いた疎な浮動小数点型配列の総和計算.
double sum;
int i, dims = cvGetDims( array );
CvSparseMatIterator mat_iterator;
CvSparseNode* node = cvInitSparseMatIterator( array, &mat_iterator );
for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))
{
/* 要素インデックスへのポインタを取得 */
const int* idx = CV_NODE_IDX( array, node );
/* 要素値の取得(タイプがCV_32FC1であると仮定) */
float val = *(float*)CV_NODE_VAL( array, node );
printf( "(" );
for( i = 0; i < dims; i++ )
printf( "%4d%s", idx[i], i < dims - 1 "," : "): " );
printf( "%g¥n", val );
sum += val;
}
printf( "¥nTotal sum = %g¥n", sum );
GetElemType
配列要素のタイプを返す
int cvGetElemType( const CvArr* arr );
- arr
- 入力配列.
関数GetElemTypeは,cvCreateMatの説明に述べられている以下のような配列要素のタイプを返す.
CV_8UC1 ... CV_64FC4
GetDims, GetDimSize
配列の次元数とそれらのサイズ,または特定の次元のサイズを返す
int cvGetDims( const CvArr* arr, int* sizes=NULL ); int cvGetDimSize( const CvArr* arr, int index );
- arr
- 入力配列.
- sizes
- 配列の次元の大きさを示すオプションの出力ベクトル.2次元配列の場合は1番目に行数(高さ),次は列数(幅)を示す.
- index
- 0を基準にした次元のインデックス(行列では0は行数,1は列数を示す.画像では0は高さ, 1は幅を示す).
関数cvGetDimsは配列の次元とそれらのサイズを返す. IplImageまたは CvMatの場合には,画像や行列の行数に関係なく常に 2 を返す. 関数cvGetDimSizeは特定の次元のサイズ(指定された次元の要素数)を返す.例えば,次のコードは配列要素の数を計算する2つの方法である.
// cvGetDims()を用いる方法
int sizes[CV_MAX_DIM];
int i, total = 1;
int dims = cvGetDims( arr, size );
for( i = 0; i < dims; i++ )
total *= sizes[i];
// cvGetDims() と cvGetDimSize() を用いる方法
int i, total = 1;
int dims = cvGetDims( arr );
for( i = 0; i < dims; i++ )
total *= cvGetDimsSize( arr, i );
Ptr*D
特定の配列要素へのポインタを返す
uchar* cvPtr1D( const CvArr* arr, int idx0, int* type=NULL ); uchar* cvPtr2D( const CvArr* arr, int idx0, int idx1, int* type=NULL ); uchar* cvPtr3D( const CvArr* arr, int idx0, int idx1, int idx2, int* type=NULL ); uchar* cvPtrND( const CvArr* arr, const int* idx, int* type=NULL, int create_node=1, unsigned* precalc_hashval=NULL );
- arr
- 入力配列.
- idx0
- 要素インデックスの,0を基準とした第1成分.
- idx1
- 要素インデックスの,0を基準とした第2成分.
- idx2
- 要素インデックスの,0を基準とした第3成分.
- idx
- 要素インデックスの配列.
- type
- オプションの出力パラメータ.行列要素のタイプ.
- create_node
- 疎な行列に対するオプションの入力パラメータ.非0の場合,指定された要素が存在しないときは要素を生成する.
- precalc_hashval
- 疎な行列に対するオプションの入力パラメータ.ポインタがNULLでないとき,関数はノードのハッシュ値を再計算せず,指定された場所から取ってくる. これにより,ペアワイズ操作の速度が向上する.
関数cvPtr*Dは,特定の配列要素へのポインタを返す.1次元からN次元までの密な配列への連続的なアクセスに用いられる関数cvPtr1Dの場合を除いて,配列の次元数は関数の引き数として渡されるインデックスの数と一致しなければならない.
同様に,この関数は,疎な配列に対しても用いられる.指定したノードが存在しない場合,関数はそれを生成し,0をセットする.
配列要素にアクセスするその他の関数(cvGet*D, cvGetReal*D, cvSet*D, cvSetReal*D)も同様であるが,要素のインデックスが範囲外であれば,エラーが起こる.
Get*D
特定の配列要素を返す
CvScalar cvGet1D( const CvArr* arr, int idx0 ); CvScalar cvGet2D( const CvArr* arr, int idx0, int idx1 ); CvScalar cvGet3D( const CvArr* arr, int idx0, int idx1, int idx2 ); CvScalar cvGetND( const CvArr* arr, const int* idx );
- arr
- 入力配列.
- idx0
- 要素インデックスの0を基準とした第1成分.
- idx1
- 要素インデックスの0を基準とした第2成分.
- idx2
- 要素インデックスの0を基準とした第3成分.
- idx
- 要素インデックスの配列.
関数cvGet*Dは,特定の配列要素を返す.疎な配列で,指定したノードが存在しない場合,この関数は0を返す(この関数によって新しいノードは生成されない).
GetReal*D
シングルチャンネルの配列の特定の要素を返す
double cvGetReal1D( const CvArr* arr, int idx0 ); double cvGetReal2D( const CvArr* arr, int idx0, int idx1 ); double cvGetReal3D( const CvArr* arr, int idx0, int idx1, int idx2 ); double cvGetRealND( const CvArr* arr, const int* idx );
- arr
- 入力配列. シングルチャンネルでなくてはならない.
- idx0
- 要素インデックスの,0を基準とした第1成分.
- idx1
- 要素インデックスの,0を基準とした第2成分.
- idx2
- 要素インデックスの,0を基準とした第3成分.
- idx
- 要素インデックスの配列.
関数cvGetReal*Dは,シングルチャンネルの配列の特定の要素を返す.配列がマルチチャンネルの場合は,ランタイムエラーが発生する. 注釈:関数cvGet*Dはシングルチャンネルとマルチチャンネルの配列に対して安全に使用することができるが,若干処理速度が遅い.
指定したノードが存在しなければ,この関数は0を返す(この関数によって新しいノードは生成されない).
mGet
シングルチャンネル浮動小数点型行列の特定の要素を返す
double cvmGet( const CvMat* mat, int row, int col );
- mat
- 入力行列.
- row
- 行の0を基準としたインデックス.
- col
- 列の0を基準としたインデックス.
関数cvmGetは,シングルチャンネル浮動小数点型行列の場合における,cvGetReal2Dの高速化版関数である. インライン処理され,配列のタイプや要素のタイプのチェックを行わず,また行と列の範囲のチェックもデバックモードのときしか行わないので高速である.
Set*D
特定の配列要素を変更する
void cvSet1D( CvArr* arr, int idx0, CvScalar value ); void cvSet2D( CvArr* arr, int idx0, int idx1, CvScalar value ); void cvSet3D( CvArr* arr, int idx0, int idx1, int idx2, CvScalar value ); void cvSetND( CvArr* arr, const int* idx, CvScalar value );
- arr
- 入力配列.
- idx0
- 要素インデックスの,0を基準とした第1成分.
- idx1
- 要素インデックスの,0を基準とした第2成分.
- idx2
- 要素インデックスの,0を基準とした第3成分.
- idx
- 要素インデックスの配列.
- value
- 割り当てる値.
関数cvSet*Dは,新しい値を指定した配列要素に割り当てる. 疎な配列の場合,ノードが存在しなければ,この関数はノードを生成する.
SetReal*D
特定の配列要素を変更する
void cvSetReal1D( CvArr* arr, int idx0, double value ); void cvSetReal2D( CvArr* arr, int idx0, int idx1, double value ); void cvSetReal3D( CvArr* arr, int idx0, int idx1, int idx2, double value ); void cvSetRealND( CvArr* arr, const int* idx, double value );
- arr
- 入力配列.
- idx0
- 要素インデックスの,0を基準とした第1成分.
- idx1
- 要素インデックスの,0を基準とした第2成分.
- idx2
- 要素インデックスの,0を基準とした第3成分.
- idx
- 要素インデックスの配列.
- value
- 割り当てる値.
関数cvSetReal*Dはシングルチャンネルの配列の指定した要素に新しい値を割り当てる. 配列がマルチチャンネルのときは,ランタイムエラーが起こる. 注釈:関数cvSet*Dはシングルチャンネルとマルチチャンネルの両方に安全に使用することができるが,若干処理速度が遅い.
疎な配列の場合に,ノードが存在しなれば,この関数はノードを生成する.
mSet
シングルチャンネルの浮動小数点型行列の特定の要素の値を変更する
void cvmSet( CvMat* mat, int row, int col, double value );
- mat
- 行列.
- row
- 行の,0を基準としたインデックス.
- col
- 列の,0を基準としたインデックス.
- value
- 行列の要素の新しい値.
関数cvmSetは,シングルチャンネル浮動小数点型行列の場合における,cvSetReal2Dの高速化版関数である. インライン処理され,配列のタイプや要素のタイプのチェックを行わず,また行と列の範囲のチェックもデバックモードのときしか行わないため高速である.
ClearND
特定の要素の値をクリアする
void cvClearND( CvArr* arr, const int* idx );
- arr
- 入力配列.
- idx
- 要素のインデックスの配列.
関数cvClearNDは,密な配列と疎な配列の指定した要素をクリア(0にセット)する.要素が存在しなければ,この関数は何もしない.
コピーと充填(Copying and Filling)
Copy
一つの配列を別の配列にコピーする
void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL );
- src
- コピー元の配列.
- dst
- コピー先の配列.
- mask
- 8 ビットシングルチャンネル配列の処理マスク.コピー先の配列の変更する要素を指定する.
関数 cvCopy は,入力配列から出力配列に選択された要素をコピーする.
mask(I)!=0 の場合,dst(I)=src(I)
引数の配列が IplImage 型の場合,その ROI と COI が利用される. コピー元配列とコピー先配列は,同じ型,同じ次元,同じサイズでなければならない.この関数は,疎な配列もコピーできる(この場合,マスクはサポートされない).
Set
配列の各要素に与えられた値をセットする
void cvSet( CvArr* arr, CvScalar value, const CvArr* mask=NULL );
- arr
- 値をセットする配列.
- value
- 配列を埋める値.
- mask
- 8 ビットシングルチャンネル配列の処理マスク.配列の変更する要素を指定する.
関数 cvSet は,スカラー値 value を,配列の選択された各要素にコピーする.
mask(I)!=0 の場合,arr(I)=value
配列 arr が IplImage 型の場合, ROI は利用されるが,COI がセットされていてはならない.
SetZero
配列をクリアする
void cvSetZero( CvArr* arr );
#define cvZero cvSetZero
- arr
- クリアされる配列.
関数 cvSetZero は,配列をクリアする. 密な配列(CvMat, CvMatND, IplImage)に対する cvZero(array) は,cvSet(array,cvScalarAll(0),0) と等価である. 疎な配列の場合は,全ての要素が削除される.
SetIdentity
スカラー倍された単位行列を用いて初期化を行う
void cvSetIdentity( CvArr* mat, CvScalar value=cvRealScalar );
- arr
- 初期化される行列(正方である必要はない).
- value
- 対角成分の値.
関数 cvSetIdentity は,スカラー倍された単位行列を用いた初期化を行う.
i=j ならば, arr(i,j)=value そうでなければ, 0
Range
与えられた範囲の数で行列を埋める
void cvRange( CvArr* mat, double start, double end );
- mat
- 初期化される行列.これは,整数型あるいは浮動小数点型 32 ビットシングルチャンネルでなくてはならない.
- start
- 範囲の下限(範囲に含まれる).
- end
- 範囲の上限(範囲に含まれない).
関数 cvRange は,次のように行列を初期化する.
arr(i,j)=(end-start)*(i*cols(arr)+j)/(cols(arr)*rows(arr))例えば,以下のコードは連続した整数の1次元ベクトルを初期化する.
CvMat* A = cvCreateMat( 1, 10, CV_32S ); cvRange( A, 0, A->cols ); // A は,[0,1,2,3,4,5,6,7,8,9] で初期化される.
変形と置換(Transforms and Permutations)
Reshape
データのコピーなしに行列/画像の形状を変える
CvMat* cvReshape( const CvArr* arr, CvMat* header, int new_cn, int new_rows=0 );
- arr
- 入力配列.
- header
- 書き込まれる出力ヘッダ.
- new_cn
- 新しいチャンネル数 .new_cn = 0はチャンネル数が変更されていないことを意味する.
- new_rows
- 新しい行数. new_rows = 0は,行数がnew_cnの値に応じて変更する必要があるのにも関わらず,変更されないままであることを意味する.
関数cvReshapeは,オリジナルの配列と同じデータだが, 異なる形状(異なるチャンネル数,異なる行数,またその両方)を持つCvMatのヘッダを初期化する.
例えば,以下は一つの画像バッファと二つの画像のヘッダ(1番目は 320×240×3の画像,2番目は960×240x1の画像)を作成するためのコードである.
IplImage* color_img = cvCreateImage( cvSize(320,240), IPL_DEPTH_8U, 3 ); CvMat gray_mat_hdr; IplImage gray_img_hdr, *gray_img; cvReshape( color_img, &gray_mat_hdr, 1 ); gray_img = cvGetImage( &gray_mat_hdr, &gray_img_hdr );
そして,次の例は3×3の行列から1×9のベクトルへの変換である.
CvMat* mat = cvCreateMat( 3, 3, CV_32F ); CvMat row_header, *row; row = cvReshape( mat, &row_header, 0, 1 );
ReshapeMatND
データのコピーなしに多次元配列の形状を変える
CvArr* cvReshapeMatND( const CvArr* arr,
int sizeof_header, CvArr* header,
int new_cn, int new_dims, int* new_sizes );
#define cvReshapeND( arr, header, new_cn, new_dims, new_sizes ) ¥
cvReshapeMatND( (arr), sizeof(*(header)), (header), ¥
(new_cn), (new_dims), (new_sizes))
- arr
- 入力配列.
- sizeof_header
- IplImageとCvMat,CvMatNDそれぞれの出力ヘッダを区別するための出力ヘッダのサイズ.
- header
- 書き込まれる出力ヘッダ.
- new_cn
- 新しいチャンネル数. new_cn = 0は,チャンネル数が変更されていないことを意味する.
- new_dims
- 新しい次元数. new_dims = 0は,次元数が同じままであることを意味する.
- new_sizes
- 新しい次元サイズの配列.要素の総数は変化してはいけないので,new_dims-1の値のみ使用される.従って,new_dims = 1であればnew_sizesは使用されない.
関数cvReshapeMatNDは,cvReshape の拡張バージョンである.これは多次元配列を扱うことが可能(普通の画像と行列に対しても使用することが可能)で,さらに次元の変更も可能である.以下の2つのサンプルはcvReshapeでの記述を,cvReshapeMatNDを用いて書き直したものである.
IplImage* color_img = cvCreateImage( cvSize(320,240), IPL_DEPTH_8U, 3 );
IplImage gray_img_hdr, *gray_img;
gray_img = (IplImage*)cvReshapeND( color_img, &gray_img_hdr, 1, 0, 0 );
...
/* 2番目は2x2x2の配列を8x1のベクトルに変換する例である */
int size[] = { 2, 2, 2 };
CvMatND* mat = cvCreateMatND( 3, size, CV_32F );
CvMat row_header, *row;
row = cvReshapeND( mat, &row_header, 0, 1, 0 );
Repeat
出力配列を入力配列でタイル状に埋める
void cvRepeat( const CvArr* src, CvArr* dst );
- src
- 入力配列, 画像または行列.
- dst
- 出力配列, 画像または行列.
関数cvRepeatは,入力配列をタイル状に配置して出力配列を埋める.
dst(i,j)=src(i mod rows(src), j mod cols(src))
出力配列は入力配列より大きいこともあれば,小さいこともある.
Flip
2次元配列を垂直,水平,または両軸で反転する
void cvFlip( const CvArr* src, CvArr* dst=NULL, int flip_mode=0);
#define cvMirror cvFlip
- src
- 入力配列.
- dst
- 出力配列.もしdst = NULLであれば,反転はインプレースモードで行われる.
- flip_mode
- 配列の反転方法の指定.
flip_mode = 0 は,x軸周りでの反転, flip_mode > 0(例えば,1)は,y軸周りでの反転, flip_mode < 0(例えば,-1)は,両軸周りでの反転. 以下の式も参照.
関数cvFlipは,3種類の異なる方法のうち1つを指定して配列を反転させる(行と列のインデックスは0が基準である).
dst(i,j)=src(rows(src)-i-1,j) (flip_mode = 0 の場合)
dst(i,j)=src(i,cols(src1)-j-1) (flip_mode > 0 の場合)
dst(i,j)=src(rows(src)-i-1,cols(src)-j-1) (flip_mode < 0 の場合)
関数の使用例
- 画像原点を左上から左下に,あるいはその逆方向に入れ替えるため(Win32システムの動画像処理では典型的な処理)に,垂直反転(flip_mode > 0)を用いる.
- 垂直軸対称性をチェックするために,画像の水平反転と水平方向シフトを行い,絶対誤差を計算する(flip_mode > 0).
- 点対称性をチェックするために,画像の水平垂直の同時反転をとシフトを行い,絶対誤差を計算する(flip_mode < 0).
- 1次元の配列の並びを逆転する(flip_mode > 0).
Split
マルチチャンネルの配列を,複数のシングルチャンネルの配列に分割する.または,配列から一つのチャンネルを取り出す.
void cvSplit( const CvArr* src, CvArr* dst0, CvArr* dst1,
CvArr* dst2, CvArr* dst3 );
#define cvCvtPixToPlane cvSplit
- src
- 入力配列.
- dst0...dst3
- 出力チャンネル.
関数cvSplitは,マルチチャンネルの配列をシングルチャンネルの配列に分割する.この操作には二つのモードがある. 入力配列がNチャンネルの場合,先頭からN番目までの出力チャンネルが NULL でなければ,それらはすべて入力配列から取り出される. そうでなく,N個の出力チャネルのうち一つだけが NULL でない場合は,この特定のチャンネルのみを抽出する.このいずれでもない場合はエラーとなる. N番目以降の出力チャンネルは常に NULL でなくてはならない. IplImageでは,画像から一つのシングルチャンネルを抽出するために,COIを伴うcvCopyも利用される.
Merge
複数のシングルチャネルの配列からマルチチャンネル配列を構成する.または,配列に一つのシングルチャンネルを挿入する
void cvMerge( const CvArr* src0, const CvArr* src1,
const CvArr* src2, const CvArr* src3, CvArr* dst );
#define cvCvtPlaneToPix cvMerge
- src0... src3
- 入力配列.
- dst
- 出力配列.
関数cvMergeは,前述の関数と反対の操作である.もし出力配列がNチャンネルで,N個の入力チャンネルが NULL でないとき,これらのすべては出力配列にコピーされる.そうでなく,一つの入力配列のみが NULL でなければ,この特定のチャンネルが出力配列にコピーされ,このいずれもでない場合はエラーとなる.N番目以降の入力チャンネルは常に NULL でなくてはならない. IplImageでは,画像に一つのシングルチャンネルを挿入するために,COIを伴うcvCopyも利用される.
MixChannels
入力配列のチャンネルを出力配列の指定されたチャンネルにコピーする
void cvMixChannels( const CvArr** src, int src_count,
CvArr** dst, int dst_count,
const int* from_to, int pair_count );
- src
- 入力配列の配列.
- src_count
- 入力配列の数.
- dst
- 出力配列の配列.
- dst_count
- 出力配列の数.
- from_to
- コピーされる平面(チャンネル)のインデックスのペア配列. from_to[k*2]は入力平面の0を基準としたインデックスで,from_to[k*2+1]は出力平面のインデックス.ここで,入力及び出力配列すべてについて,各平面への連続的な番号付けが行われる.from_to[k*2]が負のとき,対応する出力平面は0で埋められる.
- pair_count
- from_toのペア数,またはコピーされた平面の数.
関数cvMixChannelsは,cvSplit,cvMerge,および cvCvtColorのいくつかの書式の汎用形である.これは,平面の順番の変更,アルファチャネルの追加や削除,1枚の平面や複数平面の抽出や挿入などに用いられる.以下に,どのように4チャンネルのRGBA画像を,3チャンネルのBGR画像(つまり,RとBの入れ替え) にするか,そしてアルファチャネルを分離するかを示す.
CvMat* rgba = cvCreateMat( 100, 100, CV_8UC4 );
CvMat* bgr = cvCreateMat( rgba->rows, rgba->cols, CV_8UC3 );
CvMat* alpha = cvCreateMat( rgba->rows, rgba->cols, CV_8UC1 );
CvArr* out[] = { bgr, alpha };
int from_to[] = { 0, 2, 1, 1, 2, 0, 3, 3 };
cvSet( rgba, cvScalar(1,2,3,4) );
cvMixChannels( (const CvArr**)&rgba, 1, out, 2, from_to, 4 );
RandShuffle
配列の要素をランダムにシャッフルする
void cvRandShuffle( CvArr* mat, CvRNG* rng, double iter_factor=1. );
- mat
- 入力/出力行列.インプレースモードでシャッフルされる.
- rng
- 要素のシャッフルで用いられる Random Number Generator.ポインタがNULLの場合,一時的なRNGが生成され,利用される.
- iter_factor
- シャッフルの強さを指定するパラメータ.以下を参照.
関数cvRandShuffleは,ランダムに選ばれた配列要素ペアの入れ替えを反復することにより行列をシャッフルする(マルチチャンネル配列の場合,それぞれの要素は複数の成分を含む). 反復回数(つまり,ペアの入れ替え)は round(iter_factor*rows(mat)*cols(mat))であり, iter_factor=0はシャッフルを行わないことを, iter_factor=1はこの関数がrows(mat)*cols(mat)回ランダムなペアを入れ替えることを意味する.
四則演算,論理演算,比較演算(Arithmetic, Logic and Comparison)
LUT
配列のルックアップテーブルによる変換
void cvLUT( const CvArr* src, CvArr* dst, const CvArr* lut );
- src
- 入力配列(各要素は8ビットデータ).
- dst
- 出力配列(任意のデプス,入力配列と同じチャンネル数).
- lut
- 要素数が256であるルックアップテーブル(出力配列と同じデプスでなければならない). マルチチャンネルの入力/出力配列の場合,テーブルはシングルチャンネル(この場合すべてのチャンネル対して,同じテーブルを使う)か,入力/出力配列と同じチャンネル数でなければならない.
関数 cvLUT は,出力配列の各要素値をルックアップテーブルを用いて決定する. 配列のインデックスは入力配列より求められる. src の各要素に対して以下のような処理を行う.
dst(I)=lut[src(I)+DELTA]ここで,srcのデプスが CV_8U の場合はDELTA=0,CV_8S の場合は DELTA=128.
ConvertScale
任意の線形変換によって配列の値を変換する
void cvConvertScale( const CvArr* src, CvArr* dst, double scale=1, double shift=0 );
#define cvCvtScale cvConvertScale
#define cvScale cvConvertScale
#define cvConvert( src, dst ) cvConvertScale( (src), (dst), 1, 0 )
- src
- 入力配列.
- dst
- 出力配列.
- scale
- スケーリング係数.
- shift
- スケーリングした入力配列の要素に加える値.
関数 cvConvertScale は,様々な目的を持つため,違う名前での関数(マクロ)としても定義されている. この関数は,入力配列をスケーリングしてコピーし,さらに以下のような変換を行う(あるいは変換のみを行う).
dst(I)=src(I)*scale + (shift,shift,...)
マルチチャンネル配列の全てのチャンネルは独立に処理される.
異なる型への変換では,丸めや飽和を伴う.すなわち,スケーリング+変換の結果が出力先のデータタイプで表現できない値になる場合には,表現できる最も近い実軸上の値で表現する.
scale=1, shift=0 の場合は,何も行わない.これは特別なケースであり,cvConvert と同じ意味である. 入力配列と出力配列が同じタイプの場合,行列や画像のスケーリングと移動を行うことができ,cvScale に相当する.
ConvertScaleAbs
任意の線形変換によって,入力配列の要素を8ビット符号無し整数型の配列に変換する.
void cvConvertScaleAbs( const CvArr* src, CvArr* dst, double scale=1, double shift=0 );
#define cvCvtScaleAbs cvConvertScaleAbs
- src
- 入力配列.
- dst
- 出力配列(デプスは 8u).
- scale
- ScaleAbs 係数.
- shift
- スケーリングした入力配列の要素に加える値.
関数 cvConvertScaleAbs は前述の関数と類似しているが,以下に示すように,変換結果の絶対値を出力する.
dst(I)=abs(src(I)*scale + (shift,shift,...))
この関数は,出力配列のタイプとして 8u(8ビット符号無し整数)のみをサポートしている.その他の型の場合は,cvConvertScale と cvAbs を組み合わせることで同様の効果が得られる.
Add
二つの配列を要素ごとに加算する
void cvAdd( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
- src1
- 1番目の入力配列.
- src2
- 2番目の入力配列.
- dst
- 出力配列.
- mask
- 処理マスク.8ビットシングルチャンネル配列(出力配列のどの要素が変更されるかを指定する).
関数 cvAdd は,以下のようにsrc1の各要素にsrc2の各要素を加える.
dst(I)=src1(I)+src2(I) (mask(I)!=0の場合)
すべての配列(マスクを除く)は同じタイプで<,配列のサイズ(またはROIのサイズ)も同じでなければならない.
AddS
スカラーと配列を加算する
void cvAddS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
- src
- 入力配列.
- value
- 加算するスカラー.
- dst
- 出力配列.
- mask
- 処理マスク.8ビットシングルチャンネル配列(出力配列のどの要素が変更されるかを指定する).
関数 cvAddS は,入力配列 src1 のすべての要素にスカラー value を加え,結果を dst に保存する.
dst(I)=src(I)+value ( mask(I)!=0 の場合 )
すべての配列(マスクを除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
AddWeighted
二つの配列の重み付き和を計算する
void cvAddWeighted( const CvArr* src1, double alpha,
const CvArr* src2, double beta,
double gamma, CvArr* dst );
- src1
- 1番目の入力配列.
- alpha
- 1番目の配列要素への重み.
- src2
- 2番目の入力配列.
- beta
- 2番目の配列要素への重み.
- dst
- 出力配列.
- gamma
- 加算結果に,さらに加えられるスカラー値.
関数 cvAddWeighted は以下のように二つの配列の重み付き和を計算する.
dst(I)=src1(I)*alpha+src2(I)*beta+gamma
すべての配列は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
Sub
二つの配列の要素ごとの減算を行う
void cvSub( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
- src1
- 1番目の入力配列.
- src2
- 2番目の入力配列.
- dst
- 出力配列.
- mask
- 処理マスク.8ビットシングルチャンネル配列(出力配列のどの要素が変更されるかを指定する).
関数 cvSub は,以下のようにsrc1の各要素からsrc2の各要素を引く.
dst(I)=src1(I)-src2(I) (mask(I)!=0 の場合 )
すべての配列(マスクを除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
SubS
配列要素からスカラーを減算する
void cvSubS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
- src
- 入力配列.
- value
- 減算するスカラー
- dst
- 出力配列.
- mask
- 処理マスク.8ビットシングルチャンネル配列(出力配列のどの要素が変更されるかを指定する).
関数 cvSubS は,以下のように入力配列のすべての要素から指定されたスカラーを引く.
dst(I)=src(I)-value if mask(I)!=0
すべての配列(マスクを除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
SubRS
スカラーから配列要素を減算する
void cvSubRS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
- src
- 入力配列.
- value
- 減算されるスカラー.
- dst
- 出力配列.
- mask
- 処理マスク.8ビットシングルチャンネル配列(出力配列のどの要素が変更されるかを指定する).
関数 cvSubRS は,以下のように指定されたスカラーから入力配列のすべての要素それぞれを引く.
dst(I)=value-src(I) ( mask(I)!=0 の場合 )
すべての配列(マスクを除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
Mul
二つの配列の要素同士を乗算する
void cvMul( const CvArr* src1, const CvArr* src2, CvArr* dst, double scale=1 );
- src1
- 1番目の入力配列.
- src2
- 2番目の入力配列.
- dst
- 出力配列.
- scale
- 任意のスケーリング係数.
関数 cvMul は,以下のように二つの配列の要素同士の乗算を行う.
dst(I)=scale•src1(I)•src2(I)
すべての配列(マスクを除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
Div
二つの配列の要素同士を除算する
void cvDiv( const CvArr* src1, const CvArr* src2, CvArr* dst, double scale=1 );
- src1
- 1番目の入力配列.ポインタが NULL の場合は,すべての要素が 1であると仮定する.
- src2
- 2番目の入力配列.
- dst
- 出力配列.
- scale
- オプションのスケーリング係数.
関数 cvDiv は,以下のように1番目の入力配列の各要素を2番目の入力配列の各要素で割る.
dst(I)=scale•src1(I)/src2(I), (src1!=NULLの場合) dst(I)=scale/src2(I), (src1=NULLの場合)
すべての配列(マスクを除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
And
ビット単位の論理積を計算する
void cvAnd( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
- src1
- 1番目の入力配列.
- src2
- 2番目の入力配列.
- dst
- 出力配列.
- mask
- 処理マスク.8ビットシングルチャンネル配列(出力配列のどの要素が変更されるかを指定する).
関数 cvAnd は以下のように,二つの配列の要素ごとの論理積(AND)を計算する.
dst(I)=src1(I)&src2(I) (mask(I)!=0 の場合)
浮動小数点型配列の場合,それらのビット表現が処理に使われる.すべての配列(マスクを除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
AndS
配列の各要素とスカラーとのビット単位の論理積を計算する
void cvAndS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
- src
- 入力配列.
- value
- 処理に用いるスカラー.
- dst
- 出力配列.
- mask
- 処理マスク.8ビットシングルチャンネル配列(出力配列のどの要素が変更されるかを指定する).
関数 AndS は以下のように,配列の各要素と指定されたスカラーのビットごとの論理積を計算する.
dst(I)=src(I)&value if mask(I)!=0
実際の計算の前に,スカラーは配列と同じタイプに変換される.浮動小数点型配列の場合,それらのビット表現が処理に使われる.すべての配列(マスクを除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
以下のサンプルコードは,最上位ビットをクリアすることで浮動小数点型配列の各要素の絶対値を求める方法を示している.
float a[] = { -1, 2, -3, 4, -5, 6, -7, 8, -9 };
CvMat A = cvMat( 3, 3, CV_32F, &a );
int i, abs_mask = 0x7fffffff;
cvAndS( &A, cvRealScalar(*(float*)&abs_mask), &A, 0 );
for( i = 0; i < 9; i++ )
printf("%.1f ", a[i] );
出力は以下のとおりである.
1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
Or
二つの配列要素のビット単位の論理和を計算する
void cvOr( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
- src1
- 1番目の入力配列.
- src2
- 2番目の入力配列.
- dst
- 出力配列.
- mask
- 処理マスク.8ビットシングルチャンネル配列(出力配列のどの要素が変更されるかを指定する).
関数 cvOr は以下のように,二つの配列の要素ごとの論理和(OR)を計算する.
dst(I)=src1(I)|src2(I)
浮動小数点型配列の場合,それらのビット表現が処理に使われる.すべての配列(マスクを除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
OrS
配列の各要素とスカラーとのビット単位の論理和を計算する
void cvOrS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
- src1
- 入力配列.
- value
- 処理に用いるスカラー.
- dst
- 出力配列.
- mask
- 処理マスク.8ビットシングルチャンネル配列(出力配列のどの要素が変更されるかを指定する).
関数 OrS は以下のように,配列の各要素とスカラーのビットごとの論理和を計算する.
dst(I)=src(I)|value (mask(I)!=0の場合)
実際の計算の前に,スカラーは配列と同じタイプに変換される.浮動小数点型配列の場合,それらのビット表現が処理に使われる.すべての配列(マスクを除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
Xor
二つの配列要素のビット単位の排他的論理和を計算する
void cvXor( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
- src1
- 1番目の入力配列.
- src2
- 2番目の入力配列.
- dst
- 出力配列.
- mask
- 処理マスク.8ビットシングルチャンネル配列(出力配列のどの要素が変更されるかを指定する).
関数 cvXor は以下のように,二つの配列の要素ごとの排他的論理和(XOR)を計算する.
dst(I)=src1(I)^src2(I) (mask(I)!=0の場合)
浮動小数点型配列の場合,それらのビット表現が処理に使われる.すべての配列(マスクを除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
XorS
配列の各要素とスカラーとのビット単位の排他的論理和を計算する
void cvXorS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
- src
- 入力配列.
- value
- 処理に用いるスカラー.
- dst
- 出力配列.
- mask
- 処理マスク.8ビットシングルチャンネル配列(出力配列のどの要素が変更されるかを指定する).
関数 XorS は以下のように,配列の各要素とスカラーの,ビットごとの排他的論理和を計算する.
dst(I)=src(I)^value if mask(I)!=0
浮動小数点型配列の場合,それらのビット表現が処理に使われる.すべての配列(マスクを除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
以下は,虚部の最上位ビットのON-OFFを入れ替えることで共役複素ベクトルを求めるサンプルコードである.
float a[] = { 1, 0, 0, 1, -1, 0, 0, -1 }; /* 1, j, -1, -j */
CvMat A = cvMat( 4, 1, CV_32FC2, &a );
int i, neg_mask = 0x80000000;
cvXorS( &A, cvScalar( 0, *(float*)&neg_mask, 0, 0 ), &A, 0 );
for( i = 0; i < 4; i++ )
printf("(%.1f, %.1f) ", a[i*2], a[i*2+1] );
出力は以下のとおり.
(1.0,0.0) (0.0,-1.0) (-1.0,0.0) (0.0,1.0)
Not
各配列要素のビット単位の反転を行う
void cvNot( const CvArr* src, CvArr* dst );
- src1
- 入力配列.
- dst
- 出力配列.
関数 Not は以下のように,配列の各要素のビットをすべて反転(NOT)する.
dst(I)=~src(I)
Cmp
二つの配列の各要素ごとの比較を行う
void cvCmp( const CvArr* src1, const CvArr* src2, CvArr* dst, int cmp_op );
- src1
- 1番目の入力配列.
- src2
- 2番目の入力配列.どちらの入力配列もシングルチャンネルでなければならない.
- dst
- 出力配列(タイプは 8u か 8s でないといけない).
- cmp_op
- 比較方法を示すフラグ.
CV_CMP_EQ - src1(I) と src2(I) は等しい
CV_CMP_GT - src1(I) は src2(I) より大きい
CV_CMP_GE - src1(I) は src2(I) より大きいか等しい
CV_CMP_LT - src1(I) は src2(I) より小さい
CV_CMP_LE - src1(I) は src2(I) より小さいか等しい
CV_CMP_NE - src1(I) と src2(I) は等しくない
関数 cvCmp は,以下のように二つの配列の対応する要素を比較し,出力配列の値にセットする.
dst(I)=src1(I) op src2(I),
ここで op は '=', '>', '>=', '<', '<=', '!=' のいずれか.
比較結果が真(TRUE)であれば dst(I) には 0xff(要素すべてのビットが 1 )をセットし,それ以外の場合(FALSE)であれば 0 をセットする.すべての配列(出力配列を除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
CmpS
配列要素とスカラーを比較する
void cvCmpS( const CvArr* src, double value, CvArr* dst, int cmp_op );
- src
- 入力配列(シングルチャンネル).
- value
- それぞれの配列要素と比較されるスカラー.
- dst
- 出力配列(タイプは8u または8s).
- cmp_op
- 比較方法を示すフラグ.
CV_CMP_EQ - src1(I) と value は等しい
CV_CMP_GT - src1(I) は value より大きい
CV_CMP_GE - src1(I) は value より大きいか等しい
CV_CMP_LT - src1(I) は value より小さい
CV_CMP_LE - src1(I) は value より小さいか等しい
CV_CMP_NE - src1(I) と value は等しくない
関数 cvCmpS は以下のように配列要素とスカラーとを比較し,出力配列の値をセットする.
dst(I)=src(I) op scalar,
ここで op は '=', '>', '>=', '<', '<=' or '!=' のいずれか.
比較結果が真(TRUE)であれば dst(I) には 0xff(要素すべてのビットが 1 ) をセットし,それ以外の場合(FALSE)であれば 0 をセットする.すべての配列のサイズ(またはROIのサイズ)は同じでなければならない.
InRange
配列の要素値が他の二つの配列要素で表される範囲内に位置するかをチェックする
void cvInRange( const CvArr* src, const CvArr* lower, const CvArr* upper, CvArr* dst );
- src
- 入力配列.
- lower
- 下限値(その値を含む)を表す配列.
- upper
- 上限値(その値は含まない)を表す配列.
- dst
- 出力配列(タイプは8u または 8s).
関数 cvInRange は以下のように,入力配列のすべての要素について範囲チェックを行う.
dst(I)=lower(I)0 <= src(I)0 < upper(I)0
(シングルチャンネル配列の場合),
dst(I)=lower(I)0 <= src(I)0 < upper(I)0 &&
lower(I)1 <= src(I)1 < upper(I)1
(2チャンネルなどの場合).
src(I) が範囲内であれば dst(I) には 0xff(要素すべてのビットが '1')をセットし,それ以外の場合は 0 をセットする.すべての配列(出力配列を除く)は同じタイプで,配列のサイズ(またはROIのサイズ)も同じでなければならない.
InRangeS
配列の要素値が二つのスカラーの間に位置するかをチェックする
void cvInRangeS( const CvArr* src, CvScalar lower, CvScalar upper, CvArr* dst );
- src
- 入力配列.
- lower
- 下限値(その値を含む).
- upper
- 上限値(その値は含まない).
- dst
- 出力配列(タイプは8u または 8s).
関数 cvInRangeS は以下のように,入力配列のすべての要素のについて範囲チェックを行う.
dst(I)=lower0 <= src(I)0 < upper0
(シングルチャンネル配列の場合),
dst(I)=lower0 <= src(I)0 < upper0 &&
lower1 <= src(I)1 < upper1
(2チャンネルなどの場合).
src(I) が範囲内であれば dst(I) には 0xff(要素すべてのビットが '1')をセットし,それ以外の場合は 0 をセットする. すべての配列のサイズ(またはROIのサイズ)は同じでなければならない.
Max
二つの配列の各要素についての最大値を求める
void cvMax( const CvArr* src1, const CvArr* src2, CvArr* dst );
- src1
- 1番目の入力配列.
- src2
- 2番目の入力配列.
- dst
- 出力配列.
関数 cvMax は以下のように,二つの配列の要素ごとの最大値を計算する.
dst(I)=max(src1(I), src2(I))
すべての配列はシングルチャンネルで,タイプ,配列のサイズ(またはROIのサイズ)は同じでなければならない.
MaxS
配列の各要素とスカラーについての最大値を求める
void cvMaxS( const CvArr* src, double value, CvArr* dst );
- src
- 入力配列.
- value
- スカラー.
- dst
- 出力配列.
関数 cvMaxS は以下のように,配列の各要素とスカラーとの最大値を計算する.
dst(I)=max(src(I), value)
すべての配列はシングルチャンネルで,タイプ,配列のサイズ(またはROIのサイズ)は同じでなければならない.
Min
二つの配列の各要素についての最小値を求める
void cvMin( const CvArr* src1, const CvArr* src2, CvArr* dst );
- src1
- 1番目の入力配列.
- src2
- 2番目の入力配列.
- dst
- 出力配列.
関数 cvMin は以下のように,二つの配列の要素ごとの最小値を計算する.
dst(I)=min(src1(I),src2(I))
すべての配列はシングルチャンネルで,タイプ,配列のサイズ(またはROIのサイズ)は同じでなければならない.
MinS
配列の各要素とスカラーについての最小値を求める
void cvMinS( const CvArr* src, double value, CvArr* dst );
- src
- 入力配列.
- value
- スカラー.
- dst
- 出力配列.
関数 cvMinS は以下のように,配列の各要素とスカラーとの最小値を計算する.
dst(I)=min(src(I), value)
すべての配列はシングルチャンネルで,タイプ,配列のサイズ(またはROIのサイズ)は同じでなければならない.
AbsDiff
二つの配列の要素ごとの差の絶対値を計算する
void cvAbsDiff( const CvArr* src1, const CvArr* src2, CvArr* dst );
- src1
- 1番目の入力配列.
- src2
- 2番目の入力配列.
- dst
- 出力配列.
関数 cvAbsDiff は以下のように,src1 の各要素と src2 の差の絶対値を計算する.
dst(I)c = abs(src1(I)c - src2(I)c).
すべての配列は同じタイプ,同じサイズ(または同じROIサイズ)でなければならない.
AbsDiffS
配列の要素と定数との差の絶対値を計算する
void cvAbsDiffS( const CvArr* src, CvArr* dst, CvScalar value );
#define cvAbs(src, dst) cvAbsDiffS(src, dst, cvScalarAll(0))
- src
- 入力配列.
- dst
- 出力配列.
- value
- スカラー.
関数 cvAbsDiffS は以下のように,配列の各要素とスカラーとの差の絶対値を計算する.
dst(I)c = abs(src(I)c - valuec).
すべての配列は同じタイプ,同じサイズ(または同じROIサイズ)でなければならない.
統計(Statistics)
CountNonZero
配列要素において 0 ではない要素をカウントする
int cvCountNonZero( const CvArr* arr );
- arr
- 配列(シングルチャンネルまたはCOIがセットされたマルチチャンネルの画像).
関数 cvCountNonZero は以下のように,入力配列内の 0 でない要素数を返す.
result = sumI arr(I)!=0配列が IplImage の場合, ROI,COI の両方に対応している.
Sum
配列要素の総和を計算する
CvScalar cvSum( const CvArr* arr );
- arr
配列.
関数 cvSum は以下のように,配列要素の総和 S を各チャンネルで独立に計算する.
Sc = sumI arr(I)c配列のタイプが IplImage で COI がセットされている場合,指定されたチャンネルのみを処理し,総和を1番目のスカラー値(S0)として保存する.
Avg
配列要素の平均値を計算する
CvScalar cvAvg( const CvArr* arr, const CvArr* mask=NULL );
- arr
- 配列.
- mask
- オプションの処理マスク.
関数 cvAvg は,配列要素の平均値 M を各チャンネルで独立に計算する.
N = sumI mask(I)!=0 Mc = 1/N • sumI,mask(I)!=0 arr(I)c配列のタイプが IplImage で COI がセットされている場合,指定されたチャンネルのみを処理し,平均値を1番目のスカラー値(M0)として保存する.
AvgSdv
配列要素の平均と標準偏差を計算する
void cvAvgSdv( const CvArr* arr, CvScalar* mean, CvScalar* std_dev, const CvArr* mask=NULL );
- arr
- 配列.
- mean
- 計算結果の平均値へのポインタ.必要でない場合は NULL.
- std_dev
- 計算結果の標準偏差へのポインタ.
- mask
- オプションの処理マスク.
関数 cvAvgSdv は,配列要素の平均と標準偏差を各チャンネルで独立に計算する.
N = sumI mask(I)!=0 meanc = 1/N • sumI,mask(I)!=0 arr(I)c std_devc = sqrt(1/N • sumI,mask(I)!=0 (arr(I)c - Mc)2)配列のタイプが IplImage で COI がセットされている場合,指定されたチャンネルのみを処理し,平均値と標準偏差をそれぞれ1番目のスカラー値(M0と S0)として保存する.
MinMaxLoc
配列あるいは部分配列内の最小値と最大値を求める
void cvMinMaxLoc( const CvArr* arr, double* min_val, double* max_val,
CvPoint* min_loc=NULL, CvPoint* max_loc=NULL, const CvArr* mask=NULL );
- arr
- 入力配列(シングルチャンネルまたはCOIがセットされたマルチチャンネル).
- min_val
- 戻り値の最小値へのポインタ.
- max_val
- 戻り値の最大値へのポインタ.
- min_loc
- 戻り値の最小値を持つ位置へのポインタ.
- max_loc
- 戻り値の最大値を持つ位置へのポインタ.
- mask
- 部分配列を指定するためのオプションのマスク.
関数 MinMaxLoc は,配列要素の中から最小値・最大値とその位置を求める. 各極値は配列全体または選択されたROI(IplImageの場合)をスキャンして求める. mask が NULL でない場合は,指定された領域のみをスキャンする. マルチチャンネル配列の場合,入力は COI がセットされた IplImage データタイプでなければならない. 多次元配列の場合は,min_loc->xと max_loc->yには,極値の座標がそのまま入る.
Norm
配列の絶対値ノルム(absolute array norm),絶対値差分ノルム(absolute difference norm),相対値差分ノルム(relative difference norm)を計算する
double cvNorm( const CvArr* arr1, const CvArr* arr2=NULL, int norm_type=CV_L2, const CvArr* mask=NULL );
- arr1
- 1番目の入力画像.
- arr2
- 2番目の入力画像.NULL の場合,arr1の絶対値ノルムが計算され,そうでない場合は,arr1-arr2 の絶対値あるいは相対値ノルムが計算される.
- normType
- ノルムのタイプ(以下の説明を参照).
- mask
- オプションの処理マスク.
関数 cvNorm は arr2 が NULL の場合,以下のように arr1 の絶対値ノルムを計算する.
norm = ||arr1||C = maxI abs(arr1(I)), (normType = CV_Cの場合)
norm = ||arr1||L1 = sumI abs(arr1(I)), (normType = CV_L1の場合)
norm = ||arr1||L2 = sqrt( sumI arr1(I)2), (normType = CV_L2の場合)
この関数は,arr2 が NULL でない場合,以下のように絶対値あるいは相対値ノルムを計算する.
norm = ||arr1-arr2||C = maxI abs(arr1(I)-arr2(I)), (normType = CV_Cの場合) norm = ||arr1-arr2||L1 = sumI abs(arr1(I)-arr2(I)), (normType = CV_L1の場合) norm = ||arr1-arr2||L2 = sqrt( sumI (arr1(I)-arr2(I))2 ), (normType = CV_L2の場合) もしくは norm = ||arr1-arr2||C/||arr2||C, (normType = CV_RELATIVE_Cの場合) norm = ||arr1-arr2||L1/||arr2||L1, (normType = CV_RELATIVE_L1の場合) norm = ||arr1-arr2||L2/||arr2||L2, (normType = CV_RELATIVE_L2の場合)
関数 cvNorm は計算したノルムを返す.マルチチャンネル配列はシングルチャンネルとして取り扱う.すなわち,すべてのチャンネルの結果が統合される.
Reduce
行列をベクトルへ縮小する
void cvReduce( const CvArr* src, CvArr* dst, int op=CV_REDUCE_SUM );
- src
- 入力行列.
- dst
- 1行(または1列)の出力ベクトル(すべての行/列から指定された方法で計算される).
- dim
- 配列をどのように縮小するかを示すインデックス. 0 は行列を1行ベクトルに縮小する. 1 は行列を1列ベクトルに縮小する. -1 はdst のサイズから次元を解析し,自動的に選択する.
- op
- 縮小処理の種類.以下の値のいずれか.
CV_REDUCE_SUM - 出力は各行(または各列)の総和
CV_REDUCE_AVG - 出力は各行(または各列)の平均ベクトル
CV_REDUCE_MAX - 出力は各行(または各列)における最大値
CV_REDUCE_MIN - 出力は各行(または各列)における最小値
関数 cvReduce は,行列の各行(各列)を1次元ベクトルの集合として取り扱い,その集合に対して指示された処理を行うことによって,入力行列をベクトルに縮小する. 例えば,ラスター画像の水平方向(あるいは垂直方向)への射影を計算するために使うことができる.CV_REDUCE_SUM と CV_REDUCE_AVG の場合は,精度を保つために出力要素のビットデプスを大きくとるべきである.また,マルチチャンネル配列においても,これら二つのモードがサポートされる.
線形代数(Linear Algebra)
DotProduct
ユークリッド距離に基づく2つの配列の内積を計算する
double cvDotProduct( const CvArr* src1, const CvArr* src2 );
- src1
- 1番目の入力配列.
- src2
- 2番目の入力配列.
関数cvDotProductはユークリッド幾何学における内積を計算し,その結果を返す.
src1•src2 = sumI(src1(I)*src2(I))
マルチチャンネル配列の場合,全てのチャンネルの結果が累算される.特にaを複素ベクトルとすると,cvDotProduct(a,a) は ||a||2を返す.この関数は,多次元配列を1行,1レイヤーずつ処理することもできる.
Normalize
指定のノルムになるように,あるいは値が指定の範囲になるように,配列を正規化する
void cvNormalize( const CvArr* src, CvArr* dst,
double a=1, double b=0, int norm_type=CV_L2,
const CvArr* mask=NULL );
- src
- 入力配列.
- dst
- 出力配列.インプレース処理が可能.
- a
- 出力配列の最小値または最大値,あるいは出力配列のノルム.
- b
- 出力配列の最大値または最小値.
- norm_type
- 正規化のタイプ.以下のうち一つを用いることができる.
CV_C - 配列のC-norm(絶対値の最大値)を正規化
CV_L1 - 配列のL1-norm(絶対値の合計)を正規化
CV_L2 - 配列のL2-norm(ユークリッド距離)を正規化
CV_MINMAX - 配列の値が指定の範囲に収まるようにスケーリングとシフトを行う.
- mask
- 操作マスク.特定の配列要素のみを正規化するためのマスク.
関数cvNormalizeは,入力配列をそのノルム,または値が特定の値や範囲になるように正規化する.
norm_type==CV_MINMAXのとき,
dst(i,j)=(src(i,j)-min(src))*(b'-a')/(max(src)-min(src)) + a', (mask(i,j)!=0 の場合)
dst(i,j)=src(i,j) (それ以外の場合)
ここで b'=MAX(a,b),a'=MIN(a,b).min(src) と max(src) はそれぞれ入力配列の全体,または指定された部分集合について計算した全体の最小値と最大値である.
norm_type!=CV_MINMAXのとき,
dst(i,j)=src(i,j)*a/cvNorm(src,0,norm_type,mask), (mask(i,j)!=0 の場合)
dst(i,j)=src(i,j) (それ以外の場合)
以下に,簡単な例を示す.
float v[3] = { 1, 2, 3 };
CvMat V = cvMat( 1, 3, CV_32F, v );
// 単位ベクトルの生成
// これは,以下と等しい.
// for(int i=0;i<3;i++) v[i]/=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
cvNormalize( &V, &V );
CrossProduct
二つの3次元ベクトルの外積を計算する
void cvCrossProduct( const CvArr* src1, const CvArr* src2, CvArr* dst );
- src1
- 1番目の入力ベクトル.
- src2
- 2番目の入力ベクトル.
- dst
- 出力ベクトル.
関数 cvCrossProduct は,二つの3次元ベクトルの外積を計算する.
dst = src1 × src2, (dst1 = src12src23 - src13src22 , dst2 = src13src21 - src11src23 , dst3 = src11src22 - src12src21).
ScaleAdd
スケーリングされた配列ともう一つの配列の和を計算する
void cvScaleAdd( const CvArr* src1, CvScalar scale, const CvArr* src2, CvArr* dst );
#define cvMulAddS cvScaleAdd
- src1
- 1番目の入力配列
- scale
- 1番目の配列のためのスケールファクタ.
- src2
- 2番目の入力配列.
- dst
- 出力配列.
関数cvScaleAddは,スケーリングされた配列ともう一つの配列の和を計算する.
dst(I)=src1(I)*scale + src2(I)
全ての配列パラメータは同じタイプで同じサイズでなくてはならない.
GEMM
汎用的な行列の乗算を行う
void cvGEMM( const CvArr* src1, const CvArr* src2, double alpha,
const CvArr* src3, double beta, CvArr* dst, int tABC=0 );
#define cvMatMulAdd( src1, src2, src3, dst ) cvGEMM( src1, src2, 1, src3, 1, dst, 0 )
#define cvMatMul( src1, src2, dst ) cvMatMulAdd( src1, src2, 0, dst )
- src1
- 1番目の入力配列.
- src2
- 2番目の入力配列.
- alpha
- 乗算結果に対するスケーリング係数.以下の説明を参照.
- src3
- 3番目の入力配列(シフト用).もしシフトしない場合はNULLにできる.
- beta
- 3番目の入力配列に対するスケーリング係数.以下の説明を参照.
- dst
- 出力配列.
- tABC
- 操作フラグ.0または以下の値の組み合わせ.
CV_GEMM_A_T - src1を転置
CV_GEMM_B_T - src2を転置
CV_GEMM_C_T - src3を転置
例:CV_GEMM_A_T+CV_GEMM_C_Tは, alpha*src1T*src2 + beta*src3Tに対応する.
関数cvGEMMは汎用的な行列の乗算を行う.
dst = alpha*op(src1)*op(src2) + beta*op(src3), ここで, op(X) は X あるいは XT
全ての行列は同じデータタイプ,同じサイズである必要がある.実数あるいは複素数の浮動小数点型の行列がサポートされている.
Transform
すべての配列要素を行列により変換する
void cvTransform( const CvArr* src, CvArr* dst, const CvMat* transmat, const CvMat* shiftvec=NULL );
- src
- 1番目の入力配列.
- dst
- 出力配列.
- transmat
- 変換行列.
- shiftvec
- オプションのシフトベクトル.
関数cvTransformは,srcの全て要素に行列変換を行い,その結果をdst に保存する.
dst(I)=transmat*src(I) + shiftvec または dst(I)k=sumj(transmat(k,j)*src(I)j) + shiftvec(k)
つまり,Nsrc個の要素をもつベクトルとして取り扱い, M×N行列transmatとシフトベクトルshiftvec を用いて, Mチャンネル配列dstの一つの要素へと変換する. shiftvec を transmatへ埋め込むという選択もある. この場合,transmatはM×N+1の行列でなければならず,最右列はシフトベクトルとして扱われる.
入力配列と出力配列は共にデプスが等しく,サイズあるいは選択されたROIのサイズが同じでなければならない.transmatとshiftvecは浮動小数点型の実数行列でなくてはならない.
この関数は,N次元点集合の幾何変換,任意の色空間の線形変換,チャンネルのシャッフル等に使用される.
PerspectiveTransform
ベクトルの透視投影変換を行う
void cvPerspectiveTransform( const CvArr* src, CvArr* dst, const CvMat* mat );
- src
- 3チャンネルの浮動小数点型入力配列.
- dst
- 3チャンネルの浮動小数点型出力配列.
- mat
- 3×3 または 4×4 の変換行列.
関数cvPerspectiveTransformは,以下のように,srcのすべての要素を2次元あるいは3次元ベクトルとして扱い,これを変換する.
(x, y, z) -> (x/w, y/w, z/w) または
(x, y) -> (x/w, y/w),
ここで,
(x, y, z, w) = mat4x4*(x, y, z, 1) または
(x, y, w) = mat3x3*(x, y, 1)
w = w (w!=0 の場合)
inf (そうでない場合)
MulTransposed
行列と転置行列の乗算を行う
void cvMulTransposed( const CvArr* src, CvArr* dst, int order, const CvArr* delta=NULL );
- src
- 入力行列.
- dst
- 出力行列.
- order
- 転置した行列をかける順番.
- delta
- オプション配列,乗算する前にsrcから引かれる.
関数cvMulTransposedはsrcとその転置行列との乗算を計算する.
この関数は,以下のように計算を行う.
dst=(src-delta)*(src-delta)T
(order=0 の場合)
dst=(src-delta)T*(src-delta)
(そうでない場合).
Trace
行列のトレースを返す
CvScalar cvTrace( const CvArr* mat );
- mat
- 入力行列.
関数cvTraceは,行列matの対角成分の和を返す.
tr(src1)=sumimat(i,i)
Transpose
行列の転置を行う
void cvTranspose( const CvArr* src, CvArr* dst );
#define cvT cvTranspose
- src
- 入力行列.
- dst
- 出力行列.
関数cvTransposeは行列srcを転置する.
dst(i,j)=src(j,i)
注釈:複素行列の場合,複素数の共役化は行わない.共役は別に計算されるべきである.例として,cvXorS のサンプルコードを参照すること.
Det
行列式を返す
double cvDet( const CvArr* mat );
- mat
- 入力行列.
関数cvDetは,正方行列matの行列式を返す. 小さい行列に対しては直接法が,大きい行列に対してはガウスの消去法が使用される. 正の行列式を持つ対称行列については,U=V=NULLとしてSVDを実行し, その後Wの対角要素の内積として行列式を計算することも可能である.
Invert
逆行列または擬似逆行列を求める
double cvInvert( const CvArr* src, CvArr* dst, int method=CV_LU );
#define cvInv cvInvert
- src
- 入力行列.
- dst
- 出力行列.
- method
- 逆行列を求める手法.
CV_LU - 最適なピボット選択によるガウスの消去法
CV_SVD - 特異値分解(SVD)
CV_SVD_SYM - 対称正定値行列のための特異値分解
関数cvInvertはsrcの逆行列を計算し,その結果をdstに入れる.
LUの場合,この関数はsrcの行列式を返す(srcは正方行列でなくてなならない). 行列式が0の場合, 逆行列は計算できずdstは0で埋められる.
SVDの場合,この関数はsrcの条件数の逆数(大きい特異値に対する小さい特異値の比)を返す. また,srcが全て0のときは0を返す. もし,srcが非正則行列の場合,SVDを用いる方法では擬似逆行列を計算する.
Solve
線形問題または最小二乗法問題を解く
int cvSolve( const CvArr* A, const CvArr* B, CvArr* X, int method=CV_LU );
- A
- 入力行列.
- B
- 線形システムの右辺.
- X
- 出力解.
- method
- 逆行列の解法.
CV_LU - 最適なピボット選択によるガウスの消去法
CV_SVD - 特異値分解
CV_SVD_SYM - 対称正定値行列のための特異値分解.
関数cvSolveは,線形問題または最小二乗問題を解く(後者は特異値分解を用いて解くことが可能である).
dst = arg minX||A*X-B||
methodにCV_LU を指定した場合,Aが正則行列であれば1を返し,そうでなければ0を返す. 後者の場合は,dstの値は有効ではない.
SVD
浮動小数点型の実数行列の特異値分解を行う
void cvSVD( CvArr* A, CvArr* W, CvArr* U=NULL, CvArr* V=NULL, int flags=0 );
- A
- 入力M×N行列.
- W
- 特異値行列の結果 (M×N または N×N)または ベクトル(N×1).
- U
- 任意の左直交行列 (M×M または M×N). もしCV_SVD_U_Tが指定された場合,上で述べた,行と列の数は入れ替わる.
- V
- 任意の右直交行列(N×N).
- flags
- 操作フラグ.0または以下の値の組み合わせ.
- CV_SVD_MODIFY_A を指定すると,計算中に行列Aの変更を行うことができる. このフラグの指定は処理速度を向上させる.
- CV_SVD_U_T means that the tranposed matrix U is returned. Specifying the flag はUの転置行列を返すことを意味する.このフラグの指定は処理速度を向上させる.
- CV_SVD_V_T はVの転置行列を返すことを意味する.このフラグの指定は処理速度を向上させる.
関数cvSVDは,行列Aを二つの直交行列と一つの対角行列の積に分解する.
A=U*W*VT
ここで,Wは特異値の対角行列であり,特異値の1次元のベクトルとしてエンコードされる.すべての特異値は非負の値を持ち,降順にソートされる (UとVの行も共に).
SVDアルゴリズムは数値的にロバストであり,その典型的な応用は,以下のようになる.
- 行列Aが正方行列で対称正定値行列として定義されている(例えば,それが共変動行列である)とき,厳密な固有値問題の解法である. このケースにおいてWは固有値のベクトルとなり,U=Vは固有ベクトルの行列となる. (したがって,固有ベクトルが必要となるときは,UまたはVの片方だけを計算すればよい).
- 方程式よりも未知数が多い線形問題(過少システム)における厳密な解法.
- 未知数よりも方程式が多い線形問題(過多システム)における最小二乗法による解法. これと前述の場合には,methodにCV_SVDを指定した関数cvSolveが実行される.
- ランク(0ではない特異値の数),条件数(最大の特異値と最小の特異値との比率),行列式(特異値の積に等しい行列式の絶対値)などの,様々な行列特徴量の高精度な計算.ここにリストされたすべての項目は U行列と V行列の計算を必要としない.
SVBkSb
特異値の後退代入を行う
void cvSVBkSb( const CvArr* W, const CvArr* U, const CvArr* V,
const CvArr* B, CvArr* X, int flags );
- W
- 特異値の行列またはベクトル.
- U
- 左直交行列(転置されているかもしれない)
- V
- 右直交行列(転置されているかもしれない)
- B
- 行列Aの擬似逆行列に乗ずるための行列.オプションのパラメータ. 省略されている場合,それは適切なサイズの単位行列であると仮定される(そのためXはAの再構成された擬似逆行列となる).
- X
- 出力行列.後退代入の結果.
- flags
- 操作フラグ.cvSVDでのflagsと一致していなければならない.
関数cvSVBkSbは,分解される行列A(cvSVDを参照)と行列Bのための後退代入を計算する.
X=V*W-1*UT*B
ここで,
W-1(i,i)=1/W(i,i) (W(i,i) > epsilon•sumiW(i,i) の場合)
0 (それ以外の場合)
また,epsilonは行列のデータタイプに依存する小さな数値である.
この関数はcvSVDと共に,cvInvert,cvSolveの内部で用いられる.これら(svd と bksb) の低レベル関数を使用する理由は,高レベル関数(inv と solve)において一時的な行列の確保を避けるためである.EigenVV
対称行列の固有値と固有ベクトルを計算する
void cvEigenVV( CvArr* mat, CvArr* evects, CvArr* evals, double eps=0 );
- mat
- 入力対称正方行列.処理中に変更される.
- evects
- 固有ベクトルの出力行列.連続した行として保存される.
- evals
- 固有値ベクトルの出力ベクトル.降順に保存される(もちろん固有値と固有ベクトルの順番は一致する).
- eps
- 対角化の精度(一般的に,DBL_EPSILON=≈10-15 で十分である).
関数cvEigenVVは,行列matの固有値と固有ベクトルを計算する.
mat*evects(i,:)' = evals(i)*evects(i,:)' (MTALAB表記)
行列matの内容はこの関数によって破壊される.
現在,この関数はcvSVDより遅く,精度も低い. そこで,matが正定値行列であることが既知のとき (例えば共変動行列)は, 行列matの固有値,固有ベクトルを求めるために(特に,固有ベクトルが必要とされない場合), cvSVDを使用することが推奨される. これは,
cvEigenVV(mat, eigenvals, eigenvects);の代わりに
cvSVD(mat, eigenvals, eigenvects, 0, CV_SVD_U_T + CV_SVD_MODIFY_A);を呼ぶということである.
CalcCovarMatrix
ベクトル集合の共変動行列を計算する
void cvCalcCovarMatrix( const CvArr** vects, int count, CvArr* cov_mat, CvArr* avg, int flags );
- vects
- 入力ベクトル.これらはすべて同じタイプで同じサイズでなくてはならない. ベクトルは1次元である必要はなく,2次元(例えば,画像)などでも構わない.
- count
- 入力ベクトルの数.
- cov_mat
- 浮動小数点型の正方な出力共変動行列.
- avg
- 入力または出力配列(フラグに依存する) - 入力ベクトルの平均ベクトル.
- flags
- 操作フラグ.以下の値の組み合わせ.
CV_COVAR_SCRAMBLED - 出力共変動行列は次のように計算される.
scale*[vects[0]-avg,vects[1]-avg,...]T*[vects[0]-avg,vects[1]-avg,...]
すなわち,共変動行列はcount×countである. そのような一般的でない共変動行列は,非常に大きなベクトル集合に対する高速な主成分分析のために使用される(例えば,顔認識のための固有顔). この「スクランブルされた」行列の固有値は,真共変動行列の固有値と一致し, そして「真の」固有ベクトルは「スクランブルされた」共変動行列の固有ベクトルから容易に計算できる.
CV_COVAR_NORMAL - 出力共変動行列は次のように計算される.
scale*[vects[0]-avg,vects[1]-avg,...]*[vects[0]-avg,vects[1]-avg,...]T
つまり,cov_matはすべての入力ベクトルの要素の合計と同じサイズの一般的な共変動行列となる. CV_COVAR_SCRAMBLEDとCV_COVAR_NORMALのどちらか一つは必ず指定されなくてはならない.
CV_COVAR_USE_AVG - このフラグが指定された場合,関数は入力ベクトルから平均を計算せず,引数で指定された平均ベクトルを使用する. 平均が何らかの方法で既に計算されている場合,または共変動行列が部分的に計算されている場合 (この場合,avgは入力ベクトルの一部の平均ではなく,全ての平均ベクトルである)に有用である.
CV_COVAR_SCALE - このフラグが指定された場合, 共変動行列は入力ベクトルの数によってスケーリングされる.
CV_COVAR_ROWS - 全ての入力ベクトルは単一の行列(vects[0])の行として保存されることを意味する. この場合,countは無視される.そしてavgは適切な大きさの1行のベクトルでなければならない.
CV_COVAR_COLS - 全ての入力ベクトルは単一の行列(vects[0])の列として保存されることを意味する. この場合,countは無視される.そしてavgは適切な大きさの1列のベクトルでなければならない.
関数cvCalcCovarMatrixは,共変動行列と,オプションで入力ベクトル集合の平均を計算する. この関数は,主成分分析やマハラノビス距離によるベクトルの比較等に用いられる.
Mahalonobis
2つのベクトルのマハラノビス距離を計算する
double cvMahalanobis( const CvArr* vec1, const CvArr* vec2, CvArr* mat );
- vec1
- 1番目の1次元入力ベクトル.
- vec2
- 2番目の1次元入力ベクトル.
- mat
- 逆共変動行列.
関数cvMahalonobisは,二つのベクトル間の重み付き距離を計算し,それを返す.
d(vec1,vec2)=sqrt( sumi,j {mat(i,j)*(vec1(i)-vec2(i))*(vec1(j)-vec2(j))} )
cvCalcCovarMatrixを用いて共変動行列が計算され, さらにcvInvert関数(行列が非正則行列である可能性があるので,methodにCV_SVDが選択されたもの)を用いて逆行列を求める.
CalcPCA
ベクトル集合の主成分分析を行う
void cvCalcPCA( const CvArr* data, CvArr* avg,
CvArr* eigenvalues, CvArr* eigenvectors, int flags );
- data
- 入力データ.それぞれのベクトルは単一行(CV_PCA_DATA_AS_ROW)か,単一列(CV_PCA_DATA_AS_COL)である.
- avg
- 平均ベクトル.関数内で計算されるか,ユーザによって与えられる.
- eigenvalues
- 出力である共変動行列の固有値.
- eigenvectors
- 出力である共変動行列の固有ベクトル(つまり,主成分).一つの行が一つのベクトルを意味する.
- flags
- 操作フラグ.以下の値の組み合わせ.
CV_PCA_DATA_AS_ROW - 行としてベクトルが保存される(つまり,あるベクトルすべての要素は連続的に保存される)
CV_PCA_DATA_AS_COL - 列としてベクトルが保存される(つまり,あるベクトル成分に属する値は連続的に保存される)
(上の2つのフラグは互いに排他的である)
CV_PCA_USE_AVG - 事前に計算された平均ベクトルを用いる
関数cvCalcPCAは,ベクトル集合の主成分分析を行う. まず,cvCalcCovarMatrixを用いて共変動行列を計算し,固有値,固有ベクトルを求める. 固有値,固有ベクトルの出力個数は,MIN(rows(data),cols(data))と等しいか,または少ない.
ProjectPCA
指定された部分空間にベクトルを投影する
void cvProjectPCA( const CvArr* data, const CvArr* avg,
const CvArr* eigenvectors, CvArr* result );
- data
- 入力データ.それぞれのベクトルは単一行か,単一列である.
- avg
- 平均ベクトル.単一行ベクトルの場合,それはdataの行として入力ベクトルが保存されていることを意味する. そうでない場合は,単一列ベクトルであり,そのときのベクトルはdataの列として保存されている.
- eigenvectors
- 固有ベクトル(主成分).一つの行が一つのベクトルを意味する.
- result
- 出力である分解係数の行列.行の数はベクトルの数と同じでなくてはならない. 列の数はeigenvectorsの列の数より小さいか同じでなくてはならない. 列の数が少ない場合,入力ベクトルは,第cols(result)主成分までを基底とする部分空間に投影される.
関数cvProjectPCAは,入力ベクトルを正規直交基底(eigenvectors)で表現される部分空間に投影する. 内積を計算する前に,avgベクトルが入力ベクトルから減算される.
result(i,:)=(data(i,:)-avg)*eigenvectors' // CV_PCA_DATA_AS_ROW 配置の場合
BackProjectPCA
投影係数から元のベクトルを再構築する
void cvBackProjectPCA( const CvArr* proj, const CvArr* avg,
const CvArr* eigenvects, CvArr* result );
- proj
- 入力データ.cvProjectPCAのresultと同様のフォーマット.
- avg
- 平均ベクトル.もし単一行ベクトルの場合,出力ベクトルがresultの行として保存されていることを意味する. そうでない場合は,単一列ベクトルであり,そのときはresultの列として保存される.
- eigenvectors
- 固有ベクトル(主成分).一つの行が一つのベクトルを意味する.
- result
- 出力である再構築されたベクトルの行列.
関数cvBackProjectPCAは,投影係数からベクトルを再構築する.
result(i,:)=proj(i,:)*eigenvectors + avg // CV_PCA_DATA_AS_ROW 配置の場合
数学関数(Math Functions)
Round, Floor, Ceil
浮動小数点型の変数を整数型に変換する
int cvRound( double value ); int cvFloor( double value ); int cvCeil( double value );
- value
- 浮動小数点型の入力値.
関数cvRound, cvFloor,cvCeilは,浮動小数点型の入力値を丸め手法(Round, Floor, Ceil)の一つを利用して整数型に変換する.cvRoundは,引数に最も近い整数値を返す.cvFloorは,引数より大きくない最大の整数値を返す.cvCeilは,引数より小さくない最小の整数値を返す.いくつかのアーキテクチャにおいて,これらの関数はC言語の標準的なキャスト演算よりも非常に高速である. 引数の絶対値が231より大きい場合,結果は求まらない.また,特別な値(±Inf, NaN)は扱うことができない.
Sqrt
平方根を計算する
float cvSqrt( float value );
- value
- 浮動小数点型の入力値.
関数cvSqrtは,引数の平方根を計算する. 引数が負の値の場合,結果は求まらない.
InvSqrt
平方根の逆数を計算する
float cvInvSqrt( float value );
- value
- 浮動小数点型の入力値.
関数cvInvSqrtは,引数の平方根の逆数を計算する.これは,通常,1./sqrt(value)を計算するよりも高速である. 引数が0または負の値のとき,結果は求まらない.また,特別な値(±Inf, NaN)は扱うことができない.
Cbrt
立方根を計算する
float cvCbrt( float value );
- value
- 浮動小数点型の入力値.
関数cvCbrtは,引数の立方根を計算する.これは,通常,pow(value,1./3)を計算するよりも高速である. 一方,負の引数も正しく処理される.また,特別な値(±Inf, NaN)は扱うことができない.
FastArctan
2次元のベクトルの角度を計算する
float cvFastArctan( float y, float x );
- x
- 2次元ベクトルのx座標.
- y
- 2次元ベクトルのy座標.
関数cvFastArctanは入力された2次元ベクトルの角度を計算する. 角度は度(degree)単位で扱われ,0°から360°の範囲で変化する.精度は ~0.1°.
IsNaN
引数が数値でないかどうかを確認する
int cvIsNaN( double value );
- value
- 浮動小数点型の入力値.
関数cvIsNaNは,引数が数値(IEEE754 standard に定義されている)でなければ1を返し,その他の場合は0を返す.
IsInf
引数が無限大であるかどうかを確認する
int cvIsInf( double value );
- value
- 浮動小数点型の入力値.
関数cvIsInfは,引数が±無限大(IEEE754 standard に定義されている)であれば1を返し,その他の場合は0を返す.
CartToPolar
2次元ベクトルの角度と大きさを計算する
void cvCartToPolar( const CvArr* x, const CvArr* y, CvArr* magnitude,
CvArr* angle=NULL, int angle_in_degrees=0 );
- x
- x座標の配列.
- y
- y座標の配列.
- magnitude
- 大きさの出力配列.必要でなければNULLがセットされる.
- angle
- 角度の出力配列.必要でなければNULLがセットされる.角度はラジアン(0..2π),または度(0..360°)で測定される.
- angle_in_degrees
- 角度を表すためにラジアン(デフォルト値),または度のどちらを用いるかを示すフラグ.
関数cvCartToPolarは,2次元ベクトル(x(I),y(I))の大きさと角度のどちらか,またはその両方を計算する.
magnitude(I)=sqrt( x(I)2+y(I)2 ), angle(I)=atan( y(I)/x(I) )
角度は≈0.1°の精度で計算される.(0,0)の場合,角度は0にセットされる.
PolarToCart
極座標形式で表現された2次元ベクトルのデカルト座標を計算する
void cvPolarToCart( const CvArr* magnitude, const CvArr* angle,
CvArr* x, CvArr* y, int angle_in_degrees=0 );
- magnitude
- 大きさの配列.NULLの場合,大きさはすべて1と仮定される.
- angle
- 角度の配列.単位はラジアン,または度である.
- x
- x座標の出力配列で,必要でなければNULLがセットされる.
- y
- y座標の出力配列で,必要でなければNULLがセットされる.
- angle_in_degrees
- このフラグは角度を表すために,ラジアン(デフォルト値)または度のどちらを用いるかを示す.
関数cvPolarToCartは,すべてのベクトルのx座標とy座標のどちらか, またその両方のmagnitude(I)*exp(angle(I)*j), j=sqrt(-1)を計算する.
x(I)=magnitude(I)*cos(angle(I)), y(I)=magnitude(I)*sin(angle(I))
Pow
すべての配列要素を累乗する
void cvPow( const CvArr* src, CvArr* dst, double power );
- src
- 入力配列.
- dst
- 出力配列.入力と同じタイプでなければならない.
- power
- 累乗の指数.
関数cvPowは,入力配列のすべての要素を以下のようにp乗する.
dst(I)=src(I)p, (p が整数の場合),
dst(I)=abs(src(I))p, (それ以外の場合)
累乗の指数が整数でない場合は,入力配列要素の絶対値が用いられる. しかし,いくつかの追加処理によって負の値に対しても正しい値を得ることができる.以下に,配列要素の立方根を計算する例を示す.
CvSize size = cvGetSize(src); CvMat* mask = cvCreateMat( size.height, size.width, CV_8UC1 ); cvCmpS( src, 0, mask, CV_CMP_LT ); /* 負の要素を検出 */ cvPow( src, dst, 1./3 ); cvSubRS( dst, cvScalarAll(0), dst, mask ); /* 負の入力に対する結果を反転する */ cvReleaseMat( &mask );
整数や0.5,-0.5など一部のpowerの値に対しては,特に高速なアルゴリズムが用いられる.
Exp
すべての配列要素について自然対数の底(ネイピア数)eのべき乗を求める
void cvExp( const CvArr* src, CvArr* dst );
- src
- 入力配列.
- dst
- 出力配列.倍精度の浮動小数点型(double),または入力配列と同じタイプでなければならない.
関数cvExpは入力配列のすべての要素に対して,それを指数とする自然対数の底eのべき乗を求める.
dst(I)=exp(src(I))
最大相対誤差は≈7e-6.現在,この関数は,指数表現されない(denormalize)値を出力時に0に変換する.
Log
すべての配列要素の絶対値の自然対数を計算する
void cvLog( const CvArr* src, CvArr* dst );
- src
- 入力配列.
- dst
- 出力配列.倍精度の浮動小数点型(double),または入力配列と同じタイプでなければならない
関数cvLogは,入力配列のすべての要素の絶対値の自然対数を計算する.
dst(I)=log(abs(src(I))), (src(I)!=0の場合) dst(I)=C, (src(I)=0の場合)ここで,C は大きな負の数である (現在の実装では≈-700).
SolveCubic
3次方程式の実根を求める
int cvSolveCubic( const CvMat* coeffs, CvMat* roots );
- coeffs
- 式の係数で,3個または4個の要素を持つ配列.
- roots
- 実根の出力配列.三つの要素を持つ.
関数cvSolveCubicは,3次方程式の実根を求める.
coeffs[0]*x3 + coeffs[1]*x2 + coeffs[2]*x + coeffs[3] = 0 (coeffsが4要素のベクトルの場合) or x3 + coeffs[0]*x2 + coeffs[1]*x + coeffs[2] = 0 (coeffsが3要素のベクトルの場合)
この関数は求めた実根の数を返し,配列rootsに根を格納する. 一つの根しかない場合,出力配列はには0が追加される.
乱数生成(Random Number Generation)
RNG
乱数生成器の状態を初期化する
CvRNG cvRNG( int64 seed=-1 );
- seed
- ランダムシーケンスを開始するために使用される64ビットの数値.
関数cvRNGは乱数生成器を初期化し,その状態を返す. 状態へのポインタは関数cvRandInt,cvRandReal,cvRandArrに渡される.現在の実装では,multiply-with-carry RNGが利用されている.
RandArr
配列を乱数で埋め,RNGの状態を更新する
void cvRandArr( CvRNG* rng, CvArr* arr, int dist_type, CvScalar param1, CvScalar param2 );
- rng
- cvRNGによって初期化されたRNGの状態.
- arr
- 出力配列.
- dist_type
- 分布のタイプ.
CV_RAND_UNI - 一様分布
CV_RAND_NORMAL - 正規分布(ガウス分布)
- param1
- 分布の第一パラメータ.一様分布では,発生する乱数の下限値(この値を含む)である. 正規分布では,乱数の平均値である.
- param2
- 分布の第二パラメータ.一様分布では,発生する乱数の上限値(この値は含まない)である. 正規分布では,乱数の標準偏差である.
関数cvRandArrは,一様または正規分布の乱数で出力配列を埋める. 正規分布の浮動小数点型の値を2次元配列中のランダムな位置に加算する例を以下に示す.
/* noisy_screenを,「めちゃくちゃな」浮動小数点型の2次元配列にする */
CvRNG rng_state = cvRNG(0xffffffff);
int i, pointCount = 1000;
/* 点の座標の配列を確保する */
CvMat* locations = cvCreateMat( pointCount, 1, CV_32SC2 );
/* ランダムな点の値の配列 */
CvMat* values = cvCreateMat( pointCount, 1, CV_32FC1 );
CvSize size = cvGetSize( noisy_screen );
cvRandInit( &rng_state,
0, 1, /* 現在はダミーパラメータを使用し,さらにそれらを調整する */
0xffffffff /* ここでは,固定された種を使用する */,
CV_RAND_UNI /* 一様分布の指定 */ );
/* 位置の初期化 */
cvRandArr( &rng_state, locations, CV_RAND_UNI,
cvScalar(0,0,0,0), cvScalar(size.width,size.height,0,0) );
/* 正規分布値を生成するRNGを作るためにRNGを修正する */
rng_state.disttype = CV_RAND_NORMAL;
cvRandSetRange( &rng_state,
30 /* 偏差 */,
100 /* 点の明るさの平均 */,
-1 /* すべての次元を初期化する */ );
/* 値を生成 */
cvRandArr( &rng_state, values, CV_RAND_NORMAL,
cvRealScalar(100), // average intensity
cvRealScalar(30) // deviation of the intensity
);
/* 点の集合 */
for( i = 0; i < pointCount; i++ )
{
CvPoint pt = *(CvPoint*)cvPtr1D( locations, i, 0 );
float value = *(float*)cvPtr1D( values, i, 0 );
*((float*)cvPtr2D( noisy_screen, pt.y, pt.x, 0 )) += value;
}
/* 一時的な配列を解放することを忘れないように */
cvReleaseMat( &locations );
cvReleaseMat( &values );
/* RNG状態は解放の必要はない */
RandInt
32ビット符号なし整数を返し,RNGを更新する
unsigned cvRandInt( CvRNG* rng );
- rng
- RandInitによって初期化され, オプションでRandSetRangeによってカスタマイズされたRNGの状態(後者の関数は,この関数の結果に影響を及ぼさない).
関数cvRandIntは,一様分布した32ビット符号なし整数型の乱数を返し,RNGの状態を更新する. これは,C言語のランタイムライブラリでいうところのrand() 関数に類似している. しかし,rand()が0からRAND_MAX(2**16 または 2**32,プラットホームに依存する)までの数を返すの対して,この関数では常に32ビットの数を生成する. この関数は点座標やパッチサイズ,テーブルインデックスなどのスカラーの乱数を生成するのに役立つ. ここで,ある範囲の整数は剰余演算によって生成され,浮動小数点型の数は,指定範囲を0..1にスケーリングすることで生成することができる. cvRandIntを利用して,前述の例を書き直したものを以下に示す.
/* 入力とタスクは前のサンプルと同じである. */
CvRNG rng_state = cvRNG(0xffffffff);
int i, pointCount = 1000;
/* ... - ここで配列は確保されない */
CvSize size = cvGetSize( noisy_screen );
/* オーバヘッドを減らすため,正規分布した数値のためのバッファを生成する */
#define bufferSize 16
float normalValueBuffer[bufferSize];
CvMat normalValueMat = cvMat( bufferSize, 1, CV_32F, normalValueBuffer );
int valuesLeft = 0;
for( i = 0; i < pointCount; i++ )
{
CvPoint pt;
/* ランダムな点の生成 */
pt.x = cvRandInt( &rng_state ) % size.width;
pt.y = cvRandInt( &rng_state ) % size.height;
if( valuesLeft <= 0 )
{
/* バッファが空の場合,正規分布した数値でバッファを埋める */
cvRandArr( &rng_state, &normalValueMat,
CV_RAND_NORMAL, cvRealScalar(100), cvRealScalar(30) );
valuesLeft = bufferSize;
}
*((float*)cvPtr2D( noisy_screen, pt.y, pt.x, 0 ) = normalValueBuffer[--valuesLeft];
}
/* 行列のヘッダとデータはスタックに持っているため,normalValueMatを解放する必要はない.
これは小さい固定サイズの行列で実行する際に,良く知られている効果的な方法である*/
RandReal
浮動小数点型の乱数を返し,RNGを更新する
double cvRandReal( CvRNG* rng );
- rng
- cvRNGによって初期化された,RNGの状態.
関数cvRandRealは,0から1(1は含まれない)の範囲に一様分布する浮動小数点型の乱数を返す.
離散変換(Discrete Transforms)
DFT
1次元あるいは2次元浮動小数点型配列に対して離散フーリエ変換(DFT),逆離散フーリエ変換(IDFT)を行う
#define CV_DXT_FORWARD 0
#define CV_DXT_INVERSE 1
#define CV_DXT_SCALE 2
#define CV_DXT_ROWS 4
#define CV_DXT_INV_SCALE (CV_DXT_SCALE|CV_DXT_INVERSE)
#define CV_DXT_INVERSE_SCALE CV_DXT_INV_SCALE
void cvDFT( const CvArr* src, CvArr* dst, int flags, int nonzero_rows=0 );
- src
- 入力配列(実数または複素数).
- dst
- 入力配列と同じサイズ・タイプの出力配列.
- flags
- 変換フラグ.以下の値の組み合わせ.
CV_DXT_FORWARD - 1次元または2次元の順変換を行う.結果のスケーリングは行わない.
CV_DXT_INVERSE - 1次元または2次元の逆変換を行う.結果のスケーリングは行わない. CV_DXT_FORWARD と CV_DXT_INVERSE は,もちろん同時には指定できない.
CV_DXT_SCALE - 結果を配列要素数で割り,スケーリングする.通常は CV_DXT_INVERSE と同時に用いる.ショートカットとして CV_DXT_INV_SCALE を用いても良い.
CV_DXT_ROWS - 入力配列のそれぞれの行に対して独立に,順変換あるいは逆変換を行う. このフラグは複数のベクトルの同時変換を許可し,オーバーヘッド(一つの計算の何倍も大きくなることもある)を減らすためや,3次元以上の高次元に対して変換を行うために使用される. - nonzero_rows
- 入力配列の非0である行の数(2次元順変換の場合),あるいは出力配列で注目する行の数(2次元逆変換の場合). この値が負,0,あるいは行の数より大きい場合は無視される. このパラメータにより,DFTを用いて2次元の畳み込みや相関演算を行う際の計算速度が向上する.詳しくは,以下のサンプルを参照.
関数 cvDFT は,以下に示すように1次元あるいは2次元浮動小数点型配列の順変換・逆変換を行う.
N個の要素を持つ1次元ベクトルのフーリエ変換: y = F(N) • x, ここで, F(N)jk=exp(-i • 2Pi • j • k/N),i=sqrt(-1) N個の要素を持つ1次元ベクトルの逆フーリエ変換: x'= (F(N))-1 • y = conj(F(N)) • y x = (1/N) • x M × N個の要素を持つ2次元ベクトルのフーリエ変換: Y = F(M)• X •F(N) M × N個の要素を持つ2次元ベクトルの逆フーリエ変換: X'= conj(F(M))• Y • conj(F(N)) X = (1/(M • N)) • X'
IPLで用いられる,実数(シングルチャンネル)packedフォーマットのデータが,フーリエ変換の結果あるいは逆フーリエ変換の入力を表現するために用いられる.
Re Y0,0 Re Y0,1 Im Y0,1 Re Y0,2 Im Y0,2 ... Re Y0,N/2-1 Im Y0,N/2-1 Re Y0,N/2 Re Y1,0 Re Y1,1 Im Y1,1 Re Y1,2 Im Y1,2 ... Re Y1,N/2-1 Im Y1,N/2-1 Re Y1,N/2 Im Y1,0 Re Y2,1 Im Y2,1 Re Y2,2 Im Y2,2 ... Re Y2,N/2-1 Im Y2,N/2-1 Im Y2,N/2 ............................................................................................ Re YM/2-1,0 Re YM-3,1 Im YM-3,1 Re YM-3,2 Im YM-3,2 ... Re YM-3,N/2-1 Im YM-3,N/2-1 Re YM-3,N/2 Im YM/2-1,0 Re YM-2,1 Im YM-2,1 Re YM-2,2 Im YM-2,2 ... Re YM-2,N/2-1 Im YM-2,N/2-1 Im YM-2,N/2 Re YM/2,0 Re YM-1,1 Im YM-1,1 Re YM-1,2 Im YM-1,2 ... Re YM-1,N/2-1 Im YM-1,N/2-1 Im YM-1,N/2
注釈:N が偶数なら最終列が存在し,M が偶数なら最終行が存在する.
1次元実数変換の場合,結果は上の行列の1行目のようになる.
DFTを用いた2次元畳み込みの計算
CvMat* A = cvCreateMat( M1, N1, CV_32F );
CvMat* B = cvCreateMat( M2, N2, A->type );
// 畳み込み結果の一部(abs(M2-M1)+1×abs(N2-N1)+1)のみを持つ可能性もある
CvMat* conv = cvCreateMat( A->rows + B->rows - 1, A->cols + B->cols - 1, A->type );
// AとBを初期化
...
int dft_M = cvGetOptimalDFTSize( A->rows + B->rows - 1 );
int dft_N = cvGetOptimalDFTSize( A->cols + B->cols - 1 );
CvMat* dft_A = cvCreateMat( dft_M, dft_N, A->type );
CvMat* dft_B = cvCreateMat( dft_M, dft_N, B->type );
CvMat tmp;
// Aを dft_Aにコピーし,dft_A の右部残りを0で埋める
cvGetSubRect( dft_A, &tmp, cvRect(0,0,A->cols,A->rows));
cvCopy( A, &tmp );
cvGetSubRect( dft_A, &tmp, cvRect(A->cols,0,dft_A->cols - A->cols,A->rows));
cvZero( &tmp );
// 以下のcvDFT()では,パラメータnonzero_rowsを用いているため,
// dft_Aの下部を0で埋める必要はない
cvDFT( dft_A, dft_A, CV_DXT_FORWARD, A->rows );
// 2番目の配列に対しても同様に繰り返す
cvGetSubRect( dft_B, &tmp, cvRect(0,0,B->cols,B->rows));
cvCopy( B, &tmp );
cvGetSubRect( dft_B, &tmp, cvRect(B->cols,0,dft_B->cols - B->cols,B->rows));
cvZero( &tmp );
// 以下のcvDFT()では,パラメータnonzero_rowsを用いているため,
// dft_Bの下部を0で埋める必要はない
cvDFT( dft_B, dft_B, CV_DXT_FORWBRD, B->rows );
cvMulSpectrums( dft_A, dft_B, dft_A, 0 /* 畳み込みではなく相関を得るためには
CV_DXT_MUL_CONJ を指定する */ );
cvDFT( dft_A, dft_A, CV_DXT_INV_SCALE, conv->rows ); // 上部のみを計算する
cvGetSubRect( dft_A, &tmp, cvRect(0,0,conv->cols,conv->rows) );
cvCopy( &tmp, conv );
GetOptimalDFTSize
与えられたベクトルのサイズに対する最適なDFTのサイズを返す
int cvGetOptimalDFTSize( int size0 );
- size0
- ベクトルのサイズ.
関数 cvGetOptimalDFTSize は,size0以上の最小値N を返し, 得られたサイズNのベクトルに対するDFTは高速に計算できる. 現在の実装では,ある p, q, r について,N=2p×3q×5r.
size0 が非常に大きな値(INT_MAX に非常に近い)の場合,この関数は負の値を返す.
MulSpectrums
二つのフーリエスペクトラムの要素ごとの乗算を行う
void cvMulSpectrums( const CvArr* src1, const CvArr* src2, CvArr* dst, int flags );
- src1
- 1番目の入力配列.
- src2
- 2番目の入力配列.
- dst
- 入力配列と同じタイプ・サイズの出力配列.
- flags
- 以下の値の組み合わせ.
CV_DXT_ROWS - 配列の各行を個別のスペクトラムとして扱う (cvDFT のパラメータを参照).
CV_DXT_MUL_CONJ - 乗算の前に2番目の入力配列の共役を計算する
関数 cvMulSpectrums は,実フーリエ変換あるいは複素フーリエ変換の結果として得られた二つのCCS-packed行列,または複素行列の要素ごとの乗算を行う.
この関数とcvDFTを共に用いることで,二つの配列の高速な畳み込み計算が可能である.
DCT
1次元あるいは2次元浮動小数点型配列の順方向・逆方向離散コサイン変換を行う
#define CV_DXT_FORWARD 0
#define CV_DXT_INVERSE 1
#define CV_DXT_ROWS 4
void cvDCT( const CvArr* src, CvArr* dst, int flags );
- src
- 入力配列(実数の1次元あるいは2次元配列).
- dst
- 入力と同じサイズ・タイプの出力配列.
- flags
- 変換フラグ.以下の値の組み合わせ.
CV_DXT_FORWARD - 1次元あるいは2次元の順変換.
CV_DXT_INVERSE - 1次元あるいは2次元の逆変換.
CV_DXT_ROWS - 入力配列のそれぞれの行に対して,独立に順変換あるいは逆変換を行う. このフラグは複数ベクトルの同時変換を許可し, オーバーヘッド(一つの計算の何倍も大きくなることもある)を減らすためや,3次元以上の高次元に対して変換を行うために使用される.
関数 cvDCT は以下のように,1次元あるいは2次元浮動小数点型配列に対して順方向・逆方向離散コサイン変換を行う.
N個の要素を持つ1次元ベクトルの順方向コサイン変換: y = C(N)•x, ここで C(N)jk=sqrt((j==0?1:2)/N)•cos(Pi•(2k+1)•j/N) N個の要素を持つ1次元ベクトルの逆方向コサイン変換: x = (C(N))-1•y = (C(N))T•y M×N 個の要素を持つ2次元ベクトルの順方向コサイン変換: Y = (C(M))•X•(C(N))T M×N 個の要素を持つ2次元ベクトルの逆方向コサイン変換: X = (C(M))T•Y•C(N)
動的構造体(Dynamic Structures)
メモリストレージ(Memory Storages)
CvMemStorage
動的に拡張可能なメモリストレージ
typedef struct CvMemStorage
{
struct CvMemBlock* bottom;/* 最初に確保されたブロック */
struct CvMemBlock* top; /* 新たなブロックを確保する場所 */
struct CvMemStorage* parent; /* 現在のメモリブロック − スタックの先頭 */
int block_size; /* ブロックの大きさ */
int free_space; /* topブロック内の自由領域(バイト単位) */
} CvMemStorage;
メモリストレージは低レベルの構造体で,動的に拡張可能なデータ構造を持ち,シーケンスや輪郭,グラフ,細分化などに使われる. これは同じサイズのメモリブロックのリストとして編成されている. bottomフィールドはブロックのリストの先頭,topは現在使われているブロックを意味するが, リストの最後のブロックは必ずしも必要ではない.後者(ここではtop)以外のbottomからtopまでのブロックは全て占有されている. topを除くtopから最後までのすべてのブロックは空き領域で,topブロック自体は部分的に占有されている. free_spaceは,topの後ろに残されているバイト単位で示された自由領域を意味する.
関数cvMemStorageAllocで明示的に, もしくはcvSeqPushや cvGraphAddEdge などの高レベル関数によって間接的に確保された新たなメモリ領域は,そこに納まる場合には常に現在のブロックの最後に確保される. 確保後free_spaceは,適切なアライメントを保持するために,確保したバッファサイズにパディングを加えた分ずつ減らされる. 確保されたバッファがtopの利用可能な領域に納まらない場合, リストの次のストレージブロックがtopとして用いられ, free_spaceは確保前の全ブロックサイズにリセットされる.
もし空きブロックがない場合,新しいブロックが確保され (または親から借りて,cvCreateChildMemStorageを参照), リストの最後に追加される.このようにこのストレージはスタックとして振る舞い, bottomがスタックの底, topとfree_spaceのペアがスタックの先頭を示す. スタックの先頭はcvSaveMemStoragePosで保存, cvRestoreMemStoragePosで復元, cvClearStorageでリセットされる.
CvMemBlock
メモリストレージブロック
typedef struct CvMemBlock
{
struct CvMemBlock* prev;
struct CvMemBlock* next;
} CvMemBlock;
typedef struct CvMemBlock
{
struct CvMemBlock* prev;
struct CvMemBlock* next;
} CvMemBlock;
構造体CvMemBlockは,メモリストレージの1ブロックを表現する. 実際のメモリブロックのデータはヘッダの後にあり, メモリブロックのi番目のバイトは((char*)(mem_block_ptr+1))[i]で取り出すことができる. しかし通常,直接アクセスする必要はない.
CvMemStoragePos
メモリストレージの位置
typedef struct CvMemStoragePos
{
CvMemBlock* top;
int free_space;
} CvMemStoragePos;
この構造体はスタックの先頭位置を保持しており, cvSaveMemStoragePosで保存, cvRestoreMemStoragePosで復元できる.
CreateMemStorage
メモリストレージを生成する
CvMemStorage* cvCreateMemStorage( int block_size=0 );
- block_size
- ストレージブロックのバイト単位のサイズ.0の場合,デフォルト値(現在は≈64K)が使われる.
関数cvCreateMemStorageはメモリストレージを生成し,そのポインタを返す.初期状態ではストレージは空である. block_sizeを除くヘッダのフィールドは全て0に設定されている.
CreateChildMemStorage
子メモリストレージを生成する
CvMemStorage* cvCreateChildMemStorage( CvMemStorage* parent );
- parent
- 親メモリストレージ.
関数 cvCreateChildMemStorageは,メモリ確保/解放機構の違いを除いて, 単純なメモリストレージに似た子メモリストレージを生成する. 子ストレージが新しいブロックをブロックリストに追加する必要がある場合, 子は親からブロックを取り出すことを試みる. 親に占有されていない利用可能な最初のブロックが取り出され,その部分は親のブロックリストから排除される. 利用可能なブロックがない場合,もし親の親が存在すれば,親はそこからブロックを確保するか借りる. つまり,それぞれのストレージが別のストレージの親や子になるような,チェインやさらに複雑な構造のメモリストレージが可能になる. 子ストレージが解放されるかクリアされた場合,その全てのブロックは親に返される.別の見方をすると,子ストレージは単純なストレージと同じである.
子ストレージは以下の状況において有用である.幾つかのストレージに分かれて存在する動的データを処理して, その結果を同じストレージに置く必要があるような状況を想像してほしい. 最も単純に,一時的なデータを入出力データと同じストレージに置く方法では,処理後のストレージは以下のようになる.
子ストレージを利用せずに動的なデータ処理を行った場合
このようにストレージの中央にごみが残ってしまう. しかし処理の始めに子メモリストレージを生成して,一時的なデータをそこに書き込み,最後に解放した場合,ごみは入力/出力ストレージに残らない.
子ストレージを利用して動的なデータ処理を行った場合
ReleaseMemStorage
メモリストレージを解放する
void cvReleaseMemStorage( CvMemStorage** storage );
- storage
- 解放するストレージのポインタ.
関数cvReleaseMemStorageは,ストレージの全メモリブロックを解放し,もし親がいれば親に返す. その際にストレージヘッダも解放され,ストレージへのポインタもクリアされる. 全ての子ストレージは親を解放する前に解放しておく必要がある.
ClearMemStorage
メモリストレージをクリアする
void cvClearMemStorage( CvMemStorage* storage );
- storage
- メモリストレージ.
関数cvClearMemStorageは,ストレージの先頭(空き領域の境界)を,一番最初に戻す. この関数はメモリを解放しない.もしストレージが親を持つ場合,この関数は親に全てのブロックを返す.
MemStorageAlloc
ストレージ内にメモリバッファを確保する
void* cvMemStorageAlloc( CvMemStorage* storage, size_t size );
- storage
- メモリストレージ.
- size
- バッファサイズ.
関数cvMemStorageAllocは,ストレージ内にメモリバッファを確保する. バッファサイズは,ストレージのブロックサイズを超えてはいけない. 超えた場合にはランタイムエラーが発生する. バッファアドレスは,CV_STRUCT_ALIGN(現時点では=sizeof(double))バイトにアライメントされる.
MemStorageAllocString
ストレージ内にテキスト文字列を確保する
typedef struct CvString
{
int len;
char* ptr;
}
CvString;
CvString cvMemStorageAllocString( CvMemStorage* storage, const char* ptr, int len=-1 );
- storage
- メモリストレージ.
- ptr
- 文字列.
- len
- 文字列の長さ(終端の'¥0'は数えない).負の場合,この関数が長さを計算する.
関数cvMemStorageAllocStringは,メモリストレージ内に文字列のコピーを生成する. この関数はユーザが渡した,もしくは計算された文字列の長さとコピーされた文字列へのポインタを持つ構造体を返す.
SaveMemStoragePos
メモリストレージの位置を保存する
void cvSaveMemStoragePos( const CvMemStorage* storage, CvMemStoragePos* pos );
- storage
- メモリストレージ.
- pos
- 出力するストレージ先頭の位置.
関数cvSaveMemStoragePosは,ストレージの先頭の現在位置をパラメータposに保存する. 関数cvRestoreMemStoragePosで,この位置を復元することができる.
RestoreMemStoragePos
メモリストレージの位置を復元する
void cvRestoreMemStoragePos( CvMemStorage* storage, CvMemStoragePos* pos );
- storage
- メモリストレージ.
- pos
- 新しいストレージの先頭位置.
関数 cvRestoreMemStoragePosは,パラメータposからストレージの先頭を復元する. この関数と関数cvClearMemStorageは,メモリブロック内で占有されたメモリを解放する唯一の方法である. ストレージの占有部分の途中のメモリを解放する方法は無いことに十分注意すること.
シーケンス(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 は,読み込み位置を絶対位置か相対位置で表された位置に移動する.
セット(Sets)
CvSet
ノードの集合
typedef struct CvSetElem
{
int flags; /* 空きノードなら負,他の場合0か正の値 */
struct CvSetElem* next_free; /* 空きノードの場合,次の空きノードへのポインタ */
}
CvSetElem;
#define CV_SET_FIELDS() ¥
CV_SEQUENCE_FIELDS() /* CvSeqから継承する */ ¥
struct CvSetElem* free_elems; /* 空きノードのリスト */
typedef struct CvSet
{
CV_SET_FIELDS()
} CvSet;
構造体CvSet は,OpenCVの疎なデータ構造の基本である.
上述の宣言のとおり,CvSetはCvSeqを継承し, それにfree_elems(空きノードリスト)を加えたものである. 空きかそうでないかが記述されたセットの各ノードは,内部的なシーケンスの要素である. 密なシーケンスの要素に対するような制限はないが,セット(と,ここから派生する構造体)の要素は整数型のフィールドで始める必要があり, 構造体CvSetElemに合致させる事ができなければならない. なぜなら,これら二つのフィールド(整数とそれに続くポインタ)は,空きノードリストを持つノードセットの構成に必要だからである. 空きノードの場合,flags フィールドは負の値となる(フィールドの最上位ビット(MSB)がセットされている). そしてnext_freeは,次の空きノードを指す(先頭の空きノードは,CvSetのfree_elemsフィールドから参照される).ノードが使用されている場合,flags フィールドは0以上の値で,(set_elem->flags & CV_SET_ELEM_IDX_MASK) の式を用いて取り出されるようなノードインデックスを持つ.ノードの残り部分(next_free)はユーザによって決められる. 特に,使用されているノードは空きノードのようにリンクされていないので,2番目のフィールド(next_free)は, このようなリンクや他の目的のために用いることができる. マクロCV_IS_SET_ELEM(set_elem_ptr)は,指定したノードが使用されているかどうかを判断するために利用することができる.
最初,セットとリストは空である.セットから新しいノード要求があった場合,空きノードリストからノードが取り出され,その後リストは更新される. 空きノードリストが空の場合は,新しいシーケンスブロックが確保され,ブロック内のすべてのノードが空きノードリストに追加される. 従って,セットの total フィールドには,使用されているノード数と空きノードの数の合計が入る. 使用されていたノードが解放されたときには,空きノードリストに加えられる.最後に解放されるノードは,最初に使用されたものである.
OpenCVにおいて CvSet は,グラフ(CvGraph), 疎な多次元配列(CvSparseMat), 平面の細分割(CvSubdiv2D)などを表現するために使用される.
CreateSet
空のセットを生成する
CvSet* cvCreateSet( int set_flags, int header_size,
int elem_size, CvMemStorage* storage );
- set_flags
- 生成するセットのタイプ.
- header_size
- セットのヘッダのサイズ(sizeof(CvSet)以上).
- elem_size
- セットの要素のサイズ(CvSetElem 以上).
- storage
- セットのためのコンテナ.
関数cvCreateSetは指定されたヘッダのサイズと要素のサイズを持つ空のセットを生成し,そのセットへのポインタを返す. この関数は cvCreateSeq に多少の処理を追加したものに過ぎない.
SetAdd
セットに新しいノード(要素)を追加する
int cvSetAdd( CvSet* set_header, CvSetElem* elem=NULL, CvSetElem** inserted_elem=NULL );
- set_header
- セット.
- elem
- オプションの入力引数.挿入する要素. NULLでない場合,新たに確保したノードにデータをコピーする (コピーした後,先頭の整数フィールドの最上位ビットはクリアされる).
- inserted_elem
- オプションの出力引数.割り当てられた要素へのポインタ.
関数cvSetAddは,新しいノードを割り当てる. オプションとして入力要素データをノードにコピーし,ノードへのポインタとインデックスを返す. インデックス値は,ノードのflagsフィールドの下位のビットから得る.この関数はO(1)の計算量を持つが, セットのノードを確保するためのより高速な関数が存在する(cvSetNewを参照).
SetRemove
セットから要素を削除する
void cvSetRemove( CvSet* set_header, int index );
- set_header
- セット.
- index
- 削除する要素のインデックス.
関数cvSetRemoveは,セットから指定されたインデックスの要素を取り除く. もし指定された場所のノードがない場合,この関数は何もしない.この関数はO(1)の計算量を持つ, しかし,既に取り除く要素の場所が既知である場合は,cvSetRemoveByPtr の方が高速である.
SetNew
セットに要素を加える(高速版)
CvSetElem* cvSetNew( CvSet* set_header );
- set_header
- セット.
関数cvSetNewは,cvSetAdd の高速インライン処理バージョンである. この関数は新しいノードを確保し,インデックスではなくノードへのポインタを返す.
SetRemoveByPtr
ポインタで指定したセットの要素を削除する
void cvSetRemoveByPtr( CvSet* set_header, void* elem );
- set_header
- セット.
- elem
- 削除される要素.
関数cvSetRemoveByPtrは,要素のポインタを用いる cvSetRemove の高速インライン処理バージョンである. この関数はノードが使用されているかそうでないかを確認しない.そのため,ユーザは注意して使用しなければならない.
GetSetElem
インデックスによってセットの要素を検索する
CvSetElem* cvGetSetElem( const CvSet* set_header, int index );
- set_header
- セット.
- index
- シーケンスの中のセットの要素のインデックス.
関数cvGetSetElemは,インデックスによってセットの要素を検索する. この関数は見つけた要素へのポインタを返す,インデックスが無効であるか,対応するノードが空きの場合は0を返す. この関数は負のインデックスをサポートし,これはノードの場所を得るために cvGetSeqElem を用いる際に使われる.
ClearSet
セットをクリアする
void cvClearSet( CvSet* set_header );
- set_header
- クリアされるセット.
関数cvClearSetは,セットからすべての要素を取り除く.これはO(1)の計算量を持つ.
グラフ(Graphs)
CvGraph
重み付きの有向または無向グラフ
#define CV_GRAPH_VERTEX_FIELDS() ¥
int flags; /* 頂点フラグ */ ¥
struct CvGraphEdge* first; /* 最初の辺 */
typedef struct CvGraphVtx
{
CV_GRAPH_VERTEX_FIELDS()
}
CvGraphVtx;
#define CV_GRAPH_EDGE_FIELDS() ¥
int flags; /* 辺フラグ */ ¥
float weight; /* 辺の重み */ ¥
struct CvGraphEdge* next[2]; /* 辺リストにおける次の辺.始点(0),終点(1) */ ¥
struct CvGraphVtx* vtx[2]; /* 始点(0),終点(1) */
typedef struct CvGraphEdge
{
CV_GRAPH_EDGE_FIELDS()
}
CvGraphEdge;
#define CV_GRAPH_FIELDS() ¥
CV_SET_FIELDS() /* 頂点のセット */ ¥
CvSet* edges; /* 辺のセット*/
typedef struct CvGraph
{
CV_GRAPH_FIELDS()
}
CvGraph;
構造体 CvGraph は,OpenCVで使用されるグラフの基本構造である.
グラフ構造体は,CvSet(一般的なグラフの特性とグラフ頂点を記述)を継承し, さらにメンバーとしてもう一つのセット(グラフの辺を記述)を含んでいる.
頂点,辺,グラフヘッダの構造体は,他の拡張可能なOpenCVの構造体と同じ方法(構造体の拡張やカスタマイズをシンプルにするマクロを用いて)で宣言される. 頂点と辺の構造体は明示的には CvSetElem を継承していないが, それらはセットの要素の二つの条件(先頭に整数フィールドflagsを持ち,CvSetElem構造体と合致する)を満足している. フィールド flags は,頂点と辺が存在していることを示すだけでなく,他の目的 (例えば,グラフの走査(cvCreateGraphScanner 等を参照))にも用いられるので, このフィールドを直接使用しないほうが良い.
グラフは辺のセットとして表現され,各辺はそこに接続する辺のリストを持つ.情報の重複をできる限り避けるために,違う頂点への接続リストが交互に配置される.
グラフは有向か無向かのいずれかである.無向グラフの場合,頂点AからBへの接続と,頂点BからAへの接続の区別はなく, グラフ上にはどちらか一方しか同時に存在できない.これらの接続はそれぞれ辺 <A, B> ,<B, A> と表現される.
CreateGraph
空のグラフを生成する
CvGraph* cvCreateGraph( int graph_flags, int header_size, int vtx_size,
int edge_size, CvMemStorage* storage );
- graph_flags
- 生成したグラフのタイプ.無向グラフの場合,CV_SEQ_KIND_GRAPH, 有向グラフの場合,CV_SEQ_KIND_GRAPH | CV_GRAPH_FLAG_ORIENTED.
- header_size
- グラフのヘッダサイズ (sizeof(CvGraph)以上).
- vtx_size
- グラフの頂点サイズ(カスタマイズされた頂点の構造体は CvGraphVtx で始まらなければならない( CV_GRAPH_VERTEX_FIELDS() を使用)).
- edge_size
- グラフの辺サイズ(カスタマイズされた辺の構造体は CvGraphEdge で始まらなければならない( CV_GRAPH_EDGE_FIELDS() を使用)).
- storage
- グラフコンテナ.
関数 cvCreateGraph は,空のグラフを生成し,そのポインタを返す.
GraphAddVtx
グラフに頂点を追加する
int cvGraphAddVtx( CvGraph* graph, const CvGraphVtx* vtx=NULL,
CvGraphVtx** inserted_vtx=NULL );
- graph
- グラフ.
- vtx
- 追加される頂点の初期化に使用される,オプションの入力引数(sizeof(CvGraphVtx)の領域を超えたユーザー定義フィールドのみコピーされる).
- inserted_vertex
- オプションの出力引数.NULLでない場合,新しい頂点のアドレスがここに書かれる.
関数 cvGraphAddVtx はグラフに頂点を追加し,頂点のインデックスを返す.
GraphRemoveVtx
グラフから頂点を削除する(インデックス指定)
int cvGraphRemoveVtx( CvGraph* graph, int index );
- graph
- グラフ.
- vtx_idx
- 削除される頂点のインデックス.
関数 cvGraphRemoveVtx は,指定した頂点とその頂点に接続するすべての辺をグラフから削除する. 入力された頂点がグラフに存在しない場合は,エラーを出力する. 戻り値は削除された辺の数,あるいは頂点がグラフに存在しない場合は-1である.
GraphRemoveVtxByPtr
グラフから頂点を削除する(ポインタ指定)
int cvGraphRemoveVtxByPtr( CvGraph* graph, CvGraphVtx* vtx );
- graph
- グラフ.
- vtx
- 削除される頂点へのポインタ.
関数 cvGraphRemoveVtxByPtr は,指定した頂点とその頂点に接続するすべての辺をグラフから削除する. 入力された頂点がグラフに存在しない場合は,エラーを出力する. 戻り値は削除された辺の数,あるいは頂点がグラフに存在しない場合は-1である.
GetGraphVtx
インデックスを用いてグラフの頂点を検索する
CvGraphVtx* cvGetGraphVtx( CvGraph* graph, int vtx_idx );
- graph
- グラフ.
- vtx_idx
- 頂点のインデックス.
関数 cvGetGraphVtx は,グラフの頂点をインデックスから検索し,そのポインタを返す. 頂点がグラフ内に存在しない場合は,NULLを返す.
GraphVtxIdx
グラフ頂点のインデックスを返す
int cvGraphVtxIdx( CvGraph* graph, CvGraphVtx* vtx );
- graph
- グラフ.
- vtx
- グラフ頂点へのポインタ.
関数 cvGraphVtxIdx は,ポインタで指定されたグラフ頂点のインデックスを返す.
GraphAddEdge
グラフに辺を追加する(インデックス指定)
int cvGraphAddEdge( CvGraph* graph, int start_idx, int end_idx,
const CvGraphEdge* edge=NULL, CvGraphEdge** inserted_edge=NULL );
- graph
- グラフ.
- start_idx
- 辺の始点を示すインデックス.
- end_idx
- 辺の終点を示すインデックス.無向グラフの場合,順序はどちらでもよい.
- edge
- オプションの入力パラメータ.辺の初期化のためのデータ.
- inserted_edge
- 入力された辺のアドレスを保存するための,オプションの出力パラメータ.
関数 cvGraphAddEdge は,指定した二つの頂点を接続する. この関数は,追加に成功すると1を返し,すでに二つの頂点を接続する辺が存在する場合は0を返し, 頂点のどちらかが存在しない,始点と終点が同じとき,他の重大な問題があるときには-1を返す. 後者の場合(すなわち,結果が負のとき),この関数はデフォルトでエラーも出力する.
GraphAddEdgeByPtr
グラフに辺を追加する(ポインタ指定)
int cvGraphAddEdgeByPtr( CvGraph* graph, CvGraphVtx* start_vtx, CvGraphVtx* end_vtx,
const CvGraphEdge* edge=NULL, CvGraphEdge** inserted_edge=NULL );
- graph
- グラフ.
- start_vtx
- 辺の始点を示す頂点へのポインタ.
- end_vtx
- 辺の終点を示す頂点へのポインタ.無向グラフの場合,順序はどちらでもよい.
- edge
- オプションの入力パラメータ,辺の初期化データ.
- inserted_edge
- 辺の集合の中で入力された辺のアドレスを保存するための,オプションの出力パラメータ.
関数 cvGraphAddEdgeByPtr は指定した二つの頂点を接続する. この関数は,追加に成功すると1を返し,すでに二つの頂点を接続する辺が存在する場合は0を返し, 頂点のどちらかが存在しない,始点と終点が同じとき,他の重大な問題があるときには-1を返す. 後者の場合(すなわち,結果が負のとき),関数はデフォルトでエラーも出力する.
GraphRemoveEdge
グラフから辺を削除する(インデックス指定)
void cvGraphRemoveEdge( CvGraph* graph, int start_idx, int end_idx );
- graph
- グラフ.
- start_idx
- 辺の始点を示す頂点のインデックス.
- end_idx
- 辺の終点を示す頂点のインデックス.無向グラフの場合,順序はどちらでもよい.
関数 cvGraphRemoveEdge は,指定された二つの頂点を接続する辺を削除する. 頂点が(この順序で)接続されていない場合,この関数は何もしない.
GraphRemoveEdgeByPtr
グラフから辺を削除する(ポインタ指定)
void cvGraphRemoveEdgeByPtr( CvGraph* graph, CvGraphVtx* start_vtx, CvGraphVtx* end_vtx );
- graph
- グラフ.
- start_vtx
- 辺の始点を示す頂点へのポインタ.
- end_vtx
- 辺の終点を示す頂点へのポインタ.無向グラフの場合,順序はどちらでもよい.
関数 cvGraphRemoveEdgeByPtr は,指定された二つの頂点を接続する辺を削除する. 頂点が(この順序で)接続されていない場合,この関数は何もしない.
FindGraphEdge
グラフから辺を検出する(インデックス指定)
CvGraphEdge* cvFindGraphEdge( const CvGraph* graph, int start_idx, int end_idx );
#define cvGraphFindEdge cvFindGraphEdge
- graph
- グラフ.
- start_idx
- 辺の始点を示す頂点のインデックス.
- end_idx
- 辺の終点を示す頂点のインデックス.無向グラフの場合,順序はどちらでもよい.
関数 cvFindGraphEdge は,指定した二つの頂点を接続する辺を検出し,そのポインタを返す. 辺が存在しない場合はNULLを返す.
FindGraphEdgeByPtr
グラフから辺を検出する(ポインタ指定)
CvGraphEdge* cvFindGraphEdgeByPtr( const CvGraph* graph, const CvGraphVtx* start_vtx,
const CvGraphVtx* end_vtx );
#define cvGraphFindEdgeByPtr cvFindGraphEdgeByPtr
- graph
- グラフ.
- start_vtx
- 辺の始点を示す頂点へのポインタ.
- end_vtx
- 辺の終点を示す頂点へのポインタ.無向グラフの場合,順序はどちらでもよい.
関数 cvFindGraphEdgeByPtr は,指定した二つの頂点を接続する辺を検出し,そのポインタを返す. 辺が存在しない場合はNULLを返す.
GraphEdgeIdx
グラフの辺のインデックスを返す
int cvGraphEdgeIdx( CvGraph* graph, CvGraphEdge* edge );
- graph
- グラフ.
- edge
- 辺へのポインタ.
関数 cvGraphEdgeIdx は,グラフの辺のインデックスを返す.
GraphVtxDegree
頂点に接続している辺の数を数える(インデックス指定)
int cvGraphVtxDegree( const CvGraph* graph, int vtx_idx );
- graph
- グラフ.
- vtx
- 頂点のインデックス.
関数 cvGraphVtxDegree は,指定した頂点に接続した(入る/出る両方向の)辺の数を返す. 辺の数を数えるために,以下のコードが用いられる.
CvGraphEdge* edge = vertex->first; int count = 0;
while( edge )
{
edge = CV_NEXT_GRAPH_EDGE( edge, vertex );
count++;
}
マクロ CV_NEXT_GRAPH_EDGE( edge, vertex ) は, vertex へ接続する,edge の次の辺を返す.
GraphVtxDegreeByPtr
頂点に接続している辺の数を数える(ポインタ指定)
int cvGraphVtxDegreeByPtr( const CvGraph* graph, const CvGraphVtx* vtx );
- graph
- グラフ.
- vtx
- 頂点へのポインタ.
関数 cvGraphVtxDegreeByPtr は,指定した頂点に接続した(入る/出る両方向の)辺の数を返す.
ClearGraph
グラフをクリアする
void cvClearGraph( CvGraph* graph );
- graph
- グラフ.
関数 cvClearGraph は,グラフから全ての頂点と辺を削除する. この関数の時間計算量は O(1)である.
CloneGraph
グラフをコピーする
CvGraph* cvCloneGraph( const CvGraph* graph, CvMemStorage* storage );
- graph
- コピーするグラフ.
- storage
- コピーのためのコンテナ.
関数 cvCloneGraph は,グラフの完全コピーを作成する. グラフの頂点や辺が外部データへのポインタを持つ場合,そのポインタはコピーしたグラフでも共有される. この関数は頂点や辺の集合を最適化(デフラグメント)するため,新しいグラフの頂点と辺のインデックスが元のグラフのものと違う可能性がある.
CvGraphScanner
グラフ走査状態のための構造体
typedef struct CvGraphScanner
{
CvGraphVtx* vtx; /* 現在の頂点(あるいは辺の始点) */
CvGraphVtx* dst; /* 現在の辺の接続先頂点 */
CvGraphEdge* edge; /* 現在の辺 */
CvGraph* graph; /* 走査中のグラフ */
CvSeq* stack; /* 走査中の頂点スタック */
int index; /* 走査済みの頂点の下限インデックス */
int mask; /* イベントマスク */
}
CvGraphScanner;
構造体 CvGraphScanner は,深さ優先走査のために用いられる. 以下の関数の説明を参照.
CreateGraphScanner
グラフの深さ優先走査のための構造体を生成する
CvGraphScanner* cvCreateGraphScanner( CvGraph* graph, CvGraphVtx* vtx=NULL,
int mask=CV_GRAPH_ALL_ITEMS );
- graph
- グラフ.
- vtx
- 走査開始頂点.NULLの場合,走査は先頭の頂点(頂点シーケンスのうち最小のインデックスを持つ頂点)から始まる.
- mask
- イベントマスク.どのイベントにユーザが着目したいのかを指定する
(関数 cvNextGraphItem はユーザーにコントロールを返す).
CV_GRAPH_ALL_ITEMS(すべてのイベントに着目)か,以下のフラグの組み合わせ.
- CV_GRAPH_VERTEX - はじめてアクセスした頂点で停止する
- CV_GRAPH_TREE_EDGE - tree edgeで停止する
(tree edge は最後にアクセスした頂点と次にアクセスされる頂点を接続する辺のこと)
- CV_GRAPH_BACK_EDGE - back edgeで停止する
(back edge は最後にアクセスした頂点と探索木内でのその親のいずれかを接続する辺のこと)
- CV_GRAPH_FORWARD_EDGE - forward edgeで停止する
(forward edge は最後にアクセスした頂点と探索木内でのその子のいずれかを接続する辺のこと.
forward edge は有向グラフの走査においてのみ有効)
- CV_GRAPH_CROSS_EDGE - cross edgeで停止する
(cross edge は異なる探索木同士か同じ木の枝同士を接続する辺のこと.
cross edges は有向グラフの走査においてのみ有効)
- CV_GRAPH_ANY_EDGE - 任意の辺で停止する(tree, back, forward そしてcross edges)
- CV_GRAPH_NEW_TREE - すべての新しい探索木の先頭で停止する.
走査プロセスが,走査開始頂点(initial vertex)から到達可能なすべての頂点と辺にアクセスする場合
(アクセスされた頂点は辺とともに一つの木(tree)を構成する),グラフ中でまだアクセスされていない頂点を探索し,
その頂点からの探索を再開する.新しい木の開始前(最初に cvNextGraphItem が呼ばれる,全く初めての場合も含む)に,
CV_GRAPH_NEW_TREE イベントを生成する.
無向グラフにおいては,各探索木が,グラフの接続される一つの成分に対応する.
- CV_GRAPH_BACKTRACKING - 逆探索(バックトラッキング,既にアクセスされた頂点を逆に戻っていく)中に,すべてのアクセス済みの頂点で停止する.
- CV_GRAPH_VERTEX - はじめてアクセスした頂点で停止する
関数 cvCreateGraphScanner は深さ,優先走査/探索のための構造体を生成する. 初期化された構造体は,関数 cvNextGraphItem (逐次走査処理)で用いられる.
NextGraphItem
グラフ走査処理を1ステップ,あるいは数ステップ進める
int cvNextGraphItem( CvGraphScanner* scanner );
- scanner
- グラフ走査状態.この関数で更新される.
関数 cvNextGraphItem は,ユーザーが着目したイベント (cvCreateGraphScanner の mask 引数で指定される) に合致するか, すべての走査が終了するまで,グラフ内を順に走査する. 前者の場合,この関数は上記の mask パラメータで指定されたイベントを返し,次の呼び出しで走査を再開する. 後者の場合,CV_GRAPH_OVER (-1) を返す. イベントが CV_GRAPH_VERTEX,CV_GRAPH_BACKTRACKING,CV_GRAPH_NEW_TREE の場合, 現在の走査中の頂点は scanner->vtx に保存される. 辺に関係しているイベントの場合,現在走査対象の辺は scanner->edge に, 一つ前にアクセスした頂点は scanner->vtx に, 辺のもう一方(終点)の頂点は scanner->dst にそれぞれ保存される.
ReleaseGraphScanner
グラフの走査処理を終了する
void cvReleaseGraphScanner( CvGraphScanner** scanner );
- scanner
- スキャナへのポインタのポインタ.
関数 cvGraphScanner は,グラフの走査処理を終了し,スキャナを解放する.
木(Trees)
CV_TREE_NODE_FIELDS
ツリーノードの種類を宣言するための補助マクロ
#define CV_TREE_NODE_FIELDS(node_type) ¥
int flags; /* 様々なフラグ */ ¥
int header_size; /* シーケンスヘッダのサイズ */ ¥
struct node_type* h_prev; /* 一つ前のシーケンスへのポインタ */ ¥
struct node_type* h_next; /* 一つ後のシーケンスへのポインタ */ ¥
struct node_type* v_prev; /* 一つ前のシーケンスへのポインタ(セカンダリ,構造によって意味が異なる) */ ¥
struct node_type* v_next; /* 一つ後のシーケンスへのポインタ(セカンダリ,構造によって意味が異なる) */
マクロCV_TREE_NODE_FIELDS()は,すべての動的構造の基本タイプである CvSeqのように, 階層構造(ツリー)として組織化できるデータ構造を宣言するために使用される. このマクロを用いて宣言されたノードから構成されるツリーは,このセクションで述べる各関数を用いて処理することができる.
CvTreeNodeIterator
ツリーノードのイテレータのための構造体
typedef struct CvTreeNodeIterator
{
const void* node;
int level;
int max_level;
}
CvTreeNodeIterator;
構造体 CvTreeNodeIterator は,ツリーを走査するために用いられる. ツリーのノードの宣言には,マクロCV_TREE_NODE_FIELDS(...)を用いる必要がある.
InitTreeNodeIterator
ツリーノードのイテレータを初期化する
void cvInitTreeNodeIterator( CvTreeNodeIterator* tree_iterator,
const void* first, int max_level );
- tree_iterator
- 初期化されるツリーのイテレータ.
- first
- 先頭ノード.ここから走査を開始する.
- max_level
- ツリー走査範囲の最大レベル(first ノードが第1レベルであると仮定する). 例えば,1 はfirstと同じレベルのノードのみが処理されることを意味する, また,2はfirstと同じレベルのノードとその子ノードが処理される.
関数 cvInitTreeNodeIterator は,ツリーのイテレータを初期化する.ツリーは深さ優先で走査される.
NextTreeNode
現在のノードを返し,イテレータを次のノードに移動させる.
void* cvNextTreeNode( CvTreeNodeIterator* tree_iterator );
- tree_iterator
- 初期化されるツリーのイテレータ.
関数 cvNextTreeNode は,現在対象となっているノードを返し,その後イテレータを更新する(次のノードに移動させる). つまり,この関数の動作は,通常のC言語のポインタでの *p++ 表現,あるいはC++のコレクションイテレータとほぼ同じである. これ以上のノードがない場合,この関数はNULLを返す.
PrevTreeNode
現在のノードを返し,イテレータを前のノードに移動させる.
void* cvPrevTreeNode( CvTreeNodeIterator* tree_iterator );
- tree_iterator
- 初期化されるツリーのイテレータ.
関数 cvPrevTreeNode は現在対象となっているノードを返し,その後イテレータを更新する(一つ前のノードに移動させる). つまり,この関数の動作は,通常のCのポインタでの *p-- 表現,あるいはC++のコレクションイテレータとほぼ同じである. これ以上のノードがない場合,関数はNULLを返す.
TreeToNodeSeq
すべてのノードへのポインタを一つのシーケンスに集める
CvSeq* cvTreeToNodeSeq( const void* first, int header_size, CvMemStorage* storage );
- first
- ツリーの先頭ノード.
- header_size
- 作成したシーケンスのヘッダサイズ(sizeof(CvSeq) が用いられることが多い).
- storage
- シーケンスのためのコンテナ.
関数 cvTreeToNodeSeq は,ノード first から到達可能なすべてのノードへのポインタを一つのシーケンスにまとめる. ポインタは深さ優先順に順次書き込まれる.
InsertNodeIntoTree
ツリーに新しいノードを追加する
void cvInsertNodeIntoTree( void* node, void* parent, void* frame );
- node
- 挿入されるノード.
- parent
- ツリー内に既に存在している親ノード.
- frame
- トップレベルノード.parent と frame が同じである場合, nodeのv_prevフィールドには,parent ではなく,NULLがセットされる.
関数 cvInsertNodeIntoTree は,ツリーに別のノードを追加する. この関数はメモリの領域確保を行わず,単にツリーノードのリンクを変更するだけである.
RemoveNodeFromTree
ツリーからノードを削除する
void cvRemoveNodeFromTree( void* node, void* frame );
- node
- 削除されるノード.
- frame
- トップレベルノード.node->v_prev = NULL かつ node->h_prev = NULL (つまり,node が frameの最初の子ノードである)である場合, frame->v_next は node->h_next にセットされる (つまり,最初の子ノードかframeが変更される).
関数 cvRemoveNodeFromTree は,ツリーからノードを削除する. この関数はメモリの領域解放を行わず,単にツリーノードのリンクを変更するだけである.
描画関数(Drawing Functions)
描画関数は行列や画像,任意のカラーデプスで使われる. アンチエイリアス処理は8ビット画像にのみ実装されている. すべての関数はパラメータcolor(CV_RGBマクロか,cvScalar関数を用いて作成される)を持ち, これはカラー画像ではrgb値,グレースケール画像では輝度を意味する.
描く図の一部,もしくは全てが画像の領域外にある場合には,その部分は切り取られる. カラー画像の場合,チャンネルの順番は青,緑,赤...である. 順番を変更したい場合は,cvScalarを用いて順番を指定するか,cvCvtColor あるいは cvTransformを用いて,描画前,もしくは描画後に画像を変換すればよい.
曲線と形状(Curves and Shapes)
CV_RGB
カラー値を作成する
#define CV_RGB( r, g, b ) cvScalar( (b), (g), (r) )
Line
2点を結ぶ線分を描画する
void cvLine( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
- img
- 画像.
- pt1
- 線分の1番目の端点.
- pt2
- 線分の2番目の端点.
- color
- 線分の色.
- thickness
- 線分の太さ.
- line_type
- 線分の種類.
8 (または0) - 8連結による線分.
4 - 4連結による線分.
CV_AA - アンチエイリアスされた線分. - shift
- 座標の小数点以下の桁を表すビット数.
関数cvLineは,点pt1と点pt2を結ぶ線分を画像上に描画する. 描画される線分は画像やROIにより切り取られる. 整数値座標でアンチエイリアスされていない線分では,8連結,または4連結のブレゼンハム(Bresenham)アルゴリズムが使われる. 太い線分の端は丸く描画される.アンチエイリアスされた線分は,ガウシアン(Gaussian)フィルタを用いて描かれる. 線分の色を指定するには,マクロCV_RGB(r, g, b)を用いる.
Rectangle
枠のみ,もしくは塗りつぶされた矩形を描画する
void cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
- img
- 矩形が描画される画像.
- pt1
- 矩形の一つの頂点.
- pt2
- 矩形の反対側の頂点.
- color
- 線の色(RGB),もしくは輝度(グレースケール画像).
- thickness
- 矩形を描く線の太さ.負の値,例えばCV_FILLEDを指定した場合は塗りつぶされる.
- line_type
- 線の種類,詳細はcvLineを参照.
- shift
- 座標の小数点以下の桁を表すビット数.
関数cvRectangleは,点pt1と点pt2を対角とする矩形を描画する.
Circle
円を描画する
void cvCircle( CvArr* img, CvPoint center, int radius, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
- img
- 円が描画される画像.
- center
- 円の中心.
- radius
- 円の半径.
- color
- 円の色.
- thickness
- 線の幅.負の値を指定した場合は塗りつぶされる.
- line_type
- 線の種類,詳細はcvLineを参照.
- shift
- 中心座標と半径の小数点以下の桁を表すビット数.
関数cvCircleは,与えた中心と半径に応じて枠だけ,もしくは塗りつぶされた円を描く.描画される円はROIによって切り取られる. 円の色はマクロCV_RGB ( r, g, b )で指定できる.
Ellipse
枠だけの楕円,楕円弧,もしくは塗りつぶされた扇形の楕円を描画する
void cvEllipse( CvArr* img, CvPoint center, CvSize axes, double angle,
double start_angle, double end_angle, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
- img
- 楕円が描画される画像.
- center
- 楕円の中心.
- axes
- 楕円の軸の長さ.
- angle
- 回転角度.
- start_angle
- 楕円弧の開始角度.
- end_angle
- 楕円弧の終了角度.
- color
- 楕円の色.
- thickness
- 楕円弧の線の幅.
- line_type
- 楕円弧の線の種類.詳細はcvLineを参照.
- shift
- 中心座標と軸の長さの小数点以下の桁を表すビット数.
関数cvEllipseは,枠だけの楕円,楕円弧,もしくは塗りつぶした楕円を描画する. 描画される楕円はROIによって切り取られる. アンチエイリアスされた線や太い線を指定した場合には,線形近似が用いられる.角度は度で指定する. パラメータの意味を以下の図で説明する.
楕円弧を描画するためのパラメータ
EllipseBox
枠だけの楕円,もしくは塗りつぶされた楕円を描画する
void cvEllipseBox( CvArr* img, CvBox2D box, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
- img
- 楕円が描かれる画像.
- box
- 描画したい楕円を囲む矩形領域.
- thickness
- 楕円境界線の幅.
- line_type
- 楕円境界線の種類.詳細はcvLineを参照.
- shift
- 矩形領域の頂点座標の小数点以下の桁を表すビット数.
関数cvEllipseBoxは枠だけの楕円,もしくは塗りつぶされた楕円を描画する. この関数は,cvCamShiftやcvFitEllipseで得られた結果から楕円を描画する際に便利である. 描画される楕円はROIによって切り取られる.アンチエイリアスされた線や太い線を指定した場合には,線形近似が用いられる.
FillPoly
ポリゴン内部を塗りつぶす
void cvFillPoly( CvArr* img, CvPoint** pts, int* npts, int contours,
CvScalar color, int line_type=8, int shift=0 );
- img
- ポリゴンが描かれる画像.
- pts
- ポリゴンへのポインタ配列.
- npts
- ポリゴン頂点数の配列.
- contours
- 塗りつぶされた領域を区切る輪郭の数.
- color
- ポリゴンの色.
- line_type
- 線の種類.詳細はcvLineを参照.
- shift
- 頂点座標の小数点以下の桁を表すビット数.
関数cvFillPolyは,幾つかのポリゴンにより区切られた領域を塗りつぶす. この関数では複雑な領域,例えば領域内に穴を持つものや,自己交差したものなども塗りつぶす.
FillConvexPoly
凸ポリゴンを塗りつぶす
void cvFillConvexPoly( CvArr* img, CvPoint* pts, int npts,
CvScalar color, int line_type=8, int shift=0 );
- img
- ポリゴンが描かれる画像.
- pts
- 一つのポリゴンへのポインタの配列.
- npts
- ポリゴンの頂点数.
- color
- ポリゴンの色.
- line_type
- 線の種類.詳細はcvLineを参照.
- shift
- 頂点座標の小数点以下の桁を表すビット数.
関数cvFillConvexPolyは凸ポリゴンの内部を塗りつぶす. この関数は,関数cvFillPolyより高速に動作する. また,凸ポリゴンだけでなく,その輪郭が水平なスキャンラインと2回以下しか交差しないような単純なポリゴンはすべて塗りつぶすことができる.
PolyLine
ポリライン(枠だけのポリゴン)を描画する
void cvPolyLine( CvArr* img, CvPoint** pts, int* npts, int contours, int is_closed,
CvScalar color, int thickness=1, int line_type=8, int shift=0 );
- img
- ポリラインが描かれる画像.
- pts
- ポリラインへのポインタの配列.
- npts
- ポリラインの頂点数の配列.
- contours
- ポリラインの個数.
- is_closed
- ポリラインを閉じるかどうかを指定する.閉じる場合,それぞれの領域の最後の頂点と最初の頂点を結ぶ線分を描画する.
- color
- 線の色.
- thickness
- 線の太さ.
- line_type
- 線の種類.詳細はcvLineを参照.
- shift
- 頂点座標の小数点以下の桁を表すビット数.
関数cvPolyLineは,一つ,もしくは複数のポリラインを描画する.
テキスト(Text)
InitFont
フォント構造体を初期化する
void cvInitFont( CvFont* font, int font_face, double hscale,
double vscale, double shear=0,
int thickness=1, int line_type=8 );
- font
- この関数で初期化されるフォント構造体へのポインタ
- font_face
- フォント名の識別子.現在は,Hershey fonts
(http://sources.isc.org/utils/misc/hershey-font.txt)
の一部のみサポートされている.
CV_FONT_HERSHEY_SIMPLEX - 普通サイズのsans-serif フォント
CV_FONT_HERSHEY_PLAIN - 小さいサイズのsans-serif フォント
CV_FONT_HERSHEY_DUPLEX - 普通サイズのsans-serif フォント (CV_FONT_HERSHEY_SIMPLEX よりも複雑)
CV_FONT_HERSHEY_COMPLEX - 普通サイズのserif フォント
CV_FONT_HERSHEY_TRIPLEX - 普通サイズのserif フォント (CV_FONT_HERSHEY_COMPLEX よりも複雑)
CV_FONT_HERSHEY_COMPLEX_SMALL - CV_FONT_HERSHEY_COMPLEX の小さいバージョン
CV_FONT_HERSHEY_SCRIPT_SIMPLEX - 手書きスタイルのフォント
CV_FONT_HERSHEY_SCRIPT_COMPLEX - CV_FONT_HERSHEY_SCRIPT_SIMPLEX の複雑なバージョン
パラメータは上記の値と,イタリックもしくは斜字を意味するオプションCV_FONT_ITALICフラグを合成することができる. - hscale
- 幅の比率.1.0fにした場合,文字はそれぞれのフォントに依存する元々の幅で表示される. 0.5fにした場合, 文字は元々の半分の幅で表示される.
- vscale
- 高さの比率.1.0fにした場合,文字はそれぞれのフォントに依存する元々の高さで表示される. 0.5fにした場合, 文字は元々の半分の高さで表示される.
- shear
- 垂直線からの文字の相対的な角度.ゼロの場合は非イタリックフォントで,例えば,1.0fは≈45°を意味する.
- thickness
- 文字の太さ.
- line_type
- 線の種類.詳細はcvLineを参照.
関数cvInitFontは,文字描画関数に渡されるフォント構造体を初期化する.
PutText
文字列を描画する
void cvPutText( CvArr* img, const char* text, CvPoint org, const CvFont* font, CvScalar color );
- img
- 入力画像.
- text
- 描画する文字列.
- org
- 最初の文字の左下の座標.
- font
- フォント構造体へのポインタ.
- color
- 文字の色.
関数cvPutTextは,指定したフォントと色で文字列を画像中に描画する. 描画された文字はROIによって切り取られる.指定したフォントに含まれない記号は四角で置き換えられる.
GetTextSize
文字列の幅と高さを取得する
void cvGetTextSize( const char* text_string, const CvFont* font, CvSize* text_size, int* baseline );
- text_string
- 入力文字列.
- font
- フォント構造体へのポインタ.
- text_size
- 結果として得られる文字列のサイズ.文字の高さには,ベースラインより下の部分の高さは含まれない.
- baseline
- 文字の最下点から見たベースラインのy座標.
関数cvGetTextSizeは,指定したフォントでの入力文字列を包含する矩形を計算する.
点集合と輪郭(Point Sets and Contours)
DrawContours
画像の外側輪郭線,または内側輪郭線を描画する
void cvDrawContours( CvArr *img, CvSeq* contour,
CvScalar external_color, CvScalar hole_color,
int max_level, int thickness=1,
int line_type=8, CvPoint offset=cvPoint(0,0) );
- img
- 輪郭を描画する元画像.輪郭はROIで切り取られる.
- contour
- 最初の輪郭へのポインタ.
- external_color
- 外側輪郭線の色.
- hole_color
- 内側輪郭線(穴)の色.
- max_level
- 描画される輪郭の最大レベル. 0にした場合,contourのみが描画される. 1にした場合,先頭の輪郭と,同レベルのすべての輪郭が描画される. 2にした場合,先頭の輪郭と同レベルのすべての輪郭と,先頭の輪郭の一つ下のレベルのすべての輪郭が描画される.以下同様. 負の値にした場合,この関数はcontourの後に続く同レベルの輪郭を描画しないが, contourの子の輪郭をabs(max_level)-1のレベルまで描画する.
- thickness
- 描画される輪郭線の太さ.負(例えば=CV_FILLED)にした場合には,内部を塗りつぶす.
- line_type
- 線の種類.詳細はcvLineを参照.
- offset
- 全ての座標を指定した値だけシフトする.これは,輪郭をROI内の画像から生成して,ROIのオフセットを考慮する必要がある場合に便利である.
関数cvDrawContoursは,thickness>=0の場合には外側輪郭線を画像上に描画し, thickness<0の場合には輪郭の内部を塗りつぶす.
(例)輪郭関数を用いた連結要素の検出
#include "cv.h"
#include "highgui.h"
int main( int argc, char** argv )
{
IplImage* src;
// コマンドラインの第1パラメータは2値(白黒)画像のファイル名を指定する
if( argc == 2 && (src=cvLoadImage(argv[1], 0))!= 0)
{
IplImage* dst = cvCreateImage( cvGetSize(src), 8, 3 );
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contour = 0;
cvThreshold( src, src, 1, 255, CV_THRESH_BINARY );
cvNamedWindow( "Source", 1 );
cvShowImage( "Source", src );
cvFindContours( src, storage, &contour,
sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
cvZero( dst );
for( ; contour != 0; contour = contour->h_next )
{
CvScalar color = CV_RGB( rand()&255, rand()&255, rand()&255 );
/* 輪郭を見るためには,CV_FILLEDを1にする */
cvDrawContours( dst, contour, color, color, -1, CV_FILLED, 8 );
}
cvNamedWindow( "Components", 1 );
cvShowImage( "Components", dst );
cvWaitKey(0);
}
}
輪郭を見るためには,上述のサンプルの CV_FILLED を 1 に置き換える.
InitLineIterator
ラインイテレータを初期化する
int cvInitLineIterator( const CvArr* image, CvPoint pt1, CvPoint pt2,
CvLineIterator* line_iterator, int connectivity=8,
int left_to_right=0 );
- image
- 対象画像.
- pt1
- 線分の一つ目の端点.
- pt2
- 線分のニつ目の端点.
- line_iterator
- ラインイテレータ状態構造体へのポインタ.
- connectivity
- 走査した線分の接続性.4または8.
- left_to_right
- pt1とpt2とは無関係に線分をいつも左から右に走査する(left_to_right≠0)か, pt1からpt2への決まった方向で走査するか(left_to_right=0)を指定するフラグ.
関数cvInitLineIteratorはラインイテレータを初期化し,2端点間のピクセル数を返す. 両方の点は共に画像内に存在しなければならない. ラインイテレータが初期化された後,2端点を結ぶ線分上のすべての点はCV_NEXT_LINE_POINTにより取得される. 線上の点は,4連結 または 8連結ブレゼンハム(Bresenham)アルゴリズムを用いて一つずつ計算される.
(例)ラインイテレータを用いた色のついた線上のピクセル値の総和の計算
CvScalar sum_line_pixels( IplImage* image, CvPoint pt1, CvPoint pt2 )
{
CvLineIterator iterator;
int blue_sum = 0, green_sum = 0, red_sum = 0;
int count = cvInitLineIterator( image, pt1, pt2, &iterator, 8, 0 );
for( int i = 0; i < count; i++ ){
blue_sum += iterator.ptr[0];
green_sum += iterator.ptr[1];
red_sum += iterator.ptr[2];
CV_NEXT_LINE_POINT(iterator);
/* ピクセルの座標を表示:どうやって座標を計算するか,のデモンストレーション */
{
int offset, x, y;
/* ROIは設定されていないと仮定している.もし設定されている場合には考慮する必要がある.*/
offset = iterator.ptr - (uchar*)(image->imageData);
y = offset/image->widthStep;
x = (offset - y*image->widthStep)/(3*sizeof(uchar) /* ピクセルのサイズ */);
printf("(%d,%d)¥n", x, y );
}
}
return cvScalar( blue_sum, green_sum, red_sum );
}
ClipLine
線分を画像領域で切り取る
int cvClipLine( CvSize img_size, CvPoint* pt1, CvPoint* pt2 );
- img_size
- 画像の大きさ.
- pt1
- 線分の1番目の端点.この値はこの関数によって変更される.
- pt2
- 線分の2番目の端点.この値はこの関数によって変更される.
関数cvClipLine は,画像領域内に存在する線分の領域を計算する. もし線分が完全に画像外ならば0を返し,そうでなければ1を返す.
Ellipse2Poly
楕円弧をポリラインで近似する
int cvEllipse2Poly( CvPoint center, CvSize axes,
int angle, int arc_start,
int arc_end, CvPoint* pts, int delta );
- center
- 弧の中心.
- axes
- 楕円の軸の長さ.cvEllipseを参照.
- angle
- 楕円の回転角度.cvEllipseを参照.
- start_angle
- 楕円弧の開始角度.
- end_angle
- 楕円弧の終了角度.
- pts
- この関数で塗りつぶされる点の配列.
- delta
- ポリラインの連続した頂点間の角度,近似精度.出力される点の総数は最大で ceil((end_angle - start_angle)/delta) + 1.
関数cvEllipse2Polyは,指定した楕円弧を近似するポリラインの頂点を計算する. これはcvEllipseで利用される.
データ永続性と実行時型情報(Data Persistence and RTTI)
ファイルストレージ(File Storage)
CvFileStorage
ファイルストレージ
typedef struct CvFileStorage
{
... // 隠しフィールド
} CvFileStorage;
構造体CvFileStorageは, ディスク内にあるファイルと関連付けられたファイルストレージの「ブラックボックス」的な表現である. 後述する様々な関数はCvFileStorageを引数に持ち,スカラー値で構成される階層的なコレクションや, 行列やシーケンス,グラフなどの標準的なCXCoreオブジェクト,ユーザ定義オブジェクトなどのセーブとロードをユーザに提供する.
CXCoreは,XML(http://www.w3c.org/XML)や YAML (http://www.yaml.org)形式のデータの読み書きが可能である. 以下はXMLとYAMLによる浮動小数点型の3×3単位行列Aの表現である.CXCoreの関数を用いると次のようになる.
- XML:
<?xml version="1.0"> <opencv_storage> <A type_id="opencv-matrix"> <rows>3</rows> <cols>3</cols> <dt>f</dt> <data>1. 0. 0. 0. 1. 0. 0. 0. 1.</data> </A> </opencv_storage>
- YAML:
%YAML:1.0 A: !!opencv-matrix rows: 3 cols: 3 dt: f data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1.]
この例で見られるように,XMLでは階層構造の表現にネスト(入れ子)されたタグを用い,YAMLでは(Pythonと類似した)インデントを用いる.
同じCXCore関数を用いて両データ形式の読み書きが可能であり,形式は開かれたファイルの拡張子で判別される. 拡張子はXMLの場合.xml,YAMLの場合は.ymlである.
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 /* 使用されない */
#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;
この構造体は,ファイルストレージからのデータ取り込みにのみ用いられる(例えばファイルからのデータのロード). データがファイルに書き込まれる場合,最小限のバッファリングで連続的に実行される.このファイルストレージには一切のデータが保存されない.
反対に,ファイルからデータが読み込まれた場合,全てのファイルは解析されて,メモリ内では木構造として表現される. 木構造のそれぞれのノードはCvFileNodeで表現される. ファイルノードNの型は,CV_NODE_TYPE(N->tag)として取得できる. 幾つかのファイルノード(葉)は,文字列や,整数型値,浮動小数点型値などのスカラーである. 他のファイルノードはファイルノードのコレクションであり,それはスカラー値かそのノードでのコレクションである. コレクションにはシーケンスとマップの2つの型がある(ここではYAMLの表記法を使うが,XMLストリームでも同様である). シーケンス(CvSeq と混同しないように)は名前付けされていないファイルノードの整列されたコレクションで, マップは名前付けされたファイルノードの整列されていないコレクションである. このように,シーケンスの要素には,インデックス(cvGetSeqElem)によりアクセスされ, マップの要素には名前(cvGetFileNodeByName)でアクセスされる. 以下の表はファイルノードの型の違いを示す.
| 型 | CV_NODE_TYPE(node->tag) | 値 |
| 整数 | CV_NODE_INT | node->data.i |
| 浮動小数点 | CV_NODE_REAL | node->data.f |
| 文字列 | CV_NODE_STR | node->data.str.ptr |
| シーケンス | CV_NODE_SEQ | node->data.seq |
| マップ | CV_NODE_MAP | node->data.map* |
- *
- map フィールドに直接アクセスする必要は無い(CvMapは隠された構造体である). このマップの要素は,「マップ」ファイルノードのポインタを引数に持つ関数 cvGetFileNodeByNameを使って取得できる.
ユーザ(カスタム)オブジェクトはCvMatやCvSeq等の標準的なCxCoreの型か, cvRegisterTypeInfoで登録された型のインスタンスである. これらのオブジェクトは,ファイルストレージが開かれて解析された後,初期状態ではファイル内でマップ(上述のXMLとYAMLのサンプルファイルのように)として表現されている. その後,オブジェクトはリクエスト(関数cvReadやcvReadByNameを使った場合) に応じてデコード(元々の表現に変換)される.
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 );
現在の実装では,属性はユーザオブジェクトを書き込む際の特別なパラメータを渡すために使われる(cvWriteを参照). タグの中にあるXMLの属性やオブジェクトの型指定(type_id属性)はサポートされない.
OpenFileStorage
データ読み書きのためのファイルをオープンする
CvFileStorage* cvOpenFileStorage( const char* filename, CvMemStorage* memstorage, int flags );
- filename
- ストレージに関連づけられたファイルの名前.
- memstorage
- 一時的なデータや,CvSeqや CvGraphなどの動的構造体の保存に使われるメモリストレージ.NULLの場合,一時的なメモリが確保されて使用される.
- flags
- 以下の内の一つを指定.
CV_STORAGE_READ - データ読み込みのためのファイルオープン
CV_STORAGE_WRITE - データ書き込みのためのファイルオープン
関数cvOpenFileStorageは,データの読み書きのためのファイルを開く. 書き込みの場合は,新しいファイルが作成されるか,ファイルが存在する場合には上書きされる.また,読み書きされるファイルの種類は拡張子で判別される. XMLの場合は.xml,YAMLの場合は.ymlまたは.yamlである. この関数の戻り値は構造体CvFileStorageへのポインタである.
ReleaseFileStorage
ファイルストレージの解放
void cvReleaseFileStorage( CvFileStorage** fs );
- fs
- 解放するファイルへのポインタのポインタ.
関数cvReleaseFileStorageはファイルを閉じて,一時的な構造体をすべて解放する. この関数は,すべての入出力操作が終了した後に実行されなければならない.
データの書き込み(Writing Data)
StartWriteStruct
新しい構造体の書き込みを開始する
void cvStartWriteStruct( CvFileStorage* fs, const char* name,
int struct_flags, const char* type_name=NULL,
CvAttrList attributes=cvAttrList());
- fs
- ファイルストレージ.
- name
- 書き込む構造体の名前.読み込む場合は,この名前で構造体にアクセスできる.
- struct_flags
- 次の値の組合せ.
CV_NODE_SEQ - 書き込む構造体はシーケンス(CvFileStorageを参照), つまり要素は名前を持たない.
CV_NODE_MAP - 書き込む構造体はマップ(CvFileStorageを参照), つまり全ての要素が名前を持つ.
これら二つのうち一つだけを指定しなければならない.
CV_NODE_FLOW - YAMLストリームに対してのみ意味を持つオプションフラグ. 構造体は,よりコンパクトなflow(blockではなく)として保存される. このフラグは全要素がスカラーである構造体か配列に対して用いることが推奨される. - type_name
- オプションパラメータ - オブジェクトの型の名前. XMLの場合,構造体開始タグのtype_id属性として書かれる. YAMLの場合,構造体名に続くコロンの後に書かれる(CvFileStorageの説明の中にある例を参照). 主にユーザオブジェクトと共に使われる.ストレージが読まれたとき,エンコードされた型名がオブジェクトの型を決定する (CvTypeInfoとcvFindTypeInfoを参照).
- attributes
- このパラメータは現在は使われていない.
関数cvStartWriteStructは,シーケンスかマップが複合した構造体(コレクション)の書き込みを開始する. スカラーか構造体で構成された全ての構造体のフィールドが書き込まれた後で,cvEndWriteStructを実行しなければならない. この関数は,いくつかのオブジェクトをグループ化する場合や, ユーザオブジェクト(CvTypeInfoを参照)の書き込み関数を実装する場合にも使われることがある.
EndWriteStruct
構造体の書き込みを終了する
void cvEndWriteStruct( CvFileStorage* fs );
- fs
- ファイルストレージ.
関数cvEndWriteStructは,構造体の書き込みを終了する.
WriteInt
整数型の値を書き込む
void cvWriteInt( CvFileStorage* fs, const char* name, int value );
- fs
- ファイルストレージ.
- name
- 書き込まれる値の名前.親の構造体がシーケンスの場合は,NULLにしなければならない.
- value
- 書き込まれる値.
関数cvWriteIntは,1つの整数値(名前あり,または無し)をファイルに書き込む.
WriteReal
浮動小数点型の値を書き込む
void cvWriteReal( CvFileStorage* fs, const char* name, double value );
- fs
- ファイルストレージ.
- name
- 書き込まれる値の名前.親の構造体がシーケンスの場合は,NULLにしなければならない.
- value
- 書き込まれる値.
関数cvWriteRealは,単精度浮動小数点型の値(名前あり,または無し)をファイルに書き込む. 特別な値はエンコードされる:Not A NumberはNaN に,±Infinityは +.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 );
}
WriteString
文字列を書き込む
void cvWriteString( CvFileStorage* fs, const char* name,
const char* str, int quote=0 );
- fs
- ファイルストレージ.
- name
- 書き込まれる文字列の名前.親の構造体がシーケンスの場合は,NULLにしなければならない.
- str
- 書き込まれる文字列.
- quote
- 0以外の場合,書き込まれる文字列は必要かどうかに関わらず引用符で挟まれる. 0の場合,必要な場合にのみ引用符が使われる(例えば,文字列が数字で始まっていたり,スペースを含む場合).
関数cvWriteStringは,文字列をファイルストレージに書き込む.
WriteComment
コメントを書き込む
void cvWriteComment( CvFileStorage* fs, const char* comment, int eol_comment );
- fs
- ファイルストレージ.
- comment
- 一行または複数行の,書き込まれるコメント.
- eol_comment
- 0以外の場合,この関数は現在の行の最後にコメントを入れようと試みる. フラグが0で,コメントが複数,または現在の行の最後に納まらない場合は,コメントは新しい行から始められる.
関数cvWriteCommentは,ファイルストレージにコメントを書き込む. このコメントはデバッグや説明を記述するために使われるもので,読み込み時には読み飛ばされる.
StartNextStream
次のストリームを開始する
void cvStartNextStream( CvFileStorage* fs );
- fs
- ファイルストレージ.
関数cvStartNextStreamは,ファイルストレージ内の次のストリームを開始する. YAMLとXMLはどちらも複数の「ストリーム」をサポートしている. これはファイルの連結や書き込みプロセスの再開に役立つ.
Write
ユーザオブジェクトを書き込む
void cvWrite( CvFileStorage* fs, const char* name,
const void* ptr, CvAttrList attributes=cvAttrList() );
- fs
- ファイルストレージ.
- name
- 書き込まれるオブジェクトの名前.親の構造体がシーケンスの場合は,NULLにしなければならない.
- ptr
- オブジェクトへのポインタ.
- attributes
- オブジェクトの属性.これは特定の型に対して固有である(以下を参照).
関数cvWriteは,オブジェクトをファイルストレージに書き込む. まずcvTypeOfを用いて適切な型情報を見つける.そして,型情報のwriteメソッドが呼び出される.
属性は書き込み手続きをカスタマイズするために使われる.標準の型では以下の属性をサポートしている (全ての*dt属性は,cvWriteRawDataと同じフォーマットを持つ).
- CvSeq
-
- header_dt - CvSeq,または CvChain(シーケンスがフリーマンチェインの場合),または CvContour (シーケンスが輪郭か点列の場合)に続く,シーケンスヘッダのユーザフィールドの説明.
- dt - シーケンス要素の説明.
- recursive - 属性が存在し,「0」でも「false」でも無い場合,シーケンス(輪郭)のすべての木は保存される.
- CvGraph
-
- グラフ頂点のユーザフィールドの説明.
- header_dt - CvGraphに続く,グラフヘッダのユーザフィールドの説明.
- vertex_dt - グラフ頂点のユーザフィールドの説明.
- edge_dt - グラフエッジのユーザフィールドの説明(エッジの重みは常に書かれるため,明示的に指定する必要が無いことに注意).
以下は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;
}
WriteRawData
複数の数値を書き込む
void cvWriteRawData( CvFileStorage* fs, const void* src,
int len, const char* dt );
- fs
- ファイルストレージ.
- src
- 書き込む配列へのポインタ.
- len
- 書き込む配列の要素数.
- dt
- 次に示すフォーマットを持つ配列の個々の要素の仕様.
([count]{'u'|'c'|'w'|'s'|'i'|'f'|'d'})...,で,これらの記号は基本的なC言語の型と同じである.
- 'u' - 8ビット符号なし数
- 'c' - 8ビット符号あり数
- 'w' - 16ビット符号なし数
- 's' - 16ビット符号あり数
- 'i' - 32ビット符号あり数
- 'f' - 単精度浮動小数点型数
- 'd' - 倍精度浮動小数点型数
- 'r' - ポインタ.下位32ビットは,符号あり整数として書き込まれる. この型は,書き込まれる要素同士がリンク構造を持つような構造体を格納するのに利用できる.
関数cvWriteRawDataは,一つ一つの要素が複数の数値の集まりである配列を書き込む. この関数は cvWriteIntと cvWriteRealの繰り返しで置き換えられるが,単一の実行のほうが効率的である. 名前を持つ要素が一つも無いため,マップよりはシーケンスに書き込むべきであることに注意する.
WriteFileNode
ファイルノードを他のファイルストレージに書き込む
void cvWriteFileNode( CvFileStorage* fs, const char* new_node_name,
const CvFileNode* node, int embed );
- fs
- 書き込み先のファイルストレージ.
- new_file_node
- 書き込み先ファイルストレージ内のファイルノードの新しい名前. 元の名前を維持するためには,cvGetFileNodeName(node)を用いる.
- node
- 書き込まれるノード.
- embed
- 書き込まれるノードがコレクションで,このパラメータが0でない場合,階層の余分なレベルは生成されない. その代わりに,nodeの全ての要素は現在書き込まれている構造体に書き込まれる. 当然,マップ要素はマップにのみ書き込まれ,シーケンス要素はシーケンスにのみ書き込まれる.
関数cvWriteFileNodeは,ファイルストレージにファイルノードのコピーを書き込む. この関数の用途として,いくつかのファイルストレージを一つにまとめる,XMLとYAMLのフォーマットを交換する,などが挙げられる.
データの読み込み(Reading Data)
データはファイルストレージから二つの段階を経て取り込まれる.まず要求されたデータを含むファイルノードを探索し, その後にそのノードから手動,もしくは特別なreadメソッドを用いて取り込む.
GetRootFileNode
ファイルストレージのトップレベルノードの一つを取り込む
CvFileNode* cvGetRootFileNode( const CvFileStorage* fs, int stream_index=0 );
- fs
- ファイルストレージ.
- stream_index
- 0から始まるストリームのインデックス. cvStartNextStreamを参照. 多くの場合,ファイル中に存在するのは一つのストームであるが,複数にもなり得る.
関数cvGetRootFileNodeは,トップレベルファイルノードの一つを返す. トップレベルノードは名前を持たず,それらはストリームに相当し,ファイルストレージ内に次々と保存されている. インデックスが範囲外の場合,この関数はNULLポインタを返す. この関数にstream_index=0,1,...を順に指定して呼び出し,NULLポインタが返されるまで繰り返すことで, すべてのトップレベルノードを得ることができる.この関数はファイルストレージの再帰的な走査のために使われる.
GetFileNodeByName
マップ内またはファイルストレージ内からノードを探索する
CvFileNode* cvGetFileNodeByName( const CvFileStorage* fs,
const CvFileNode* map,
const char* name );
- fs
- ファイルストレージ.
- map
- 親マップ.NULLの場合,この関数は一番最初のものから開始して,全てのトップレベルノード(ストリーム)内を探索する.
- name
- ファイルノード名.
関数cvGetFileNodeByNameは,nameのファイルノードを探索する. ノードの探索はmap内で行われ,ポインタがNULLであれば,ストレージのトップレベルファイルノードを含めて行なわれる. マップに対してこの関数を,シーケンスに対してcvGetSeqElem (またはシーケンスリーダ)を用いることで,ファイルストレージの走査が可能になる. あるキーに対する複数のクエリを高速に処理する(例えば構造体の配列など)ためには,cvGetHashedKeyと cvGetFileNodeを組み合わせて使うと良い.
GetHashedKey
与えた名前に対するユニークなポインタを返す
CvStringHashNode* cvGetHashedKey( CvFileStorage* fs, const char* name,
int len=-1, int create_missing=0 );
- fs
- ファイルストレージ.
- name
- ノード名.
- len
- 名前の長さ(事前に分かっている場合),または計算する必要がある場合は-1.
- create_missing
- absent keyをハッシュテーブルに追加するかどうかを指定するフラグ.
関数cvGetHashedKeyは,特定のファイルノード名に対する唯一のポインタを返す. このポインタは関数cvGetFileNodeByName より高速な関数cvGetFileNodeに渡すことができる. 後者の関数は文字列の内容を比較するのではなく,ポインタの比較により文字列を比較するためである.
次の例では,点列が二つのエントリを持つマップのシーケンスとして表されている.例えば,
%YAML:1.0
points:
- { x: 10, y: 10 }
- { x: 20, y: 20 }
- { x: 30, y: 30 }
# ...
そこで,ハッシュ化された"x"と"y"のポインタを得ることで,点のデコードを高速化することが可能になる.
(例)ファイルストレージから構造体の配列を読み込む
#include "cxcore.h"
#include <stdio>
int main( int argc, char** argv )
{
CvFileStorage* fs = cvOpenFileStorage( "points.yml", 0, CV_STORAGE_READ );
CvStringHashNode* x_key = cvGetHashedKey( fs, "x", -1, 1 );
CvStringHashNode* y_key = cvGetHashedKey( 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; // あるいは x = cvReadInt( xnode, 0 );
int y = ynode->data.i; // あるいは 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; // あるいは x = cvReadInt( xnode, 0 );
int y = ynode->data.i; // あるいは 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;
}
マップヘのアクセス方法に関わらず,単純なシーケンスを使うものに比べて,これはまだかなり低速であることに注意してほしい. 例えば上の例においては,点を一つのシーケンスにおける整数のペアとしてエンコードする方がより効率的である.
GetFileNode
マップまたはファイルストレージ内のノードを見つける
CvFileNode* cvGetFileNode( CvFileStorage* fs, CvFileNode* map,
const CvStringHashNode* key, int create_missing=0 );
- fs
- ファイルストレージ.
- map
- 親マップ.NULLの場合,この関数はトップレベルノードを探す.もしmapとkeyの両方がNULLの場合には, この関数はトップレベルノードを持つマップであるルートファイルノードを返す.
- key
- cvGetHashedKeyで取得されるノード名ヘの唯一のポインタ.
- create_missing
- absent nodeをマップに追加するかどうかを指定するフラグ.
関数cvGetFileNodeは,ファイルノードを見つける. これはcvGetFileNodeByName (cvGetHashedKeyを参照)の高速バージョンである. マップ内に無い場合,この関数は(パースを行う関数が利用して)新しいノードを挿入することが可能である.
GetFileNodeName
ファイルノードの名前を返す
const char* cvGetFileNodeName( const CvFileNode* node );
- node
- ファイルノード.
関数cvGetFileNodeNameファイルノードの名前を返す. ファイルノードが名前を持たないか,nodeがNULL の場合にはNULLを返す.
ReadInt
ファイルノードから整数値を読み込む
int cvReadInt( const CvFileNode* node, int default_value=0 );
- node
- ファイルノード.
- default_value
- nodeがNULLの場合の戻り値.
関数cvReadIntは,ファイルノードで表現された整数値を返す. ファイルノードがNULLの場合,default_valueを返す (つまり,cvGetFileNodeの直後でNULLポインタのチェックを行わず,この関数を使うと便利である). ファイルノードがCV_NODE_INT型を持つ場合,node->data.iを返す. ファイルノードがCV_NODE_REAL型を持つ場合,node->data.fを整数に変換して返す. それ以外の場合,戻り値は不定である.
ReadIntByName
ファイルノードを探索し,その値を返す
int cvReadIntByName( const CvFileStorage* fs, const CvFileNode* map,
const char* name, int default_value=0 );
- fs
- ファイルストレージ.
- map
- 親マップ.NULLの場合,この関数はトップレベルノードを探索する.
- name
- ノード名.
- default_value
- ファイルノードが見つからない場合の戻り値.
関数cvReadIntByNameは,cvGetFileNodeByName とcvReadIntの単純な合成である.
.ReadReal
ファイルノードから浮動小数点型の値を取り込む
double cvReadReal( const CvFileNode* node, double default_value=0. );
- node
- ファイルノード.
- default_value
- nodeがNULLの場合の戻り値.
関数cvReadRealは,ファイルノードで表現される浮動小数点型の値を返す. ファイルノードがNULLの場合,default_valueを返す (つまり,cvGetFileNodeの直後でNULLポインタのチェックを行なわず,この関数を使うと便利である). ファイルノードが CV_NODE_REAL型を持つ場合,node->data.fを返す. ファイルノードがCV_NODE_INT型を持つ場合,node->data.fを浮動小数点型に変換して返す. それ以外の場合,戻り値は不定である.
ReadRealByName
ファイルノードを探してその値を返す
double cvReadRealByName( const CvFileStorage* fs, const CvFileNode* map,
const char* name, double default_value=0. );
- fs
- ファイルストレージ.
- map
- 親マップ.NULLの場合,この関数はトップレベルノードを探す.
- name
- ノード名.
- default_value
- ファイルノードが見つからない場合の戻り値.
関数cvReadRealByNameは,cvGetFileNodeByName とcvReadRealの単純な合成である.
ReadString
ファイルノードから文字列を取り出す
const char* cvReadString( const CvFileNode* node, const char* default_value=NULL );
- node
- ファイルノード.
- default_value
- nodeがNULLの場合の戻り値.
関数cvReadStringは,ファイルノードで表現された文字列を返す. ファイルノードがNULLの場合にはdefault_valueを返す (つまり,cvGetFileNodeの直後でNULLポインタのチェックを行なわず,この関数を使うと便利である). ファイルノードがCV_NODE_STR型を持つ場合にはnode->data.str.ptrを返す. それ以外の場合,戻り値は不定である.
ReadStringByName
ファイルノードを探索して,その値を返す
const char* cvReadStringByName( const CvFileStorage* fs, const CvFileNode* map,
const char* name, const char* default_value=NULL );
- fs
- ファイルストレージ.
- map
- 親マップ.NULLの場合,この関数はトップレベルノードを探索する.
- name
- ノード名.
- default_value
- ファイルノードが見つからない場合の戻り値.
関数cvReadStringByNameは,cvGetFileNodeByNameと cvReadStringの単純な合成である.
Read
オブジェクトをデコードし,そのポインタを返す
void* cvRead( CvFileStorage* fs, CvFileNode* node,
CvAttrList* attributes=NULL );
- fs
- ファイルストレージ.
- node
- ルートオブジェクトノード.
- attributes
- 使用されないパラメータ.
関数cvReadは,ユーザオブジェクトをデコードし (オブジェクトをファイルストレージのサブツリーからネイティブな表現で作成),それを返す. デコードされるオブジェクトは,readメソッドをサポートする登録された型のインスタンスでなけらばならない (CvTypeInfoを参照). オブジェクトの型はファイル内でエンコードされた型名で決定される. もしオブジェクトが動的構造体の場合,メモリストレージ内にも生成され, cvOpenFileStorageに渡される. ここでNULLポインタが渡された場合,一時的なメモリストレージの中ではcvReleaseFileStorage が呼ばれた時に解放される. もしオブジェクトが動的構造体でない場合,ヒープ内に生成され,特別な関数か標準のcvRelease を使って解放する必要がある.
ReadByName
オブジェクトを探索し,デコードする
void* cvReadByName( CvFileStorage* fs, const CvFileNode* map,
const char* name, CvAttrList* attributes=NULL );
- fs
- ファイルストレージ.
- map
- 親マップ.NULLの場合,この関数はトップレベルノードを探索する.
- name
- ノード名.
- attributes
- 使用されないパラメータ.
関数cvReadByNameは,cvGetFileNodeByName とcvReadの単純な合成である.
ReadRawData
複数の数値を読み込む
void cvReadRawData( const CvFileStorage* fs, const CvFileNode* src,
void* dst, const char* dt );
- fs
- ファイルストレージ.
- src
- 数値を読み込むファイルノード(シーケンス).
- dst
- 書き込み先の配列へのポインタ.
- dt
- 配列の個々の要素の仕様.仕様はcvWriteRawDataと同じ.
関数cvReadRawDataは,スカラーのシーケンスで表されたファイルノードから要素を読み込む.
StartReadRawData
ファイルノードのシーケンスリーダの初期化
void cvStartReadRawData( const CvFileStorage* fs, const CvFileNode* src,
CvSeqReader* reader );
- fs
- ファイルストレージ.
- src
- 読み込むファイルノード(シーケンス).
- reader
- シーケンスリーダへのポインタ.
関数cvStartReadRawDataは,ファイルノードからデータを読み込むためのシーケンスリーダを初期化する. 初期化されたリーダはcvReadRawDataSliceに渡すことができる.
ReadRawDataSlice
複数の数値のシーケンスを読み込む
void cvReadRawDataSlice( const CvFileStorage* fs, CvSeqReader* reader,
int count, void* dst, const char* dt );
- fs
- ファイルストレージ.
- reader
- シーケンスリーダ.cvStartReadRawDataで初期化する.
- count
- 読み込む要素数.
- dst
- 出力配列へのポインタ.
- dt
- 各配列要素の仕様.仕様はcvWriteRawDataと同じ.
関数cvReadRawDataSliceは,ファイルから,シーケンスで表現される一つまたは複数の要素をユーザ定義配列へ読み込む. 読み込むシーケンス要素の総数はcountと各配列要素の要素数の積である. 例えばdt='2if'の場合,この関数はcount*3のシーケンス要素を読み込む. リーダがcvSetSeqReaderPosで再配置されると, ファイルノードシーケンスの幾つかの部分は読み飛ばされるか,重複して読み込まれる可能性がある.
実行時型情報と汎用関数(RTTI and Generic Functions)
CvTypeInfo
型情報
typedef int (CV_CDECL *CvIsInstanceFunc)( const void* struct_ptr );
typedef void (CV_CDECL *CvReleaseFunc)( void** struct_dblptr );
typedef void* (CV_CDECL *CvReadFunc)( CvFileStorage* storage, CvFileNode* node );
typedef void (CV_CDECL *CvWriteFunc)( CvFileStorage* storage,
const char* name,
const void* struct_ptr,
CvAttrList attributes );
typedef void* (CV_CDECL *CvCloneFunc)( const void* struct_ptr );
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;
構造体CvTypeInfoは,標準型もしくはユーザ定義型のいずれかに関する情報を含む. その型のインスタンスは,対応するCvTypeInfo構造体へのポインタを持つ可能性がある. どのような場合でも,関数cvTypeOfを使うことで,与えられたオブジェクトの型情報を見つけることができる. また別の方法として,オブジェクトをファイルストレージから読み込む時に使うcvFindType を用いて型の名前から見つけることもできる. ユーザは新しい型をcvRegisterTypeを使って,型情報構造体を型リストの先頭に登録できる. このように,一般的な標準の型から特別な型を作成し,基本的なメソッドをオーバーライドすることが可能である.
RegisterType
新しい型を登録する
void cvRegisterType( const CvTypeInfo* info );
- info
- 型情報構造体.
関数cvRegisterTypeは,infoに記述された新しい型を登録する. この関数は構造体のコピーを作成するので,ユーザは関数呼び出し後にその構造体を削除しなければならない.
UnregisterType
型の登録を取り消す
void cvUnregisterType( const char* type_name );
- type_name
- 登録を取り消す型の名前.
関数cvUnregisterTypeは,指定した名前の型の登録を取り消す. もしその名前が不明であれば,cvTypeOfを使って型のインスタンスから探すか, もしくはcvFirstTypeから型リストを順に見て型情報を探し, cvUnregisterType(info->type_name)を実行することで取り消すことができる.
FirstType
型リストの先頭を返す
CvTypeInfo* cvFirstType( void );
関数cvFirstTypeは,登録されている型のリストの先頭のものを返す. CvTypeInfo構造体のprevと nextフィールドを使うことで,リストをすべて走査できる.
FindType
名前から型を見つける
CvTypeInfo* cvFindType( const char* type_name );
- type_name
- 型の名前.
関数cvFindTypeは,登録された型を名前で探す. NULLを返した場合,指定した名前の型は存在しない.
TypeOf
オブジェクトの型を返す
CvTypeInfo* cvTypeOf( const void* struct_ptr );
- struct_ptr
- オブジェクトへのポインタ.
関数cvTypeOfは,与えられたオブジェクトの型を見つける. 登録された型のリストを走査し,それぞれの型情報構造体の関数/メソッドis_instanceを呼び, それらの一つが非0を返すか,すべてのリストを走査し終えるまで繰り返す.後者の場合,この関数はNULLを返す.
Release
オブジェクトを解放する
void cvRelease( void** struct_ptr );
- struct_ptr
- オブジェクトのポインタのポインタ.
関数cvReleaseは,与えられたオブジェクトの型を見つけ,与えられたポインタのポインタを引数にreleaseを呼ぶ.
Clone
オブジェクトのコピーを作成する
void* cvClone( const void* struct_ptr );
- struct_ptr
- コピーするオブジェクト.
関数cvCloneは,与えたオブジェクトの型を見つけ,渡されたオブジェクトを引数にcloneを呼ぶ.
Save
オブジェクトをファイルに保存する
void cvSave( const char* filename, const void* struct_ptr,
const char* name=NULL,
const char* comment=NULL,
CvAttrList attributes=cvAttrList());
- filename
- ファイル名.
- struct_ptr
- 保存するオブジェクト.
- name
- オブジェクト名(オプション).NULLの場合,名前はfilenameから生成される.
- comment
- ファイルの最初に置かれるコメント(オプション).
- attributes
- cvWriteに渡される属性(オプション).
関数cvSaveは,オブジェクトをファイルに保存する. これは,cvWriteへの簡単なインタフェースを提供する.
Load
オブジェクトをファイルから読み込む
void* cvLoad( const char* filename, CvMemStorage* memstorage=NULL,
const char* name=NULL, const char** real_name=NULL );
- filename
- ファイル名.
- memstorage
- CvSeqやCvGraph などの動的構造体のためのメモリストレージ.行列や画像には用いられない.
- name
- オブジェクト名(オプション).NULLの場合,ファイルストレージにある最初のトップレベルオブジェクトが読み込まれる.
- real_name
- 読み込まれたオブジェクトの名前が代入される出力パラメータ(オプション)name=NULLの場合に役立つ.
関数cvLoadは,ファイルからオブジェクトを読み込む. これはcvReadへの簡単なインタフェースを提供する. オブジェクトが読み込まれた後,ファイルストレージは閉じられて一時的なバッファは全て消去される. 従って,シーケンスや輪郭,グラフなどの動的構造体を読み込むためには,この関数に正しい出力先メモリストレージを与える必要がある.
その他の関数(Miscellaneous Functions)
CheckArr
入力配列のすべての要素について,無効な値が存在しないかをチェックする
int cvCheckArr( const CvArr* arr, int flags=0,
double min_val=0, double max_val=0);
#define cvCheckArray cvCheckArr
- arr
- チェック対象の配列.
- flags
- 処理フラグ.0 あるいは以下の値の組み合わせ.
CV_CHECK_RANGE - セットされている場合,配列のすべての要素について [minVal,maxVal) の範囲内であるかどうかをチェックする. それ以外の場合,すべての要素が NaN か ±(Infinity) でないかだけをチェックする.
CV_CHECK_QUIET - セットされている場合,要素に無効な値や範囲外のものがあっても,エラーを発生させない. - min_val
- 有効な値域の下限値(この値以上).CV_CHECK_RANGE がセットされているときのみ有効.
- max_val
- 有効な値域の上限値(この値未満).CV_CHECK_RANGE がセットされているときのみ有効.
関数 cvCheckArr は,すべての配列要素が NaN あるいは ±(Infinity)でないかをチェックする. CV_CHECK_RANGE がセットされている場合は,すべての配列要素がminVal より大きいか等しく, かつ maxVal よりも小さいかをチェックする. チェックが正しく終わった場合(すべての要素が有効で指定範囲内であるとき)関数は0以外を返し,それ以外の場合は0を返す. エラーがあった場合,CV_CHECK_QUIET フラグがセットされていなければ,関数はランタイムエラーとして取り上げる.
KMeans2
ベクトル集合を,与えられたクラスタ数に分割する
void cvKMeans2( const CvArr* samples, int cluster_count,
CvArr* labels, CvTermCriteria termcrit );
- samples
- 浮動小数点型の入力サンプル行列.1行あたり一つのサンプル.
- cluster_count
- 集合を分割するクラスタ数.
- labels
- 出力の整数ベクトル.すべてのサンプルについて,それぞれがどのクラスタに属しているかが保存されている.
- termcrit
- 最大繰り返し数と(または),精度(1ループでの各クラスタ中心位置移動距離)の指定.
関数 cvKMeans2 は,入力サンプルを各クラスタに分類するために cluster_count 個のクラスタの中心を求める k-means 法を実装する.出力 labels(i) は,配列 samples のi番目の行のサンプルが属するクラスタのインデックスを表す.
(例)複数のガウス分布を持つランダムサンプルをK-means法でクラスタリングする
#include "cxcore.h"
#include "highgui.h"
void main( int argc, char** argv )
{
#define MAX_CLUSTERS 5
CvScalar color_tab[MAX_CLUSTERS];
IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );
CvRNG rng = cvRNG(0xffffffff);
color_tab[0] = CV_RGB(255,0,0);
color_tab[1] = CV_RGB(0,255,0);
color_tab[2] = CV_RGB(100,100,255);
color_tab[3] = CV_RGB(255,0,255);
color_tab[4] = CV_RGB(255,255,0);
cvNamedWindow( "clusters", 1 );
for(;;)
{
int k, cluster_count = cvRandInt(&rng)%MAX_CLUSTERS + 1;
int i, sample_count = cvRandInt(&rng)%1000 + 1;
CvMat* points = cvCreateMat( sample_count, 1, CV_32FC2 );
CvMat* clusters = cvCreateMat( sample_count, 1, CV_32SC1 );
/* 複数のガウス分布からランダムサンプルを生成する */
for( k = 0; k < cluster_count; k++ )
{
CvPoint center;
CvMat point_chunk;
center.x = cvRandInt(&rng)%img->width;
center.y = cvRandInt(&rng)%img->height;
cvGetRows( points, &point_chunk, k*sample_count/cluster_count,
k == cluster_count - 1 ? sample_count : (k+1)*sample_count/cluster_count );
cvRandArr( &rng, &point_chunk, CV_RAND_NORMAL,
cvScalar(center.x,center.y,0,0),
cvScalar(img->width/6, img->height/6,0,0) );
}
/* サンプルをシャッフルする */
for( i = 0; i < sample_count/2; i++ )
{
CvPoint2D32f* pt1 = (CvPoint2D32f*)points->data.fl + cvRandInt(&rng)%sample_count;
CvPoint2D32f* pt2 = (CvPoint2D32f*)points->data.fl + cvRandInt(&rng)%sample_count;
CvPoint2D32f temp;
CV_SWAP( *pt1, *pt2, temp );
}
cvKMeans2( points, cluster_count, clusters,
cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0 ));
cvZero( img );
for( i = 0; i < sample_count; i++ )
{
CvPoint2D32f pt = ((CvPoint2D32f*)points->data.fl)[i];
int cluster_idx = clusters->data.i[i];
cvCircle( img, cvPointFrom32f(pt), 2, color_tab[cluster_idx], CV_FILLED );
}
cvReleaseMat( &points );
cvReleaseMat( &clusters );
cvShowImage( "clusters", img );
int key = cvWaitKey(0);
if( key == 27 ) // 'ESC'
break;
}
}
SeqPartition
データシーケンスを同値類(同じクラスに属すると定義されたデータ群)に分割する
typedef int (CV_CDECL* CvCmpFunc)(const void* a, const void* b, void* userdata);
int cvSeqPartition( const CvSeq* seq, CvMemStorage* storage, CvSeq** labels,
CvCmpFunc is_equal, void* userdata );
- seq
- 分割対象のシーケンス.
- storage
- 同値類として分割されたシーケンスの保存領域.NULLの場合は,seq->storage を使用する.
- labels
- 出力パラメータ.入力シーケンスの各要素に割り振られた(分割結果を表す)0から始まるラベルシーケンスへのポインタのポインタ.
- is_equal
- 2つのシーケンス要素が同じクラスである場合,関係関数は 0以外を返す. そうでなければ0を返す.分割アルゴリズムは,同値基準として関係関数の推移閉包を用いる.
- userdata
- 関数is_equal の引数として渡すデータへのポインタ.
関数 cvSeqPartition は,集合を一つ以上の同値類に分割する2次的(計算量がO(n2))アルゴリズムを実装する. この関数は同値類の個数を返す.
(例)2次元の点の分割
#include "cxcore.h"
#include "highgui.h"
#include <stdio.h>
CvSeq* point_seq = 0;
IplImage* canvas = 0;
CvScalar* colors = 0;
int pos = 10;
int is_equal( const void* _a, const void* _b, void* userdata )
{
CvPoint a = *(const CvPoint*)_a;
CvPoint b = *(const CvPoint*)_b;
double threshold = *(double*)userdata;
return (double)(a.x - b.x)*(a.x - b.x) + (double)(a.y - b.y)*(a.y - b.y) <= threshold;
}
void on_track( int pos )
{
CvSeq* labels = 0;
double threshold = pos*pos;
int i, class_count = cvSeqPartition( point_seq, 0, &labels, is_equal, &threshold );
printf("%4d classes\n", class_count );
cvZero( canvas );
for( i = 0; i < labels->total; i++ )
{
CvPoint pt = *(CvPoint*)cvGetSeqElem( point_seq, i );
CvScalar color = colors[*(int*)cvGetSeqElem( labels, i )];
cvCircle( canvas, pt, 1, color, -1 );
}
cvShowImage( "points", canvas );
}
int main( int argc, char** argv )
{
CvMemStorage* storage = cvCreateMemStorage(0);
point_seq = cvCreateSeq( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
CvRNG rng = cvRNG(0xffffffff);
int width = 500, height = 500;
int i, count = 1000;
canvas = cvCreateImage( cvSize(width,height), 8, 3 );
colors = (CvScalar*)cvAlloc( count*sizeof(colors[0]) );
for( i = 0; i < count; i++ )
{
CvPoint pt;
int icolor;
pt.x = cvRandInt( &rng ) % width;
pt.y = cvRandInt( &rng ) % height;
cvSeqPush( point_seq, &pt );
icolor = cvRandInt( &rng ) | 0x00404040;
colors[i] = CV_RGB(icolor & 255, (icolor >> 8)&255, (icolor >> 16)&255);
}
cvNamedWindow( "points", 1 );
cvCreateTrackbar( "threshold", "points", &pos, 50, on_track );
on_track(pos);
cvWaitKey(0);
return 0;
}
エラーハンドリングとシステム関数(Error Handling and System Functions)
エラーハンドリング(Error Handling)
OpenCV におけるエラーハンドリングは,IPL(Image Processing Library)と似ている. エラーが発生した場合でも,関数はエラーコードを返さない. その代わり,エラーステータスをcvSetErrStatusを用いてセットし, 標準またはユーザ定義のエラーハンドラ(メッセージボックスの表示や,ログに書き込む,など. cvRedirectError, cvNulDevReport, cvStdErrReport, cvGuiBoxReportを参照) を呼び出す関数cvErrorを呼ぶマクロCV_ERROR を用いてエラーの通知を行う. 各プログラムスレッドについて,それぞれ一つずつ,現在のエラーステータス(一つの整数値)を持つグローバル変数が存在する. このエラーステータスは,関数 cvGetErrStatus を用いて取り出すことが可能である.
エラーハンドリングには,以下の三つのモードが存在する(cvSetErrMode と cvGetErrMode を参照).
- Leaf
- プログラムはエラーハンドラを呼び出した後,途中終了する.デフォルト.エラー発生後,直ちに通知されるので,デバッグ時に有効. しかし,製品(完成版の)システムでは,他の二つのモードの使用が制御しやすいので好ましい.
- Parent
- プログラムは途中終了しないが,エラーハンドラが呼び出される.スタックは解放されない(C++の例外処理を用いないため). ユーザはCxCoreの関数cvGetErrStatusを呼び出し,エラーコードをチェックし,対処を行わなければならない.
- Silent
- Parentモードとほぼ同じだが,エラーハンドラは呼び出されない.
実際は,モードLeaf と Parent の動作はエラーハンドラによって実装される. 上記の説明はcvNulDevReport, cvStdErrReport に関しては正しい. cvGuiBoxReport は多少異なった動作をし,さらに, カスタマイズされたエラーハンドラは,全く違う動作の実装になる可能性がある.
ERROR Handling Macros
エラー表示やチェックなどの機能をもつマクロ群
/* 関数内の処理ステートメントを挟み,それらをプロローグ(リソースの初期化部)とエピローグ
(確保されたリソースの解放部)に分離する特別なマクロ */
#define __BEGIN__ {
#define __END__ goto exit; exit: ; }
/* 「リソース解放ステージ」へ進む */
#define EXIT goto exit
/* CV_ERROR() で使用する関数名をローカルに定義する */
#define CV_FUNCNAME( Name ) ¥
static char cvFuncName[] = Name
/* 現状のエラーを報告する */
#define CV_ERROR( Code, Msg ) ¥
{ ¥
cvError( (Code), cvFuncName, Msg, __FILE__, __LINE__ ); ¥
EXIT; ¥
}
/* CXCOREの関数呼び出しの後の状態をチェックする */
#define CV_CHECK() ¥
{ ¥
if( cvGetErrStatus() < 0 ) ¥
CV_ERROR( CV_StsBackTrace, "Inner function failed." ); ¥
}
/* CXCOREの関数呼び出しとCV_CHECK()呼び出しの簡略表現 */
#define CV_CALL( Statement ) ¥
{ ¥
Statement; ¥
CV_CHECK(); ¥
}
/* デバッグモードとリリースモード両方に対応した状態チェック */
#define CV_ASSERT( Condition ) ¥
{ ¥
if( !(Condition) ) ¥
CV_ERROR( CV_StsInternal, "Assertion: " #Condition " failed" ); ¥
}
/* これらのマクロは,それぞれ対応するマクロCV_... と似ているが,
終了ラベルも定義用のcvFuncNameも必要としない */
#define OPENCV_ERROR(status,func_name,err_msg) ...
#define OPENCV_ERRCHK(func_name,err_msg) ...
#define OPENCV_ASSERT(condition,func_name,err_msg) ...
#define OPENCV_CALL(statement) ...
ここでは,詳細な説明の代わりに,代表的なCXCOREの関数とその使用方法を示す.
エラーハンドリングマクロの使用方法
#include "cxcore.h"
#include <stdio.h>
void cvResizeDCT( CvMat* input_array, CvMat* output_array )
{
CvMat* temp_array = 0; // いずれ解放されるべきポインタの宣言.
CV_FUNCNAME( "cvResizeDCT" ); // cvFuncNameの宣言
__BEGIN__; // 処理の開始.このマクロの直後に何らかの宣言があるかもしれないが,
// それらは,エピローグ部からはアクセスできない.
if( !CV_IS_MAT(input_array) || !CV_IS_MAT(output_array) )
// エラー表示の為に CV_ERROR() を用いる
CV_ERROR( CV_StsBadArg, "input_array or output_array are not valid matrices" );
// 後のバージョンで削除されるいくつかの制限事項,CV_ASSERT() でチェックされるかもしれない
CV_ASSERT( input_array->rows == 1 && output_array->rows == 1 );
// 安全な関数呼び出しのために CV_CALL を用いる
CV_CALL( temp_array = cvCreateMat( input_array->rows, MAX(input_array->cols,output_array->cols),
input_array->type ));
if( output_array->cols > input_array->cols )
CV_CALL( cvZero( temp_array ));
temp_array->cols = input_array->cols;
CV_CALL( cvDCT( input_array, temp_array, CV_DXT_FORWARD ));
temp_array->cols = output_array->cols;
CV_CALL( cvDCT( temp_array, output_array, CV_DXT_INVERSE ));
CV_CALL( cvScale( output_array, output_array, ¥
1./sqrt((double)input_array->cols*output_array->cols), 0 ));
__END__; // 処理の終了.マクロの後に書く.
// temp_array を解放する.エラーが発生する前に temp_array の領域確保が終わっていない場合,
// cvRleaseMatが処理を行う.今回のような場合は,なにもしない.
cvReleaseMat( &temp_array );
}
int main( int argc, char** argv )
{
CvMat* src = cvCreateMat( 1, 512, CV_32F );
#if 1 /* エラーなし */
CvMat* dst = cvCreateMat( 1, 256, CV_32F );
#else
CvMat* dst = 0; /* エラー処理のメカニズムをテストする */
#endif
cvSet( src, cvRealScalar(1.), 0 );
#if 0 /* エラーハンドラの起動をしないようにするためには 0 から 1 へ変更する */
cvSetErrMode( CV_ErrModeSilent );
#endif
cvResizeDCT( src, dst ); // エラーが発生した場合,メッセージボックスがポップアップするか,
// メッセージがログに書き込まれるか,あるいはユーザー定義の処理が行われる
if( cvGetErrStatus() < 0 )
printf("Some error occured" );
else
printf("Everything is OK" );
return 0;
}
GetErrStatus
現在のエラーステータスを返す
int cvGetErrStatus( void );
関数 cvGetErrStatus は,現在のエラーステータスを返す. ステータス値は,関数cvSetErrStatus によってセットされる. Leafモードの場合は,エラー発生後,直ちにプログラムが途中終了するので,関数呼出し後も常に制御可能にしておくためには, cvSetErrModeでエラーモードをParent か Silentにセットしておくべきであることに注意する.
SetErrStatus
エラーステータスをセットする
void cvSetErrStatus( int status );
- status
- エラーステータス.
関数 cvSetErrStatus は,エラーステータスを指定された値にセットする. ほとんどの場合,この関数はエラー処理を行った後にエラーステータスをリセットする(CV_StsOkをセットする)ために用いられる. その他の場合は,cvError あるいは CV_ERROR を呼び出すのが一般的である.
GetErrMode
現在のエラーモードを返す
int cvGetErrMode( void );
関数cvGetErrMode は,現在のエラーモードを返す. モード値は,直前の関数 cvSetErrMode 呼び出しによってセットされる.
SetErrMode
エラーモードをセットする
#define CV_ErrModeLeaf 0
#define CV_ErrModeParent 1
#define CV_ErrModeSilent 2
int cvSetErrMode( int mode );
- mode
- エラーモード.
関数 cvSetErrMode は,指定されたエラーモードをセットする. エラーモードの違いに関しては,このセクションの初めの部分を参照.
Error
エラーを発生させる
int cvError( int status, const char* func_name,
const char* err_msg, const char* file_name, int line );
- status
- エラーステータス.
- func_name
- エラーが発生した関数名.
- err_msg
- エラーについての追加情報/診断結果.
- file_name
- エラーが発生したファイル名.
- line
- エラーが発生した行番号.
関数 cvError は,(cvSetErrStatusを用いて) エラーステータスを指定の値にセットする.さらにエラーモードがSilent以外の場合は,エラーハンドラを呼び出す.
ErrorStr
エラーステータスのコードのテキスト情報を返す
const char* cvErrorStr( int status );
- status
- エラーステータス.
関数 cvErrorStr は,指定したエラーステータスコードのテキスト記述を返す. 不明なステータスの場合はNULLポインタを返す.
RedirectError
新しいエラーハンドラをセットする
typedef int (CV_CDECL *CvErrorCallback)( int status, const char* func_name,
const char* err_msg, const char* file_name, int line );
CvErrorCallback cvRedirectError( CvErrorCallback error_handler,
void* userdata=NULL, void** prev_userdata=NULL );
- error_handler
- 新しいエラーハンドラ.
- userdata
- エラーハンドラへの引数として渡される任意のポインタ.
- prev_userdata
- あらかじめ割り当てられているユーザデータへのポインタのポインタ.
関数 cvRedirectError は,standard handlersの中の一つか, 特定のインタフェースを持つ独自のハンドラを新しいエラーハンドラにセットする. エラーハンドラは,関数cvErrorと同じパラメータを持つ. ハンドラが0以外の値を返した場合,プログラムは途中終了し,それ以外の場合は実行し続ける. エラーハンドラは,このような動作を決めるためにcvGetErrModeで現在のエラーモードを確認している.
cvNulDevReport cvStdErrReport cvGuiBoxReport
標準のエラーハンドリングを提供する
int cvNulDevReport( int status, const char* func_name, const char* err_msg, const char* file_name, int line, void* userdata ); int cvStdErrReport( int status, const char* func_name, const char* err_msg, const char* file_name, int line, void* userdata ); int cvGuiBoxReport( int status, const char* func_name, const char* err_msg, const char* file_name, int line, void* userdata );
- status
- エラーステータス.
- func_name
- エラーが発生した関数名.
- err_msg
- エラーについての追加情報/診断結果.
- file_name
- エラーが発生したファイル名.
- line
- エラーが発生した行番号.
- userdata
- ユーザーデータへのポインタ.標準ハンドラでは無視される.
関数 cvNullDevReport, cvStdErrReport と cvGuiBoxReportは標準のエラーハンドリングを提供する. Win32でのデフォルトエラーハンドラはcvGuiBoxReportであり,他のシステムではcvStdErrReportとなる. cvGuiBoxReportはエラーメッセージを表示するメッセージボックスをポップアップさせ,さらにいくつかのオプションを提供する. 前述のsample codeでのメッセージボックスを用いたエラー処理の例を以下に示す.
エラーメッセージボックス
標準エラー出力へのエラーメッセージ出力(Leaf モード)
OpenCV ERROR: Bad argument (input_array or output_array are not valid matrices)
in function cvResizeDCT, D:¥User¥VP¥Projects¥avl_proba¥a.cpp(75)
Terminating the application...
システム関数(System Functions)
Alloc
メモリバッファの領域を確保する
void* cvAlloc( size_t size );
- size
- バッファサイズ(バイト単位).
関数 cvAlloc は size バイトの領域を確保し,その領域へのポインタを返す. エラーが生じた場合は,エラーを通知しNULLポインタを返す. デフォルトで cvAlloc は,mallocを呼ぶ icvAlloc の呼び出しを行うが, 関数 cvSetMemoryManager を用いて, ユーザ定義のメモリ領域確保/領域解放のための関数を定義することも可能である.
Free
メモリバッファの領域を解放する
void cvFree( void** ptr );
- ptr
- 解放する領域へのポインタのポインタ.
関数 cvFree は,cvAllocによって確保されたメモリバッファの領域解放を行う. 関数から出る際にバッファへのポインタをクリアするため,ポインタのポインタを用いている. *ptr が既に NULL の場合,この関数は何もしない.
GetTickCount
tics数を返す
int64 cvGetTickCount( void );
関数 cvGetTickCount は,プラットフォーム依存の開始時点からのtics数(スタートアップからのCPU ticks数,1970年からのミリ秒等)を返す. この関数は,ある関数やユーザコードの実行時間を正確に計測するのに便利である. tics数から時間単位に変換するためには,cvGetTickFrequencyを用いる.
GetTickFrequency
1マイクロ秒あたりのtics数を返す
double cvGetTickFrequency( void );
関数 cvGetTickFrequency は,1マイクロ秒あたりのtics数を返す. つまり,cvGetTickCount() を cvGetTickFrequency() で割った値が,プラットフォーム依存の開始時刻からのマイクロ秒単位の時刻になる.
RegisterModule
他のモジュールを登録する
typedef struct CvPluginFuncInfo
{
void** func_addr;
void* default_func_addr;
const char* func_names;
int search_modules;
int loaded_from;
}
CvPluginFuncInfo;
typedef struct CvModuleInfo
{
struct CvModuleInfo* next;
const char* name;
const char* version;
CvPluginFuncInfo* func_tab;
}
CvModuleInfo;
int cvRegisterModule( const CvModuleInfo* module_info );
- module_info
- モジュールに関する情報.
関数 cvRegisterModule は,モジュールが登録されているリストに新しいモジュールを追加する. モジュールが登録されると,そのモジュールの情報は,関数cvGetModuleInfo を用いて取り出すことができるようになる. 登録されたモジュールも,CXCOREでサポートされている最適化プラグイン(IPP,MKL,...)を活用する. CXCORE 及び CV (computer vision),CVAUX (auxilary computer vision) や HIGHGUI (visualization & image/video acquisition) などはモジュールの一例である. 通常は,登録が終わってから共有ライブラリ(shared library)がロードされる. どのように登録されるかの詳細は,cxcore/src/cxswitcher.cpp と cv/src/cvswitcher.cpp を参照のこと. また,IPPとMKLがどのようにモジュールとリンクされるのかについては,cxcore/src/cxswitcher.cpp, cxcore/src/_cxipp.h を参照のこと.
GetModuleInfo
登録されたモジュールとプラグインの情報を取り出す
void cvGetModuleInfo( const char* module_name,
const char** version,
const char** loaded_addon_plugins );
- module_name
- 対象のモジュール名,NULLの場合はすべてのモジュール.
- version
- 出力パラメータ.モジュールについての情報(バージョンを含む).
- loaded_addon_plugins
- CXCOREがロード可能な最適化プラグインの名前とバージョンのリスト.
関数 cvGetModuleInfo は,登録モジュールの一つ,またはすべての情報を返す. 返された情報はライブラリ内部に保存される.そのためユーザが領域解放や返された文字列の変更を行う必要はない.
UseOptimized
最適化モード/非最適化モードを切り替える
int cvUseOptimized( int on_off );
- on_off
- 0以外のとき最適化,0のとき非最適化.
関数 cvUseOptimized は,cxcoreや,OpenCVのほかのライブラリなどを,純粋なC言語だけで実装したモードと, 可能な部分はIPP と MKLを用いて最適化したモードとを切り替える. cvUseOptimized(0) が呼ばれたときは,最適化ライブラリはロードされない. この関数はデバッグ時,IPP&MKLのアップグレード時,処理速度を動作中に比較したい時などに有効である. 戻り値は,ロードされた最適化関数の数. デフォルトで最適化プラグインがロードされるので,プログラムの最初にcvUseOptimized(1)を呼ぶ必要はない (実際,スタートアップ時に処理時間が増えるだけ)ことに注意.
SetMemoryManager
カスタムあるいはデフォルトのメモリ管理関数を指定する
typedef void* (CV_CDECL *CvAllocFunc)(size_t size, void* userdata);
typedef int (CV_CDECL *CvFreeFunc)(void* pptr, void* userdata);
void cvSetMemoryManager( CvAllocFunc alloc_func=NULL,
CvFreeFunc free_func=NULL,
void* userdata=NULL );
- alloc_func
- 領域確保関数(インタフェースは,コンテクストを決定するために使用されることがあるuserdata以外は, mallocと同じ).
- free_func
- 領域解放関数(インタフェースは,freeと同じ).
- userdata
- カスタム関数に引数として渡すユーザデータ.
関数 cvSetMemoryManager は,cvAlloc, cvFree や 上位レベルの関数 (例えば,cvCreateImage)から呼ばれるユーザ定義のメモリ管理関数(mallocとfreeに取って代わるもの)の設定を行う. cvAllocによってデータ領域を確保するときに,この関数が呼ばれることに注意. 再帰呼び出しの無限ループを避けるため,ユーザ定義の領域確保/解放関数では cvAllocとcvFreeの呼び出しを行ってはいけない.
alloc_func と free_func へのポインタが NULLの場合は, デフォルトのメモリ管理関数が用いられる.
SetIPLAllocators
画像領域の確保と解放のためのIPL関数に切り替える
typedef IplImage* (CV_STDCALL* Cv_iplCreateImageHeader)
(int,int,int,char*,char*,int,int,int,int,int,
IplROI*,IplImage*,void*,IplTileInfo*);
typedef void (CV_STDCALL* Cv_iplAllocateImageData)(IplImage*,int,int);
typedef void (CV_STDCALL* Cv_iplDeallocate)(IplImage*,int);
typedef IplROI* (CV_STDCALL* Cv_iplCreateROI)(int,int,int,int,int);
typedef IplImage* (CV_STDCALL* Cv_iplCloneImage)(const IplImage*);
void cvSetIPLAllocators( Cv_iplCreateImageHeader create_header,
Cv_iplAllocateImageData allocate_data,
Cv_iplDeallocate deallocate,
Cv_iplCreateROI create_roi,
Cv_iplCloneImage clone_image );
#define CV_TURN_ON_IPL_COMPATIBILITY() ¥
cvSetIPLAllocators( iplCreateImageHeader, iplAllocateImage, ¥
iplDeallocate, iplCreateROI, iplCloneImage )
- create_header
- iplCreateImageHeaderへのポインタ.
- allocate_data
- iplAllocateImageへのポインタ.
- deallocate
- iplDeallocateへのポインタ.
- create_roi
- iplCreateROIへのポインタ.
- clone_image
- iplCloneImageへのポインタ.
関数 cvSetIPLAllocatorsは,CXCOREが,画像領域の確保と解放を行うためにIPLの関数を使用するよう変更する. 利便性のために,ラッピングマクロ CV_TURN_ON_IPL_COMPATIBILITYが存在する. この関数は,IPL と CXCORE/OpenCVを同時に使っていたり,iplCreateImageHeaderなどを呼んでいたりする場合には有効である. IPLが単にデータ処理のみで,すべての領域確保や解放はCXCOREで行っている場合や, 逆にすべての領域確保や解放をIPLで,そしてデータ処理はOpenCVの関数で行っている場合は,この関数は不要である.
GetNumThreads
現在使われているスレッド数を返す
int cvGetNumThreads( void);
関数 cvGetNumThreadsは,(OpenMPを用いて)並列化されたOpenCV関数によって使用される現在のスレッド数を返す.
SetNumThreads
スレッド数をセットする
void cvSetNumThreads( int threads=0 );
- threads
- スレッド数.
関数 cvSetNumThreads は,並列化されたOpenCV関数によって使用されるスレッド数をセットする. 引数が0か負の場合,またプログラム開始時は,スレッド数にOpenMPランタイムの関数omp_get_num_procs() の戻り値であるシステムのプロセッサ数がセットされる.
GetThreadNum
現在のスレッドのインデックスを返す
int cvGetThreadNum( void );
関数 cvGetThreadNum は,この関数を呼んだスレッドのインデックス (0からcvGetNumThreads()-1の範囲の値)を返す. この関数は,OpenMPランタイムの関数omp_get_thread_num()のラッパーである. 取り出されたインデックスは,並列化された各コード内のローカルスレッドのデータにアクセスするために用いられる.
関数リスト(アルファベット順)
A
| AbsDiff | AddWeighted | Avg |
| AbsDiffS | Alloc | AvgSdv |
| Add | And | |
| AddS | AndS |
B
| BackProjectPCA |
C
D
| DCT | Det | DrawContours |
| DFT | Div | |
| DecRefData | DotProduct |
E
| EigenVV | EllipseBox | Error |
| Ellipse | EndWriteSeq | ErrorStr |
| Ellipse2Poly | EndWriteStruct | Exp |
F
| FastArctan | FindGraphEdgeByPtr | FlushSeqWriter |
| FillConvexPoly | FindType | Free |
| FillPoly | FirstType | |
| FindGraphEdge | Flip |
G
I
| InRange | InitLineIterator | InsertNodeIntoTree |
| InRangeS | InitMatHeader | InvSqrt |
| IncRefData | InitMatNDHeader | Invert |
| InitFont | InitSparseMatIterator | IsInf |
| InitImageHeader | InitTreeNodeIterator | IsNaN |
K
| KMeans2 |
L
| LUT | Load | |
| Line | Log |
M
| Mahalonobis | MemStorageAlloc | MinS |
| MakeSeqHeaderForArray | MemStorageAllocString | MixChannels |
| Mat | Merge | Mul |
| Max | Min | MulSpectrums |
| MaxS | MinMaxLoc | MulTransposed |
N
| NextGraphItem | Norm | Not |
| NextTreeNode | Normalize | NulDevReport |
O
| OpenFileStorage | Or | OrS |
P
| PerspectiveTransform | Pow | Ptr*D |
| PolarToCart | PrevTreeNode | PutText |
| PolyLine | ProjectPCA |
R
S
T
| Trace | Transpose | TypeOf |
| Transform | TreeToNodeSeq |
U
| UnregisterType | UseOptimized |
W
| Write | WriteInt | WriteString |
| WriteComment | WriteRawData | |
| WriteFileNode | WriteReal |
X
| Xor | XorS |
