• Open Source Computer Vision Library

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 弹出错误描述的消息框并提供几个选择。 下面是一个消息框的例子,如果和例子中的错误描述相同,它和上面的例子代码可能是兼容的。

错误消息对话框

图像:cxcore_errmsg.jpg

如果错误处理器是 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 函数来处理数据。

Views
Personal tools