Práctica

Práctica

Para finalizar la unidad didáctica, se plantea la realización de una práctica opcional libre para entender mejor los conceptos presentados:

 

  • En primer lugar, se realizará el siguiente ejercicio guiado: se presentan a continuación diferentes extractos de código que implementan diferentes funcionalidades en OpenNI. La realización de la práctica consiste en leer estos trozos de código e intentar inferir, en la medida de lo posible, su significado y funcionalidad a tenor de lo visto en la unidad didáctica. Se acompaña a cada extracto de código de una versión comentada en la que se ilustran precisamente los aspectos más relevantes que se espera que el alumno sea capaz de identificar (para que la práctica tenga sentido docente, se recomienda no corroborar las soluciones hasta haber intentado, en la medida de lo posible, entender el código presentado). Cada trozo de código y su solución se presentan a continuación como pestañas separadas.


  • En segundo lugar, el alumno deberá consultar los diferentes programas que se distribuyen con OpenNI (localizados en el directorio OpenNI/Samples/), compilarlos y ejecutarlos, con objeto de ver las posibilidades de la biblioteca en las diferentes aplicaciones. Una vez observadas las diferentes aplicaciones, el alumno deberá intentar identificar a grandes rasgos los componentes utilizados en el código fuente de los mismos (no es necesario intentar entender los programas en su totalidad, ni consultar el código fuente de todos ellos, ya que se profundizará en ellos en las unidades posteriores; se trata únicamente de una experiencia exploratoria para tomar contacto con la sintaxis que se va a utilizar a nivel de código en el resto de unidades). Por ejemplo, intentar localizar en el código secciones correspondientes a la definición de las callbacks que se van a utilizar, su registro por la AP, y funciones básicas para la extracción de datos de interés de diversos generadores (mapa de profundidad, coordenadas de la mano, etc.).

En caso de que se presenten dificultades para proceder a la lectura de los códigos presentados a continuación, se presenta también esta información en dos archivos: Ejercicios y Solución

Inicialización, creación de nodos y lectura de datos.

XnStatus nRetVal = XN_STATUS_OK;
xn::Context context;
nRetVal = context.Init();
xn::DepthGenerator depth;
nRetVal = depth.Create(context);
nRetVal = context.StartGeneratingAll();
bool bShouldRun = true;
while (bShouldRun)
{
nRetVal = context.WaitOneUpdateAll(depth);
if (nRetVal != XN_STATUS_OK)
{
printf("Failed updating data: %s
", xnGetStatusString(nRetVal));
continue;
}
const XnDepthPixel* pDepthMap = depth.GetDepthMap();
}
context.Shutdown();

Cadenas de producción

xn::Query query;
nRetVal = query.SetVendor("MyVendor");
query.AddSupportedCapability(XN_CAPABILITY_SKELETON);
xn::NodeInfoList possibleChains;
nRetVal = context.EnumerateProductionTrees(XN_NODE_TYPE_USER, &query, possibleChains, NULL);
xn::NodeInfo selected = *possibleChains.Begin();
nRetVal = context.CreateProductionTree(selected);
xn::UserGenerator userGen;
nRetVal = selected.GetInstance(userGen);

Gestión de mapas/imágenes.

XnStatus nRetVal = XN_STATUS_OK;
Context context;
nRetVal = context.Init();
DepthGenerator depth;
nRetVal = depth.Create(context);
XnMapOutputMode mapMode;
mapMode.nXRes = XN_VGA_X_RES;
mapMode.nYRes = XN_VGA_Y_RES;
mapMode.nFPS = 30;
nRetVal = depth.SetMapOutputMode(mapMode);
nRetVal = context.StartGeneratingAll();
XnUInt32 nMiddleIndex = 
XN_VGA_X_RES * XN_VGA_Y_RES/2 + XN_VGA_X_RES/2;
bShouldRun = true;                 
while (bShouldRun)
{
nRetVal = context.WaitOneUpdateAll(depth);
const XnDepthPixel* pDepthMap = depth.GetDepthMap();
printf("Middle pixel is %u millimeters away
", 
pDepthMap[nMiddleIndex]);
}
context.Shutdown();

Acceso a los datos de las coordenadas de la mano (Hand Point)


#define GESTURE_TO_USE "Click"
xn::GestureGenerator g_GestureGenerator;
xn::HandsGenerator g_HandsGenerator;
void XN_CALLBACK_TYPE 
Gesture_Recognized(xn::GestureGenerator& generator,
const XnChar* strGesture,
const XnPoint3D* pIDPosition,
const XnPoint3D* pEndPosition, void* pCookie)
{
printf("Gesture recognized: %s
", strGesture);
g_GestureGenerator.RemoveGesture(strGesture);
g_HandsGenerator.StartTracking(*pEndPosition);
}
void XN_CALLBACK_TYPE
Gesture_Process(xn::GestureGenerator& generator,
const XnChar* strGesture,
const XnPoint3D* pPosition,
XnFloat fProgress,
void* pCookie)
{}
void XN_CALLBACK_TYPE
Hand_Create(xn::HandsGenerator& generator,
XnUserID nId, const XnPoint3D* pPosition,
XnFloat fTime, void* pCookie)
{
printf("New Hand: %d @ (%f,%f,%f)
", nId,
pPosition->X, pPosition->Y, pPosition->Z);
}
void XN_CALLBACK_TYPE
Hand_Update(xn::HandsGenerator& generator,
XnUserID nId, const XnPoint3D* pPosition,
XnFloat fTime, void* pCookie)
{
}
void XN_CALLBACK_TYPE
Hand_Destroy(xn::HandsGenerator& generator,
XnUserID nId, XnFloat fTime,
void* pCookie)
{
printf("Lost Hand: %d
", nId);
g_GestureGenerator.AddGesture(GESTURE_TO_USE, NULL);
}
void main()
{
XnStatus nRetVal = XN_STATUS_OK;
Context context;
nRetVal = context.Init();
nRetVal = g_GestureGenerator.Create(context);
nRetVal = g_HandsGenerator.Create(context);
XnCallbackHandle h1, h2;
g_GestureGenerator.RegisterGestureCallbacks(Gesture_Recognized,
Gesture_Process,
NULL, h1);
g_HandsGenerator.RegisterHandCallbacks(Hand_Create, Hand_Update,
Hand_Destroy, NULL, h2);
nRetVal = context.StartGeneratingAll();
nRetVal = g_GestureGenerator.AddGesture(GESTURE_TO_USE);
while (TRUE)
{
nRetVal = context.WaitAndUpdateAll();  
}
context.Shutdown();
}

Acceso a los datos del generador de audio


Context context;
nRetVal = context.Init();
AudioGenerator audio;
nRetVal = audio.Create(context);
XnWaveOutputMode waveMode;
waveMode.nSampleRate = 44100;
waveMode.nChannels = 2;
waveMode.nBitsPerSample = 16;
nRetVal = audio.SetWaveOutputMode(waveMode);
while (true)
{
nRetVal = context.WaitOneUpdateAll(audio);
const XnUChar* pAudioBuf = audio.GetAudioBuffer();
XnUInt32 nBufSize = audio.GetDataSize();
}
context.Shutdown();

Obra publicada con Licencia Creative Commons Reconocimiento 3.0