读OpenCV源代码的一些经验

由于OpenCV上大量使用了宏,对于一些经验不足的算法研究者来说,要找到一些函数体都是困难的,因为他们用##连接,直接查函数名甚至不能找到函数的实现代码,所以一般建议在这种情况下取函数关键字段作为搜索条件.这里有个列子,是对OpenCV中的一些初始化过程的部分解析.

我查看了代码,函数icvCalcOpticalFlowPyrLK_8uC1R应该没有调用你上面提到的三个函数指针,因为用#if 0注释掉了,那三个函数应该是IPP库优化的函数指针接口,只有需要用IPP库的时候才可用,void* ipp_optflow_state = 0;也限制了icvOpticalFlowPyrLKFree_8u_C1R_p( ipp_optflow_state );调用.
下面是从opencv各个宏抽取出来的,这样是可以在cpp里面编译通过,可以看到事实上它是会调用ipp库中的ippiOpticalFlowPyrLKInitAlloc_8u_C1R,至于其初始化在哪儿,我没往下查.
typedef int CvStatus ;
typedef struct
{
int width;
int height;
}
CvSize;
#if defined WIN32 || defined WIN64
#define CV_CDECL __cdecl
#define CV_STDCALL __stdcall
#else
#define CV_CDECL
#define CV_STDCALL
#endif

#define CV_PLUGIN_IPPCV 2 /* IPP: computer vision */
#define CV_PLUGINS1(lib1) ((lib1)&15)
#ifndef IPCVAPI
#define IPCVAPI(type,declspec,name,args) /
/* function pointer */ /
typedef type (declspec* name##_t) args; /
extern name##_t name##_p; /
type declspec name args;
#endif

#define IPCVAPI_EX(type,name,ipp_name,ipp_search_modules,args) /
IPCVAPI(type,CV_STDCALL,name,args)

#define IPCVAPI_C_EX(type,name,ipp_name,ipp_search_modules,args)/
IPCVAPI(type,CV_CDECL,name,args)



IPCVAPI_EX( CvStatus, icvOpticalFlowPyrLKInitAlloc_8u_C1R,
"ippiOpticalFlowPyrLKInitAlloc_8u_C1R", CV_PLUGINS1(CV_PLUGIN_IPPCV),
( void** ppState, CvSize roiSize, int winSize, int hint ))

icvOpticalFlowPyrLKInitAlloc_8u_C1R_t icvOpticalFlowPyrLKInitAlloc_8u_C1R_p = 0;
继续关于初始化的问题,在cvswitcher.cpp中有
static CvPluginFuncInfo cv_ipp_tab[] =
{
#undef _CV_IPP_H_
#include "_cvipp.h"
#undef _CV_IPP_H_
{0, 0, 0, 0, 0}
};
如果做个简单的提取,就会得到如下情况:
typedef struct CvPluginFuncInfo
{
void** func_addr;
void* default_func_addr;
const char* func_names;
int search_modules;
int loaded_from;
}
CvPluginFuncInfo;


#undef IPCVAPI_EX
#define IPCVAPI_EX(type,func_name,names,modules,arg) /
{ (void**)&func_name##_p, (void*)(size_t)-1, names, modules, 0 },


static CvPluginFuncInfo cv_ipp_tab[] =
{
IPCVAPI_EX( CvStatus, icvOpticalFlowPyrLKInitAlloc_8u_C1R,
"ippiOpticalFlowPyrLKInitAlloc_8u_C1R", CV_PLUGINS1(CV_PLUGIN_IPPCV),
( void** ppState, CvSize roiSize, int winSize, int hint ))
{0, 0, 0, 0, 0}
};
这里将icvOpticalFlowPyrLKInitAlloc_8u_C1R的函数指针icvOpticalFlowPyrLKInitAlloc_8u_C1R_p的指针给了cv_ipp_tab,cv_ipp_tab这个时候已经有两个元素了.
个人认为icvOpticalFlowPyrLKInitAlloc_8u_C1R的初始化表在获得ipp库后会提供一个初始化该表的操作,可能是通过const char* func_names和LoadLib获得该函数的地址.这样在调用icvOpticalFlowPyrLKInitAlloc_8u_C1R_p,实际调用了ipp里的ippiOpticalFlowPyrLKInitAlloc_8u_C1R
继续上面的代码查询,cv_ipp_tab最终被放到cv_info中,这里提取了一些代码,可以看出cv_ipp_tab是在CvModule::CvModule( CvModuleInfo* _info )的构造函数中调用cvRegisterModule,而cvRegisterModule函数又会调用cvUseOptimized通过LoadLib和GetProcAddress将函数地址赋给函数指针的指针.对opencv的优化就体现在是否提供了相应的intel的优化库,通过cvRegisterModule来更新函数地址表不同的优化选项插件被定义在cvmisc.h文件里最多可支持16个外部优化插件.有兴趣的可以继续找下去.
#if (defined WIN32 || defined WIN64) && defined CVAPI_EXPORTS
#define CV_EXPORTS __declspec(dllexport)
#else
#define CV_EXPORTS
#endif

typedef struct CvModuleInfo
{
struct CvModuleInfo* next;
const char* name;
const char* version;
CvPluginFuncInfo* func_tab;
}
CvModuleInfo;
struct CV_EXPORTS CvModule
{
CvModule( CvModuleInfo* _info );
~CvModule();
CvModuleInfo* info;

static CvModuleInfo* first;
static CvModuleInfo* last;
};

static CvModuleInfo cv_info = { 0, "cv", "1.0.0", 0 };
CvModule cv_module( &cv_info );
int cvRegisterModule( const CvModuleInfo* module )
{
return 0;
}
CvModuleInfo *CvModule::first = 0, *CvModule::last = 0;
CvModule::CvModule( CvModuleInfo* _info )
{
cvRegisterModule( _info );
info = last;
}

CvModule::~CvModule()
{
if( info )
{
CvModuleInfo* p = first;
for( ; p != 0 && p->next != info; p = p->next )
;
if( p )
p->next = info->next;
if( first == info )
first = info->next;
if( last == info )
last = p;
//cvFree( &info );
info = 0;
}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值