Cxcore错误处理和系统函数
Wikipedia,自由的百科全书
目录 |
错误处理
在 OpenCV 中错误处理和 IPL (Image Processing Library)很相似。假如错误处理函数不返回错误代码,而是用CV_ERROR 宏调用 cvError 函数报错,按次序地,用 cvSetErrStatus 函数设置错误状态,然后调用标准的或者用户自定义的错误处理器(它可以显示一个消息对话框,写出错误日志等等, 参考函数 cvRedirectError, cvNulDevReport, cvStdErrReport, cvGuiBoxReport)。每个程序的线程都有一个全局变量,它包含了错误状态(一个整数值)。这个状态可以被 cvGetErrStatus 函数检索到。
有三个错误处理模式(参考 cvSetErrMode 和 cvGetErrMode):
- Leaf
- 错误处理器被调用以后程序被终止。这是缺省值。它在调试中是很有用的,当错误发生的时候立即产生错误信息。然而对于产生式系统后面两种方法可能会为他们提供更多的控制方式。
- Parent
- 错误处理器被调用以后程序不会被终止。栈被清空 (它用 C++ 异常处理机制完成写/输出--w/o)。当调用 CxCore 的函数 cvGetErrStatus 起作用以后用户可以检查错误代码。
- Silent
- 和 Parent 模式相似, 但是没有错误处理器被调用。
事实上, Leaf 和 Parent 模式的语义被错误处理器执行,上面的描述对 cvNulDevReport, cvStdErrReport. cvGuiBoxReport 的行为有一些细微的差别,一些自定义的错误处理器可能语义上会有很大的不同。 错误处理宏
报错,检查错误等的宏
/* special macros for enclosing processing statements within a function and separating
them from prologue (resource initialization) and epilogue (guaranteed resource release) */
#define __BEGIN__ {
#define __END__ goto exit; exit: ; }
/* proceeds to "resource release" stage */
#define EXIT goto exit
/* Declares locally 函数 name for CV_ERROR() use */
#define CV_FUNCNAME( Name ) \
static char cvFuncName[] = Name
/* Raises an error within the current context */
#define CV_ERROR( Code, Msg ) \
{ \
cvError( (Code), cvFuncName, Msg, __FILE__, __LINE__ ); \
EXIT; \
}
/* Checks status after calling CXCORE function */
#define CV_CHECK() \
{ \
if( cvGetErrStatus() < 0 ) \
CV_ERROR( CV_StsBackTrace, "Inner function failed." ); \
}
/* Provies shorthand for CXCORE function call and CV_CHECK() */
#define CV_CALL( Statement ) \
{ \
Statement; \
CV_CHECK(); \
}
/* Checks some condition in both debug and release configurations */
#define CV_ASSERT( Condition ) \
{ \
if( !(Condition) ) \
CV_ERROR( CV_StsInternal, "Assertion: " #Condition " failed" ); \
}
/* these macros are similar to their CV_... counterparts, but they
do not need exit label nor cvFuncName to be defined */
#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; // declare pointer that should be released anyway.
CV_FUNCNAME( "cvResizeDCT" ); // declare cvFuncName
__BEGIN__; // start processing. There may be some declarations just after this macro,
// but they couldn't be accessed from the epilogue.
if( !CV_IS_MAT(input_array) || !CV_IS_MAT(output_array) )
// use CV_ERROR() to raise an error
CV_ERROR( CV_StsBadArg, "input_array or output_array are not valid matrices" );
// some restrictions that are going to be removed later, may be checked with CV_ASSERT()
CV_ASSERT( input_array->rows == 1 && output_array->rows == 1 );
// use CV_CALL for safe function 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__; // finish processing. Epilogue follows after the macro.
// release temp_array. If temp_array has not been allocated before an error occured, cvReleaseMat
// takes care of it and does nothing in this case.
cvReleaseMat( &temp_array );
}
int main( int argc, char** argv )
{
CvMat* src = cvCreateMat( 1, 512, CV_32F );
#if 1 /* no errors */
CvMat* dst = cvCreateMat( 1, 256, CV_32F );
#else
CvMat* dst = 0; /* test error processing mechanism */
#endif
cvSet( src, cvRealScalar(1.), 0 );
#if 0 /* change 0 to 1 to suppress error handler invocation */
cvSetErrMode( CV_ErrModeSilent );
#endif
cvResizeDCT( src, dst ); // if some error occurs, the message box will popup, or a message will be
// written to log, or some user-defined processing will be done
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, void* userdata );
CvErrorCallback cvRedirectError( CvErrorCallback error_handler,
void* userdata=NULL, void** prev_userdata=NULL );
- error_handler
- 新的错误处理器
- userdata
- 传给错误处理器的任意透明指针
- prev_userdata
- 指向前面分配给用户数据的指针的指针
函数 cvRedirectError 在标准错误处理器或者有确定借口的自定义错误处理器中选择一个新的错误处理器 。错误处理器和 cvError 函数有相同的参数。 如果错误处理器返回非零的值, 程序终止, 否则, 程序继续运行。错误处理器通过 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 提供标准错误操作。cvGuiBoxReport 是 Win32 系统缺省的错误处理器, cvStdErrReport - 其他系统. cvGuiBoxReport 弹出错误描述的消息框并提供几个选择。 下面是一个消息框的例子,如果和例子中的错误描述相同,它和上面的例子代码可能是兼容的。
- 错误消息对话框
- 如果错误处理器是 cvStdErrReport, 上面的消息将被打印到标准错误输出,程序将要终止和继续依赖于当前错误模式。
- 错误消息打印到标准错误输出 (在 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...
系统函数
Alloc
分配内存缓冲区
void* cvAlloc( size_t size );
- size
- 以字节为单位的缓冲区大小
函数 cvAlloc 分配字节缓冲区大小并返回分配的缓冲区的指针。如果错误处理函数产生了一个错误报告 则返回一个空(NULL)指针。 缺省地 cvAlloc 调用 icvAlloc 而 icvAlloc 调用 malloc ,然而用 cvSetMemoryManager 调用用户自定义的内存分配和释放函数也是可能的。
Free
释放内存缓冲区
void cvFree( void** ptr );
- buffer
- 指向被释放的缓冲区的双重指针
函数 cvFree 释放被 cvAlloc 分配的缓冲区。在退出的时候它清除缓冲区指针,这就是为什么要使用双重指针的原因 。 如果 *buffer 已经是空(NULL), 函数什么也不做。
GetTickCount
Returns number of tics
int64 cvGetTickCount( void );
函数 cvGetTickCount 返回从依赖于平台的事件(从启动开始 CPU 的ticks 数目, 从1970年开始的微秒数目等等)开始的 tics 的数目 。 该函数对于精确测量函数/用户代码的执行时间是很有用的。要转化 tics 的数目为时间单位,使用函数 cvGetTickFrequency 。
GetTickFrequency
返回每个微秒的 tics 的数目
double cvGetTickFrequency( void );
函数 cvGetTickFrequency 返回每个微秒的 tics 的数目。 因此, cvGetTickCount() 和 cvGetTickFrequency() 将给出从依赖于平台的事件开始的 tics 的数目 。
RegisterModule
Registers another module注册另外的模块
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) 自身就是模块的例子。 通常注册后共享库就被载入。参考 cxcore/src/cxswitcher.cpp and cv/src/cvswitcher.cpp 获取细节信息, 怎样注册的参考 cxcore/src/cxswitcher.cpp , cxcore/src/_cxipp.h 显示了 IPP 和 MKL 是怎样连接到模块的。
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 在两个模式之间切换,这里只有纯 C 才从 cxcore, OpenCV 等执行。如果可用 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 函数来处理数据。


