OpenNI context初始化
Context对象初始化方式
Context::Init
封装了xnInit,里面进行这几个操作
<1>XnOSInit():
xnOSStartHighResTimer(&g_xnOSHighResGlobalTimer);
typedef struct XnOSTimer
{
XnDouble dTicksPerTimeUnit;
LARGE_INTEGER nStartTick;
} XnOSTimer;
XnOSTimer g_xnOSHighResGlobalTimer;
xnOSStartHighResTimer里的主要内容:
bRetVal = QueryPerformanceFrequency(&nTicksPerSecond);
pTimer->dTicksPerTimeUnit = (XnDouble)nTicksPerSecond.QuadPart / 1000.0;
bRetVal = QueryPerformanceCounter(&pTimer->nStartTick);
从这里可以看到,这个函数主要是获得系统CPU运行每帧所需的时间以及系统的高分辨率性能计数器的当前值,也就是CPU已经运行的次数,将它们存放到全局变量g_xnOSHighResGlobalTimer中
<2> xnLogInitSystem()
在这里面主要是获得当前执行文件所在的目录以及当前的时间,将这些信息存放到全局变量static XnLoggerData g_xnLoggerData;中
<3>给成员分配内存空间
pContext->pLicenses = XN_NEW(XnLicenseList);
pContext->pModuleLoader = XN_NEW(XnModuleLoader, pContext);
pContext->pNodesMap = XN_NEW(XnNodesMap);
pContext->pGlobalErrorChangeEvent= XN_NEW(XnErrorStateChangedEvent);
这里面进行的只是分配内存空间,构造函数里面没有进行什么操作
<4>xnFPSInit(&pContext->readFPS, XN_NODE_FPS_CALC_SAMPLES)
XnFPSData readFPS; typedef struct XnFPSDataImpl* XnFPSData; struct XnFPSDataImpl { /** An array of the time of each frame. */ XnUInt64* anTimes; /** The size of the array. */ XnUInt32 nArraySize; /** Index of the next place to write to. */ XnUInt32 nCurrIndex; }; XnStatus xnFPSInit(XnFPSData* pFPS, XnUInt32 nSamplesCount) { …………….. XnFPSDataImpl* pData = *pFPS; // Allocate array XN_VALIDATE_ALIGNED_CALLOC(pData->anTimes, XnUInt64, nSamplesCount, XN_DEFAULT_MEM_ALIGN); pData->nArraySize = nSamplesCount; return XN_STATUS_OK; } XN_C_API XnStatus xnOSCreateEvent(XN_EVENT_HANDLE* pEventHandle, XnBool bManualReset) { return (xnOSCreateNamedEvent(pEventHandle, NULL, bManualReset)); } XN_C_API XnStatus xnOSCreateNamedEvent(XN_EVENT_HANDLE* pEventHandle, const XnChar* cpEventName, XnBool bManualReset) { ………. // Create a named event via the OS *pEventHandle = CreateEvent(NULL, bManualReset, FALSE, cpEventName); …………….. return (XN_STATUS_OK); }
5>在这个函数里,调用系统函数来创建一个命名的事件对象
HANDLE WINAPI CreateEvent(
__in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
__in BOOL bManualReset,
__in BOOL bInitialState,
__in_opt LPCTSTR lpName
);
lpEventAttributes:安全属性对象,默认为NULL,这样子线程不可以继承
bManualReset:是否自动重置,如果是,则需要手动调用ResetEvent来将事件对象重置成无信号状态,否则在等待这个事件的线程退出后会自动将其状态设成无信号的
bInitialState:初始状态,为真则为有信号
lpName:名称,大小写敏感
<6>装载模块
pContext->pModuleLoader->Init();
XnStatus XnModuleLoader::Init() { ……….. nRetVal = LoadAllModules(); ………… } XnStatus XnModuleLoader::LoadAllModules() { TiXmlDocument doc; nRetVal = loadModulesFile(doc);//这里加载modules.xml,使用系统的环境变量//OPEN_NI_INSTALL_PATH来获得modules.xml的路径 TiXmlElement* pModule = doc.RootElement()->FirstChildElement(XN_MODULE_ELEMENT_NAME); while (pModule != NULL) { const XnChar* strModulePath = NULL; nRetVal = xnXmlReadStringAttribute(pModule, "path", &strModulePath); XN_IS_STATUS_OK(nRetVal); const XnChar* strConfigDir = pModule->Attribute("configDir"); nRetVal = LoadModule(strModulePath, strConfigDir); XN_IS_STATUS_OK(nRetVal); pModule = pModule->NextSiblingElement(XN_MODULE_ELEMENT_NAME); } ……… return (XN_STATUS_OK); }
这里面只加载了Recorder,Mock Node 和Codec和XnDeviceSensorV2等多个模块
Recorder这个模块里面的节点类型有:XN_NODE_TYPE_RECORDER,XN_NODE_TYPE_PLAYER
Mock Nodes里面有:XN_NODE_TYPE_DEVICE,XN_NODE_TYPE_DEPTH,XN_NODE_TYPE_IMAGE,XN_NODE_TYPE_IR,XN_NODE_TYPE_AUDIO
Codec里面有:XN_NODE_TYPE_CODEC,对应的strName分别有16zP,16Zt,Im8z,NONE,JPEG
XnDeviceSensorV2里面有各种产品节点的类型
XnVFeatures提供了场景分析和骨骼提取的功能
XnVHandGenerator提供了手势识别的功能