/// <summary> /// 距離データをカラー画像に変換する /// </summary> /// <param name="kinect"></param> /// <param name="depthFrame"></param> /// <returns></returns> private void HeightMeasure( KinectSensor kinect, DepthImageFrame depthFrame, SkeletonFrame skeletonFrame ) { ColorImageStream colorStream = kinect.ColorStream; DepthImageStream depthStream = kinect.DepthStream; // トラッキングされている最初のスケルトンを取得する // インデックスはプレイヤーIDに対応しているのでとっておく Skeleton[] skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength]; skeletonFrame.CopySkeletonDataTo( skeletons ); int playerIndex = 0; for ( playerIndex = 0; playerIndex < skeletons.Length; playerIndex++ ) { if ( skeletons[playerIndex].TrackingState == SkeletonTrackingState.Tracked ) { break; } } if ( playerIndex == skeletons.Length ) { return; } // トラッキングされている最初のスケルトン Skeleton skeleton = skeletons[playerIndex]; // 実際のプレイヤーIDは、スケルトンのインデックス+1 playerIndex++; // 頭、足先がトラッキングされていない場合は、そのままRGBカメラのデータを返す Joint head = skeleton.Joints[JointType.Head]; Joint leftFoot = skeleton.Joints[JointType.FootLeft]; Joint rightFoot = skeleton.Joints[JointType.FootRight]; if ( (head.TrackingState != JointTrackingState.Tracked) || (leftFoot.TrackingState != JointTrackingState.Tracked) || (rightFoot.TrackingState != JointTrackingState.Tracked) ) { return; } // 距離カメラのピクセルごとのデータを取得する short[] depthPixel = new short[depthFrame.PixelDataLength]; depthFrame.CopyPixelDataTo( depthPixel ); // 距離カメラの座標に対応するRGBカメラの座標を取得する(座標合わせ) ColorImagePoint[] colorPoint = new ColorImagePoint[depthFrame.PixelDataLength]; kinect.MapDepthFrameToColorFrame( depthStream.Format, depthPixel, colorStream.Format, colorPoint ); // 頭のてっぺんを探す DepthImagePoint headDepth = depthFrame.MapFromSkeletonPoint( head.Position ); int top = 0; for ( int i = 0; (headDepth.Y - i) > 0; i++ ) { // 一つ上のY座標を取得し、プレイヤーがいなければ、現在の座標が最上位 int index = ((headDepth.Y - i) * depthFrame.Width) + headDepth.X; int player = depthPixel[index] & DepthImageFrame.PlayerIndexBitmask; if ( player == playerIndex ) { top = i; } } // 頭のてっぺんを3次元座標に戻し、足の座標(下にあるほう)を取得する // この差分で身長を測る head.Position = depthFrame.MapToSkeletonPoint( headDepth.X, headDepth.Y - top ); Joint foot = (leftFoot.Position.Y < rightFoot.Position.Y) ? leftFoot : rightFoot; // 背丈を表示する DrawMeasure( kinect, colorStream, head, foot ); }
/// <summary> /// Check queue if right hand and elbow positions are stable /// under the condition that Status is DepthDetecting. /// If is stable, the Status will be changed to next after doing depth calibration. /// If not, nothing will be changed. /// </summary> public void DoDepthDetecting(KinectSensor sensor, DepthImageFrame depthFrame) { if (Status == MainStatus.DepthDetecting) { if (IsStable(rightHandQueue, DEPTH_HAND_TOLERANCE, DEPTH_HAND_COUNT)) { // if is stable, calibrate depth according to avg of position near hand SkeletonPoint handPoint = rightHandQueue.Last().Position; DepthImagePoint centerDepthPoint = sensor.MapSkeletonPointToDepth( handPoint, sensor.DepthStream.Format); int[] depthArr = new int[DEPTH_NEAR_COUNT * 4]; int index = 0; for (int i = 0; i < DEPTH_NEAR_COUNT; ++i) { // top SkeletonPoint topSke = depthFrame.MapToSkeletonPoint( centerDepthPoint.X - DEPTH_NEAR_RADIUS + (int)(DEPTH_SPAN * i), centerDepthPoint.Y - DEPTH_NEAR_RADIUS); depthArr[index++] = depthFrame.MapFromSkeletonPoint(topSke).Depth; // bottom SkeletonPoint bottomSke = depthFrame.MapToSkeletonPoint( centerDepthPoint.X - DEPTH_NEAR_RADIUS + (int)(DEPTH_SPAN * i), centerDepthPoint.Y + DEPTH_NEAR_RADIUS); depthArr[index++] = depthFrame.MapFromSkeletonPoint(bottomSke).Depth; // left SkeletonPoint leftSke = depthFrame.MapToSkeletonPoint( centerDepthPoint.X - DEPTH_NEAR_RADIUS, centerDepthPoint.Y - DEPTH_NEAR_RADIUS + (int)(DEPTH_SPAN * i)); depthArr[index++] = depthFrame.MapFromSkeletonPoint(leftSke).Depth; // right SkeletonPoint rightSke = depthFrame.MapToSkeletonPoint( centerDepthPoint.X + DEPTH_NEAR_RADIUS, centerDepthPoint.Y - DEPTH_NEAR_RADIUS + (int)(DEPTH_SPAN * i)); depthArr[index++] = depthFrame.MapFromSkeletonPoint(rightSke).Depth; } // set median(rather than mean) depth of the list Array.Sort(depthArr); kCalibrator.SetDepth(depthArr[DEPTH_NEAR_COUNT / 2]); ClearQueue(); Status = MainStatus.EdgeDetecting; mainWindow.textBlock.Text = "Detecting edge now. Arm at four corners of the screen."; // cooling time timer edgeTimer.Start(); edgeCooling = true; } } }