¿Por qué Kinect necesita realizar una conversión de coordenadas al diseñar un mouse aéreo?
El vídeo está en /v_show/id_XMjk2OTU3MjYw.html. El corte a mano alzada requiere más práctica.
En el tutorial anterior, usamos RaiseHand para capturar la posición después de levantar la mano, por lo que decidimos cuidadosamente usar RaiseHand para activar el evento de movimiento del mouse y Click para activar el clic del mouse. Sin embargo, los resultados de la prueba. no fueron satisfactorios. El mouse mueve una tarjeta tras otra. La razón es que el reconocimiento de RaiseHand tarda en alcanzar los estándares en tiempo real. ¿Qué hacer? Revisé la documentación de OpenNI y encontré la API de seguimiento, de modo que después de identificar la mano, podemos usar el seguimiento para obtener la posición de la mano en tiempo real, ¡y el problema de mover el mouse está resuelto! Es como seguir a una persona entre una gran multitud, ¡es más fácil que encontrarla!
Dado que la cantidad de código en este tutorial es un poco grande, el editor tiene mucho cuidado de no tirarlo todo de una vez. Primero presentaré la función principal y luego explicaré la función de devolución de llamada. 1. Cuando se ejecuta el programa, la visualización del formulario es la misma que la rutina de reconocimiento de gestos final. Dado que mouse_event se usa para controlar el mouse, Xiaojin eligió el marco MFC, que es principalmente un cuadro de diálogo y un botón. Dado que la ejecución de nuestro programa utiliza OpenCV highgui para mostrar imágenes, haga clic en el botón en el formulario para crear e iniciar un hilo. La función del hilo es KinectGestureMain(), que es la función principal aquí.
En 2KinectGestureMain(), la mayor parte del contenido es el mismo que en la rutina anterior. En 2, Xiaojin creó un HandsGenerator. Este generador nos ayuda principalmente con el trabajo de seguimiento. Se crea de la misma manera que otros generadores, simplemente pasa un contexto al método Create()
3 Similar al generador de gestos, necesitamos registrar una función de devolución de llamada para HandsGenerator,
[cpp]?ver plano?copia
,?HandUpdate?HandUpdate?UpdateCB,?HandDestroy?DestroyCB,?void?*?pCookie,?XnCallbackHandle?&?hCallback?)
La definición es: HandCreate se llama cuando se crea un novato (pista); HandDestroy, por el contrario, se llama cuando la mano desaparece; UpdateCB se llama cuando la mano cambia de posición. Además, pCookie es un puntero que se pasa a la función de devolución de llamada y se puede usar para colocar algunos datos del usuario; pCookie es un puntero a la imagen de la mesa de trabajo del programa y se puede usar para dibujar directamente en la función de devolución de llamada; phCallback es el identificador de la devolución de llamada; función y se puede utilizar para cerrar sesión en la función de devolución de llamada.
4 Después de configurar aquí, presione la tecla m para ingresar al modo de control del mouse.
El resto del código es básicamente el mismo que la rutina anterior, echemos un vistazo a la función de devolución de llamada.
[cpp]?ver?simple?copia
//?función?de devolución de llamada?para?gesto?reconocido?
void?XN_CALLBACK_TYPEGReconocido(?xn:.
¿nulo? const?XnPoint3D?*pIDPosition,? const?XnPoint3D?*pEndPosition,? ¿nulo?*pCookie?)
{?
int?imgStartY=0;?
int?imgEndX=0;?
int?imgEndY=0;
/ 5?
imgStartX=(int)(640/2-(pIDPosition->X));?
imgStartY=(int)(480/2-(pIDPosition->Y) ));?
imgEndX=(int)(640/2-(pEndPosition->X));?
imgEndY=(int)(480/2-(pEndPosition- >Y));?
IplImage*?refimage=(IplImage*)pCookie;?
if(strcmp(strGesture, "Wave")==0)?
{?
cvLine(refimage,cvPoint(imgStartX,imgStartY),cvPoint(imgEndX,imgEndY),CV_RGB(255,255,0),6);?
/ /6?
handsGenerator.StartTracking(*pEndPosition);?
}?
else?if(strcmp(strGesture, "Click")==0 )?
{?
cvCircle(refimage,cvPoint(imgStartX,imgStartY),6,CV_RGB(0,0,255),12);?
/ /7?
if(isRealMouseControl)?
{?
messageHandler(cvPoint(imgStartX,imgStartY),0,REAL_MOUSE_CLICK);?
}?
}?
}
//?
constante?
constante ?XnPoint3D?*pPosition,?
XnFloat?fProgress,?
void?*pCookie?
{?
5 Dado que las coordenadas de pIDPosition y pEndPosition están en el sistema de coordenadas con el centro de la pantalla como el punto (0,0), y lo que se muestra en OpenCV es el sistema de coordenadas con la esquina superior izquierda de la pantalla como el punto (0,0), por lo que aquí se requiere la conversión.
6 En este código, nuestro GestureGenerator reconoce el gesto de "ola" y luego llama al método StartTracking() de HandsGenerator para comenzar a rastrear la mano en pEndPosition, que es la posición final del gesto de "ola". .
7. Si reconoce el gesto de "empujar hacia adelante" y activa el modo de control del mouse, llamará al método messageHandler() definido por Xiaojian para simular un clic del mouse. messageHandler() se implementará más adelante en AppMessage.cpp.
A continuación, Xiaolin implementó la función de devolución de llamada relacionada con Hands: [cpp]?view?plain?copy
/8?
void?XN_CALLBACK_TYPEHand_Create(xn::HandsGenerator&? generador, XnUserID? nId,const?XnPoint3D*pPosition,?XnFloatfTime,?void*pCookie)?
{?
addTrackingId(nId);?
}? p>
void?XN_CALLBACK_TYPEHand_Update (xn::HandsGenerator&?generator,XnUserID?nId,const?
int?imgPosX=0;?
int?imgPosY=0;?
char?locationinfo[100];?
imgPosX=(int )(640/2-(pPosition->X));?
imgPosY=(int)( 480/2-(pPosition->Y));?
IplImage* ?refimage=(IplImage*)pCookie;?
cvSetImageROI(refimage,cvRect(40,450,640,30)) ;?
cvFont?
cvInitFont(? &font ,CV_FONT_VECTOR0,1,?1,?0,?3,?5);?
cvSet( refimage,cvScalar(255,255,255));?
if(isRealMouseControl)?
{?
sprintf(ubicacióninfo, "MouseCtrl:?%dth?HandLoc: ?%d,%d",nId,(int)pPosition->X,(int)pPosition ->Y);?
}?
¿otro?
{?
sprintf(ubicacióninfo, "Normal:?%dth ?HandLoc:?%d,%d",nId,(int)pPosition->X,(int)pPosition->Y );?
}?
cvPutText(refimage,locationinfo?,cvPoint(30,30),? &font,?CV_RGB(0,0,0));? p>
cvResetImageROI(refimage);?
CvPoint?thisLocation= cvPoint(imgPosX,imgPosY);?
//9?
if( isRealMouseControl)?
{?
//cvCircle (refimage,cvPoint(imgPosX,imgPosY),1,CV_RGB(255,0,0),2);?
messageHandler(thisLocation,nId,REAL_MOUSE_MOVE);?
} ?
else?
{
cvCircle( refima
ge,cvPoint(imgPosX,imgPosY),1,CV_RGB(255,0,0),2);?
}?
}
?