ユーティリティとシステム関数,マクロ

Error Handling

OpenCVのエラーハンドリングは,IPL(Image Processing Library)の場合と似ています.エラーが発生した場合でも,関数はエラーコードを返しません.その代わりに, Error を呼び出すマクロ CV_ERROR を用いてエラーを発生させます.その中で, SetErrStatus によりエラー状態をセットし,標準あるいはユーザ定義のエラーハンドラ(メッセージボックスを表示したり,ログを書き出したりできます.詳しくは, RedirectError を参照してください)を呼び出します.1スレッドに1つ,現在のエラー状態(整数値)を保存するグローバル変数が存在します.このエラー状態は,関数 GetErrStatus によって取得できます.

エラーハンドリングには3つのモードが存在します( SetErrMode および GetErrMode を参照してください):

  • Leaf . エラーハンドラを呼び出した後に,プログラムが終了します.これはデフォルト値です.エラーが発生すると即座に通知されるので,デバッグ時に役立ちます.しかし,製品版のシステムでは,より細かく制御可能な他の2つのモードの方が適しているかもしれません.
  • Parent . エラーハンドラは呼ばれますが,プログラムは終了しません.また,(C++の例外処理を利用しないので)スタックは巻き戻されません.ユーザは, CxCore の関数を呼び出した後で, GetErrStatus を用いてエラーコードをチェックし,対処を行います.
  • Silent . これは Parent モードと似ていますが,エラーハンドラが呼ばれません.

実際は, Leaf モードと Parent モードの動作は,エラーハンドラによって実装され,その実装された動作に関しては,上述の説明は正しいと言えます.しかし, GuiBoxReport では少し違う挙動を示し,カスタムエラーハンドラに至っては全く異なる動作をする可能性があります.

エラーの発生やチェックなどを行うマクロ.

/* 関数内の処理文を挟むことで,それらをプロローグ(リソースの初期化)と
   エピローグ(確保されたリソースの解放)から分離する特別なマクロ */
#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 )                                       \


/* CXCORE の関数呼び出しの後の状態をチェックします */
#define CV_CHECK()                                                  \


/* CXCORE の関数呼び出しと CV_CHECK() 呼び出しの簡略表現です */
#define CV_CALL( Statement )                                        \


/* デバッグモードとリリースモード両方に対応した状態チェックを行います */
#define CV_ASSERT( Condition )                                          \


/* これらのマクロは,それぞれ対応するマクロ CV_... と似ていますが,
   exit ラベルを必要とせず,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の関数とその使用方法を以下に示します.

Example: Use of Error Handling Macros

#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 が確保されていない場合,
    // cvReleaseMat が適切に処理を行います.今回のような場合は,特にに何もしません.
    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;
}

cv::GetErrStatus

int cvGetErrStatus(void)
現在のエラー状態を返します.

この関数は,現在のエラー状態,つまり直前の SetErrStatus 呼び出しによってセットされた値,を返します. Leaf モードでは,エラー発生後直ちにプログラムが終了するので,関数呼び出し後も常に制御可能にしておくためには, SetErrMode を呼び出して,エラーモードを Parent あるいは Silent にセットしておかなくてはいけません.

cv::SetErrStatus

void cvSetErrStatus(int status)

エラー状態をセットします.

Parameter:status – エラー状態

この関数は,指定された値をエラー状態としてセットします.大抵の場合,この関数は,エラー発生後の復帰時にエラー状態をリセットする( CV_StsOk をセットする)ために利用されます.その他の場合では, ErrorCV_ERROR を呼び出すのが普通です.

cv::GetErrMode

int cvGetErrMode(void)
現在のエラーモードを返します.

この関数は,現在のエラーモード,つまり直前の SetErrMode 呼び出しによってセットされた値を返します.

cv::SetErrMode

..
int cvSetErrMode(int mode)
エラーモードをセットします.

#define CV_ErrModeLeaf 0 #define CV_ErrModeParent 1 #define CV_ErrModeSilent 2

param mode:エラーモード

この関数は,指定されたエラーモードをセットします.エラーモードの違いに関しては,このセクションの最初を参照してください.

cv::Error

int cvError(int status, const char* func_name, const char* err_msg, const char* filename, int line)

エラーを発生させます.

パラメタ:
  • status – エラー状態
  • func_name – エラーが発生した箇所の関数名
  • err_msg – エラーに関する追加情報/診断結果
  • filename – エラーが発生した箇所のファイル名
  • line – エラーが発生した行番号

この関数は,( SetErrStatus を介して)指定された値をエラー状態としてセットします.さらに,エラーモードが Silent でなければ,エラーハンドラを呼び出します.

cv::ErrorStr

const char* cvErrorStr(int status)

エラー状態コードのテキスト情報を返します.

Parameter:status – エラー状態

この関数は,指定されたエラー状態コードに対するテキスト情報を返します.また,状態が不明な場合,この関数はNULLポインタを返します.

cv::RedirectError

CvErrorCallback cvRedirectError(CvErrorCallback error_handler, void* userdata=NULL, void** prevUserdata=NULL)

新たなエラーハンドラをセットします.

パラメタ:
  • error_handler – 新しいエラーハンドラ
  • userdata – エラーハンドラに引数としてそのまま渡される,任意のポインタ
  • prev_userdata – 事前に確保されているユーザデータへのポインタ
typedef int (CV_CDECL *CvErrorCallback)( int status, const char* func_name,
                    const char* err_msg, const char* file_name, int line );

この関数は,標準ハンドラや,特定のインタフェースを持つカスタムハンドラを,新たなエラーハンドラとしてセットします.エラーハンドラは,関数 Error と同じ引数を持ちます.ハンドラが 0 ではない値を返した場合は,プログラムが終了し,それ以外の場合は実行され続けます.エラーハンドラは,このような戻り値を決定するために, GetErrMode を利用して現在のエラーモードを確認する場合があります.

cv::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 – エラーに関する追加情報/診断結果
  • filename – エラーが発生した箇所のファイル名
  • line – エラーが発生した行番号
  • userdata – ユーザデータへのポインタ.標準ハンドラでは無視されます

関数 cvNullDevReport , cvStdErrReport , そして cvGuiBoxReport は,標準的なエラーハンドリングを提供します. cvGuiBoxReport は,Win32 システムではデフォルトのエラーハンドラで, cvStdErrReport は,その他のシステムでのデフォルトのエラーハンドラです. cvGuiBoxReport は,エラーの説明といくつかの選択肢を表示するメッセージボックスをポップアップします.以下は,前述のサンプル内で説明されているようにエラーを発生させた場合に,表示されるメッセージボックスの例です.

エラーメッセージボックス

_images/errmsg.png

エラーハンドラとして cvStdErrReport がセットされている場合,上述のメッセージが標準エラー出力に表示され,現在のエラーモードに応じて,プログラムが終了,あるいは,継続動作します.

標準エラー出力に表示されるエラーメッセージ( ``Leaf`` モード)

OpenCV ERROR: Bad argument (input_array or output_array are not valid matrices)
        in function cvResizeDCT, D:UserVPProjectsavl_probaa.cpp(75)
Terminating the application...

cv::Alloc

void* cvAlloc(size_t size)

メモリバッファを確保します.

Parameter:size – バイト単位で表されるバッファサイズ

この関数は, size バイトの領域を確保し,その確保されたバッファへのポインタを返します.エラーが起こった場合は,この関数はエラーを報告し,NULLポインタを返します.デフォルトでは, cvAllocicvAlloc を呼び出し,その中で malloc が呼ばれます.しかし,関数 SetMemoryManager を用いて,ここにユーザ定義のメモリ確保/解放関数を割り当てることも可能です.

cv::Free

void cvFree(void** ptr)

メモリバッファを解放します.

Parameter:ptr – 解放されるバッファへのダブルポインタ

この関数は,関数 Alloc によって確保されたメモリバッファを解放します.ダブルポインタを利用するのは,関数終了時にバッファへのポインタをクリアするためです. *buffer が既にNULLの場合は,この関数は何もしません.

cv::GetTickCount

int64 cvGetTickCount(void)
tick数を返します.

この関数は,プラットフォーム依存のイベントからのtick数(起動時からのCPU tick数,1970年からのミリ秒単位の時間,など)を返します.これは,関数やユーザコードの実行時間を正確に計測する場合に役立ちます.tick数を時間単位に変換するには, GetTickFrequency を利用します.

cv::GetTickFrequency

double cvGetTickFrequency(void)
1マイクロ秒毎のticks数を返します.

この関数は,1マイクロ秒あたりのtick数を返します.したがって, GetTickCountGetTickFrequency で割った値が,プラットフォーム依存のイベントからのマイクロ秒単位の経過時間になります.

cv::RegisterModule

..
int cvRegisterModule(const CvModuleInfo* moduleInfo)
他のモジュールを登録します.

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;

param moduleInfo:
 モジュールに関する情報

この関数は,登録モジュールリストに新しいモジュールを追加します.登録されたモジュールに関する情報は,関数 GetModuleInfo を使って取得できます.また,この登録されたモジュールも,CXCOREでサポートされる最適化プラグイン(IPP, MKL, ...)をフルに活用します.CXCORE自身や,CV(コンピュータビジョン),CVAUX(補助的コンピュータビジョン),HIGHGUI(可視化,画像/動画の取得)は,モジュールの一例です.登録は通常,共有ライブラリがロードされる際に行われます.登録方法の詳細については, cxcore/src/cxswitcher.cpp および cv/src/cvswitcher.cpp を参照してください.また,IPPやMKLがどのようにモジュールとリンクされるかについては, cxcore/src/cxswitcher.cpp および cxcore/src/_cxipp.h を参照してください.

cv::GetModuleInfo

void cvGetModuleInfo(const char* moduleName, const char** version, const char** loadedAddonPlugins)

登録されたモジュールおよびプラグインに関する情報を取得します.

パラメタ:
  • moduleName – 情報を取得するモジュールの名前.全てのモジュールを指定する場合はNULL
  • version – 出力パラメータ.バージョン情報を含む,モジュールに関する情報
  • loadedAddonPlugins – CXCOREが検出・ロード可能な,最適化プラグインの名前とバージョンのリスト

この関数は,登録されたモジュールの1つ,あるいは全てに関する情報を返します.取得した情報はライブラリ内部に保存されるので,ユーザは,返された文字列を解放したり変更したりするべきではありません.

cv::UseOptimized

int cvUseOptimized(int onoff)

最適化/非最適化モードを切り替えます.

Parameter:onoff – 最適化 ( \ne 0 ) ,非最適化 ( =0 )

この関数は,cxcore,OpenCV などの純粋なC言語のみで実装したものを利用するモードと,可能な部分はIPPやMKLの関数を用いて最適化するモードを切り替えます. cvUseOptimized(0) が呼ばれると,全ての最適化ライブラリがアンロードされます.この関数は,デバッグ時,IPPやMKLをプログラム実行時にアップグレードする場合,実行時に速度比較を行う場合,などに役立ちます.戻り値として,ロードされた最適化関数の数が返されます.デフォルトでは最適化プラグインがロードされるので,プログラムの先頭で cvUseOptimized(1) を呼ぶ必要はないことに注意してください(実際,開始時の処理時間が長くなってしまうだけです).

cv::SetMemoryManager

..
void cvSetMemoryManager(CvAllocFunc allocFunc=NULL, CvFreeFunc freeFunc=NULL, void* userdata=NULL)
カスタム/デフォルトメモリ管理関数にアクセスします.

typedef void* (CV_CDECL CvAllocFunc)(size_t size, void userdata); typedef int (CV_CDECL CvFreeFunc)(void pptr, void* userdata);

param allocFunc:
 メモリ確保関数.そのインタフェースは,コンテクストを決定するためなどに使用される userdata を除けば, malloc と同様です
param freeFunc:メモリ解放関数.そのインタフェースは, free と同様です
param userdata:カスタム関数に引数としてそのまま渡されるユーザデータ

この関数は, cvAlloc , cvFree や高レベル関数(例えば, cvCreateImage )によって呼び出されるユーザ定義のメモリ管理関数( mallocfree の代替)をセットします. cvAlloc によって確保されるデータが存在すれば,この関数が呼ばれるだろうことに注意してください.また,再帰呼び出しの無限ループを避けるために,カスタムメモリ確保/解放関数から cvAlloccvFree を呼び出していはいけません.

もし, alloc_funcfree_func のポインタがNULLの場合,デフォルトのメモリ管理関数が復元されます.

cv::SetIPLAllocators

\
\
void cvSetIPLAllocators(Cv_iplCreateImageHeader create_header, Cv_iplAllocateImageData allocate_data, Cv_iplDeallocate deallocate, Cv_iplCreateROI create_roi, Cv_iplCloneImage clone_image)
画像領域の確保/解放に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*);

#define CV_TURN_ON_IPL_COMPATIBILITY() cvSetIPLAllocators( iplCreateImageHeader, iplAllocateImage, iplDeallocate, iplCreateROI, iplCloneImage )

param create_header:
 iplCreateImageHeader へのポインタ
param allocate_data:
 iplAllocateImage へのポインタ
param deallocate:
 iplDeallocate へのポインタ
param create_roi:
 iplCreateROI へのポインタ
param clone_image:
 iplCloneImage へのポインタ

この関数は,CXCOREの画像領域の確保および解放処理に関して,IPLの関数を利用するようにします.利便性のために,ラッパーマクロ CV_TURN_ON_IPL_COMPATIBILITY が存在します.この関数は,IPLとCXCORE/OpenCVが一緒に利用されるアプリケーションや,まだ iplCreateImageHeader などの呼び出しを行っているアプリケーションでは便利です.IPLの関数がデータ処理のみに対して呼び出され,全てのメモリ確保/解放がCXCOREによって行われる場合,あるいは逆に,全てのメモリ確保/解放がIPLで行われ,OpenCVの関数がデータの処理に利用される場合は,この関数は不要です.