// Нарисовать кости и суставы
void Nui_DrawBone( const NUI_SKELETON_DATA & skel, NUI_SKELETON_POSITION_INDEX bone0, NUI_SKELETON_POSITION_INDEX bone1 )
{
NUI_SKELETON_POSITION_TRACKING_STATE bone0State = skel.eSkeletonPositionTrackingState[bone0];
NUI_SKELETON_POSITION_TRACKING_STATE bone1State = skel.eSkeletonPositionTrackingState[bone1];
// выход, если суставы не обнаружены
if ( bone0State == NUI_SKELETON_POSITION_NOT_TRACKED || bone1State == NUI_SKELETON_POSITION_NOT_TRACKED )
return;
// не отрисовывать если обе точки совпадают
if ( bone0State == NUI_SKELETON_POSITION_INFERRED && bone1State == NUI_SKELETON_POSITION_INFERRED )
return;
// нарисовать зеленым цветом кости суставы которых отслеживаются, а красным суставы кости которых не видно
if ( bone0State == NUI_SKELETON_POSITION_TRACKED && bone1State == NUI_SKELETON_POSITION_TRACKED ) // если кость видима
{
cvLine( ImageSkel, cvPointFrom32f( m_Points[bone0]), cvPointFrom32f( m_Points[bone1]), CV_RGB(0, 128, 0), 2 ); // нарисовать кость
cvLine( ImageVideo, cvPointFrom32f( m_Points[bone0]), cvPointFrom32f( m_Points[bone1]), CV_RGB(0, 128, 0), 1 ); // нарисовать кость на видео
}
else // если кость не видима
{
cvLine( ImageSkel, cvPointFrom32f( m_Points[bone0]), cvPointFrom32f( m_Points[bone1]), CV_RGB(128, 0, 0), 2 ); // нарисовать кость
cvLine( ImageVideo, cvPointFrom32f( m_Points[bone0]), cvPointFrom32f( m_Points[bone1]), CV_RGB(128, 0, 0), 1 ); // нарисовать кость на видео
}
}
// Точка в OpenCV
CvPoint2D32f SkeletonToScreen( Vector4 skeletonPoint, int width, int height )
{
LONG x, y;
USHORT depth;
// вычислить положение скелета на экране
// NuiTransformSkeletonToDepthImage возвращает координаты в разрешении NUI_IMAGE_RESOLUTION_320x240
NuiTransformSkeletonToDepthImage( skeletonPoint, &x, &y, &depth );
float screenPointX = static_cast<float>(x * width) / g_ScreenWidth * 2;
float screenPointY = static_cast<float>((y + 10) * height) / g_ScreenHeight * 2;
return cvPoint2D32f(screenPointX, screenPointY);
}
// Какие скелеты отслеживать и их отслеживание
void UpdateTrackedSkeletons( const NUI_SKELETON_FRAME & skel )
{
DWORD nearestIDs[2] = { 0, 0 };
USHORT nearestDepths[2] = { NUI_IMAGE_DEPTH_MAXIMUM, NUI_IMAGE_DEPTH_MAXIMUM };
// Очистить идентификаторы скелета, если пользователь покинул кадр
bool stickyID0Found = false;
bool stickyID1Found = false;
for ( int i = 0 ; i < NUI_SKELETON_COUNT; i++ )
{
NUI_SKELETON_TRACKING_STATE trackingState = skel.SkeletonData[i].eTrackingState;
if ( trackingState == NUI_SKELETON_TRACKED || trackingState == NUI_SKELETON_POSITION_ONLY )
{
if ( skel.SkeletonData[i].dwTrackingID == m_StickySkeletonIds[0] )
stickyID0Found = true;
else if ( skel.SkeletonData[i].dwTrackingID == m_StickySkeletonIds[1] )
stickyID1Found = true;
}
}
if ( !stickyID0Found && stickyID1Found )
{
m_StickySkeletonIds[0] = m_StickySkeletonIds[1];
m_StickySkeletonIds[1] = 0;
}
else if ( !stickyID0Found )
{
m_StickySkeletonIds[0] = 0;
}
else if ( !stickyID1Found )
{
m_StickySkeletonIds[1] = 0;
}
// рассчитать ближайший скелет
for ( int i = 0 ; i < NUI_SKELETON_COUNT; i++ )
{
NUI_SKELETON_TRACKING_STATE trackingState = skel.SkeletonData[i].eTrackingState;
if ( trackingState == NUI_SKELETON_TRACKED || trackingState == NUI_SKELETON_POSITION_ONLY )
{
// сохранить скелетон если нет ранее сохраненных
if ( 0 == m_StickySkeletonIds[0] && m_StickySkeletonIds[1] != skel.SkeletonData[i].dwTrackingID )
{
m_StickySkeletonIds[0] = skel.SkeletonData[i].dwTrackingID;
}
else if ( 0 == m_StickySkeletonIds[1] && m_StickySkeletonIds[0] != skel.SkeletonData[i].dwTrackingID )
{
m_StickySkeletonIds[1] = skel.SkeletonData[i].dwTrackingID;
}
LONG x, y;
USHORT depth;
// вычислить положение скелета на экране
NuiTransformSkeletonToDepthImage( skel.SkeletonData[i].Position, &x, &y, &depth );
if ( depth < nearestDepths[0] )
{
nearestDepths[1] = nearestDepths[0];
nearestIDs[1] = nearestIDs[0];
nearestDepths[0] = depth;
nearestIDs[0] = skel.SkeletonData[i].dwTrackingID;
}
else if ( depth < nearestDepths[1] )
{
nearestDepths[1] = depth;
nearestIDs[1] = skel.SkeletonData[i].dwTrackingID;
}
}
}
}
/// Нарисовать скелетон
void Nui_DrawSkeleton( const NUI_SKELETON_DATA & skel, int windowWidth, int windowHeight )
{
int i;
for (i = 0; i < NUI_SKELETON_POSITION_COUNT; i++)
{
m_Points[i] = SkeletonToScreen( skel.SkeletonPositions[i], windowWidth, windowHeight );
}
// отобразить торс
Nui_DrawBone( skel, NUI_SKELETON_POSITION_HEAD, NUI_SKELETON_POSITION_SHOULDER_CENTER );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_SHOULDER_CENTER, NUI_SKELETON_POSITION_SHOULDER_LEFT );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_SHOULDER_CENTER, NUI_SKELETON_POSITION_SHOULDER_RIGHT );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_SHOULDER_CENTER, NUI_SKELETON_POSITION_SPINE );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_SPINE, NUI_SKELETON_POSITION_HIP_CENTER );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_HIP_CENTER, NUI_SKELETON_POSITION_HIP_LEFT );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_HIP_CENTER, NUI_SKELETON_POSITION_HIP_RIGHT );
// левая рука
Nui_DrawBone( skel, NUI_SKELETON_POSITION_SHOULDER_LEFT, NUI_SKELETON_POSITION_ELBOW_LEFT );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_ELBOW_LEFT, NUI_SKELETON_POSITION_WRIST_LEFT );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_WRIST_LEFT, NUI_SKELETON_POSITION_HAND_LEFT );
// правая рука
Nui_DrawBone( skel, NUI_SKELETON_POSITION_SHOULDER_RIGHT, NUI_SKELETON_POSITION_ELBOW_RIGHT );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_ELBOW_RIGHT, NUI_SKELETON_POSITION_WRIST_RIGHT );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_WRIST_RIGHT, NUI_SKELETON_POSITION_HAND_RIGHT );
// левая нога
Nui_DrawBone( skel, NUI_SKELETON_POSITION_HIP_LEFT, NUI_SKELETON_POSITION_KNEE_LEFT );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_KNEE_LEFT, NUI_SKELETON_POSITION_ANKLE_LEFT );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_ANKLE_LEFT, NUI_SKELETON_POSITION_FOOT_LEFT );
// правая нога
Nui_DrawBone( skel, NUI_SKELETON_POSITION_HIP_RIGHT, NUI_SKELETON_POSITION_KNEE_RIGHT );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_KNEE_RIGHT, NUI_SKELETON_POSITION_ANKLE_RIGHT );
Nui_DrawBone( skel, NUI_SKELETON_POSITION_ANKLE_RIGHT, NUI_SKELETON_POSITION_FOOT_RIGHT );
head.x = m_Points[NUI_SKELETON_POSITION_HEAD].x; // получить координату X головы
head.y = m_Points[NUI_SKELETON_POSITION_HEAD].y; // получить координату Y головы
// нарисовать суставы разным цветом
for ( i = 0; i < NUI_SKELETON_POSITION_COUNT; i++ )
{
if ( skel.eSkeletonPositionTrackingState[i] == NUI_SKELETON_POSITION_INFERRED ) // если сустав видим
{
cvCircle( ImageSkel, cvPointFrom32f( m_Points[i]), 5, CV_RGB(128, 0, 0), 3 ); // отобразить сустав
cvCircle( ImageVideo, cvPointFrom32f( m_Points[i]), 5, CV_RGB(128, 0, 0), 1 ); // отобразить сустав на видео
}
else if ( skel.eSkeletonPositionTrackingState[i] == NUI_SKELETON_POSITION_TRACKED ) // если сустав не видим
{
cvCircle( ImageSkel, cvPointFrom32f( m_Points[i]), 5, CV_RGB(0, 128, 0), 3 ); // отобразить сустав
cvCircle( ImageVideo, cvPointFrom32f( m_Points[i]), 5, CV_RGB(0, 128, 0), 1 ); // отобразить сустав на видео
}
}
// Отображать надпись при поднятии рук вверх
CvFont font;
float aa=1;
cvInitFont( &font, CV_FONT_HERSHEY_SIMPLEX, aa,aa,0,2, 8 );
i = 0;
if ( m_Points[NUI_SKELETON_POSITION_HAND_RIGHT].y < m_Points[NUI_SKELETON_POSITION_HEAD].y )
{
cvPutText( ImageSkel, "Right Hand Up", cvPoint(0,30), &font, CV_RGB(255,255,255) );
i++;
}
if ( m_Points[NUI_SKELETON_POSITION_HAND_LEFT].y < m_Points[NUI_SKELETON_POSITION_HEAD].y )
{
cvPutText( ImageSkel, "Left Hand Up", cvPoint(0,30+i*30), &font, CV_RGB(255,255,255) );
i++;
}
}