/// <summary> /// Handles the user clicking on the stop button /// </summary> /// <param name="sender">object sending the event</param> /// <param name="e">event arguments</param> private async void stopButton_Click(object sender, RoutedEventArgs e) { this.stopButton.IsEnabled = false; // Log off events' enqueueing method to stop receiving new frames LogoffEnqueueEvents(); String msg = "The \"start\" button is uable until the left images have already been written to disk !"; System.Windows.MessageBox.Show(msg); await Task.Run((Action)(() => stopButtonSleep())); // Cancel five storing threads' task colorCollectedCancellationTokenSource.Cancel(); depthCollectedCancellationTokenSource.Cancel(); bodyCollectedCancellationTokenSource.Cancel(); bodyIndexCollectedCancellationTokenSource.Cancel(); infraredCollectedCancellationTokenSource.Cancel(); // Clear five event args' queues // 清空队列 ClearQueues(); // Reset global frame information used for regularizing the frame number lock (FramesAndPaths.allFrameInfo) { FramesAndPaths.ResetAllFrameInfos(); } this.startButton.IsEnabled = true; this.decrementVideoBtn.IsEnabled = true; this.incrementVideoBtn.IsEnabled = true; }
/// <summary> /// Main Window /// </summary> public MainWindow() { kinectSensor = KinectSensor.GetDefault(); coordinateMapper = kinectSensor.CoordinateMapper; // Initialize the global frame information // 初始化帧相关的全局信息 FramesAndPaths.initializeFrameData(); // Initialize the components (controls) of the window // 初始化窗口组件 this.InitializeComponent(); // Use the window object as the view model in this simple example this.DataContext = this; this.InitializePart_DisplayingImgsHandler(); this.InitializePart_DrawingSkeletonHandler(); // Open readers OpenFrameReaders(); // Show three kinds of image information(here are the color, depth and skeleton) onto three image controls //this.RegisterMonitors(); // Open the kinect sensor kinectSensor.Open(); // Initialize and start the written fps timer this.writtenFpsTimer = new DispatcherTimer(); this.writtenFpsTimer.Tick += new EventHandler(this.WrittenFpsTimerTick); this.writtenFpsTimer.Interval = new TimeSpan(0, 0, 1); this.writtenFpsTimer.Start(); this.lastWrittenFpsTimerStamp = DateTime.UtcNow; }
/// <summary> /// Handles the user clicking on the create button /// </summary> /// <param name="sender">object sending the event</param> /// <param name="e">event arguments</param> private void createButton_Click(object sender, RoutedEventArgs e) { System.Windows.Forms.FolderBrowserDialog selectFolderDialog = new FolderBrowserDialog(); selectFolderDialog.ShowDialog(); if (selectFolderDialog.SelectedPath != String.Empty) { // Set root directory of your dataset. SSD is prefered which supplies higher IO efficiency than a normal disk FramesAndPaths.SetDatasetRootDirectory(System.IO.Path.Combine(selectFolderDialog.SelectedPath, "KinectDataSet")); // Display the root directory of your dataset String str = FramesAndPaths.GetDatasetRootDirectory(); this.datasetRootTextBlock.Text = str; // Ask video number int result = 0; while (result < 1 || result >= 100) { // Input video number String userInput = Microsoft.VisualBasic.Interaction.InputBox("video number: 1 to 99 is valid", "Please input the video number", "1"); int.TryParse(userInput, out result); } FramesAndPaths.SetVideoCount(result); videoTextBoxBorder.BorderBrush = Brushes.Blue; // Create file structure under the root directory of the dataset // Create root directory String root = FramesAndPaths.GetDatasetRootDirectory(); System.IO.Directory.CreateDirectory(root); for (int i = 0; i < result; ++i) { // Create video directories String videoFolderPath = System.IO.Path.Combine(FramesAndPaths.GetDatasetRootDirectory(), (i < 9 ? "video0" : "video") + (i + 1).ToString()); System.IO.Directory.CreateDirectory(videoFolderPath); // Create image info sub-directories under the corresponding video directory for (int j = 0; j < FramesAndPaths.fileCategories.Length; ++j) { String imagePath = videoFolderPath + FramesAndPaths.fileCategories[j]; System.IO.Directory.CreateDirectory(imagePath); } // Create Skeleton text under the SkeletonInfo folder to record skeleton information String skeletonInfoPath = System.IO.Path.Combine(videoFolderPath, "SkeletonInfo", "SkeletonInfo.txt"); System.IO.File.Create(skeletonInfoPath); } startButton.IsEnabled = true; createButton.IsEnabled = false; // Set videoText uneditable //videoText.IsEnabled = true; incrementVideoBtn.IsEnabled = true; decrementVideoBtn.IsEnabled = true; } // Release the dialog selectFolderDialog.Dispose(); }
/// <summary> /// Handles body(skeleton) /// </summary> /// <param name="bodyCollectedCancelTokenSource">cancelTokenSource used to stop the task</param> private static void HandleBody(CancellationTokenSource bodyCollectedCancelTokenSource) { BodyFrameArrivedEventArgs e = null; String frameNumber = String.Empty; BodyFrame bodyFrame; while (true) { bodyFrame = null; if (bodyCollectedCancelTokenSource.IsCancellationRequested) { break; } if (bodyFrameQueue.Count != 0) { lock (FramesAndPaths.allFrameInfo) { if ((FramesAndPaths.allFrameInfo.allFrameFlag & 4) != 0) { continue; } try { e = bodyFrameQueue.Dequeue(); } catch (InvalidOperationException) { continue; } try { bodyFrame = e.FrameReference.AcquireFrame(); } catch (NullReferenceException) {} if (bodyFrame == null) { continue; } frameNumber = FramesAndPaths.allFrameInfo.frameNumber; FramesAndPaths.allFrameInfo.allFrameFlag |= 4; if ((FramesAndPaths.allFrameInfo.allFrameFlag ^ 31) == 0) { FramesAndPaths.allFrameInfo.allFrameFlag = 0; FramesAndPaths.FrameNumberIncrement(); ++writtenCount; } } StoreFramesData.Handle_BodyFrame(bodyFrame, frameNumber); } } }
/// <summary> /// Store color image /// </summary> /// <param name="colorFrame">color frame to be stored</param> /// <param name="frameNumber">frame number</param> public static void Handle_ColorFrame(ColorFrame colorFrame, String frameNumber) { colorFrame.CopyConvertedFrameDataToArray(bgraColor, ColorImageFormat.Bgra); BitmapSource bitmapSource = BitmapSource.Create(colorWidth, colorHeight, 96.0, 96.0, PixelFormats.Bgra32, null, bgraColor, colorWidth << 2); String colorPath = FramesAndPaths.GetImageFilePath(FramesAndPaths.FileType.ColorImage, frameNumber); bitmapSource.Save(colorPath + ".jpg", ImageFormat.Jpeg); // Release colorFrame colorFrame.Dispose(); }
/// <summary> /// Store body index image /// </summary> /// <param name="bodyIndexFrame">body index frame to be stored</param> /// <param name="frameNumber">frame number</param> public static void Handle_BodyIndexFrame(BodyIndexFrame bodyIndexFrame, String frameNumber) { using (Microsoft.Kinect.KinectBuffer bodyIndexBuffer = bodyIndexFrame.LockImageBuffer()) { BitmapSource bitmapSource = BitmapSource.Create(bodyIndexWidth, bodyIndexHeight, 96.0, 96.0, PixelFormats.Gray8, null, bodyIndexBuffer.UnderlyingBuffer, (int)bodyIndexBuffer.Size, bodyIndexWidth * 1); String bodyIndexPath = FramesAndPaths.GetImageFilePath(FramesAndPaths.FileType.BodyIndexImage, frameNumber); bitmapSource.Save(bodyIndexPath + ".jpg", ImageFormat.Jpeg); } // Release bodyIndexFrame bodyIndexFrame.Dispose(); }
/// <summary> /// Store depth image /// </summary> /// <param name="depthFrame">depth frame to be stored</param> /// <param name="frameNumber">frame number</param> public static void Handle_DepthFrame(DepthFrame depthFrame, String frameNumber) { using (Microsoft.Kinect.KinectBuffer depthBuffer = depthFrame.LockImageBuffer()) { BitmapSource bitmapSource = BitmapSource.Create(depthWidth, depthHeight, 96.0, 96.0, PixelFormats.Gray16, null, depthBuffer.UnderlyingBuffer, (int)depthBuffer.Size, depthWidth << 1); String depthPath = FramesAndPaths.GetImageFilePath(FramesAndPaths.FileType.DepthImage, frameNumber); bitmapSource.Save(depthPath + ".png", ImageFormat.Png); } // Release depthFrame depthFrame.Dispose(); }
/// <summary> /// Store infrared image /// </summary> /// <param name="infraredFrame">infrared frame to be stored</param> /// <param name="frameNumber">frame number</param> public static void Handle_InfraredFrame(InfraredFrame infraredFrame, String frameNumber) { using (Microsoft.Kinect.KinectBuffer infraredBuffer = infraredFrame.LockImageBuffer()) { BitmapSource bitmapSource = BitmapSource.Create(infraredWidth, infraredHeight, 96.0, 96.0, PixelFormats.Gray16, null, infraredBuffer.UnderlyingBuffer, (int)infraredBuffer.Size, infraredWidth << 1); String infraredPath = FramesAndPaths.GetImageFilePath(FramesAndPaths.FileType.InfraredImage, frameNumber); bitmapSource.Save(infraredPath + ".jpg", ImageFormat.Jpeg); } // Release infraredFrame infraredFrame.Dispose(); }
/// <summary> /// Handles the user clicking on the decrement button /// Select previous video folder to record /// </summary> /// <param name="sender">object sending the event</param> /// <param name="e">event arguments</param> private void decrementVideoBtn_Click(object sender, RoutedEventArgs e) { int result; int.TryParse(this.videoText.Text, out result); this.videoText.Text = (--result).ToString(); if (result >= 1 && result <= FramesAndPaths.GetVideoCount()) { videoTextBoxBorder.BorderBrush = Brushes.Blue; FramesAndPaths.RefreshCurrentVideoNumber(result); } else { videoTextBoxBorder.BorderBrush = Brushes.Red; } }
/// <summary> /// Store body(skeleton) information /// </summary> /// <param name="bodyFrame">body(skeleton) information to be stored</param> /// <param name="frameNumber">frame number</param> public static void Handle_BodyFrame(BodyFrame bodyFrame, String frameNumber) { String skeletonInfoPath = FramesAndPaths.GetSkeletonFilePath(FramesAndPaths.FileType.SkeletonInfo, "SkeletonInfo.txt"); try { using (StreamWriter skeletonWriter = new StreamWriter(skeletonInfoPath, true)) { Body[] bodies = new Body[bodyFrame.BodyCount]; bodyFrame.GetAndRefreshBodyData(bodies); // A string to store all the skeletons' information in this frame // 要写入 txt 文件的本帧所有骨骼信息 String peopleInfo = String.Empty; foreach (Body body in bodies) { if (body.IsTracked) { IReadOnlyDictionary <JointType, Joint> joints = body.Joints; IReadOnlyDictionary <JointType, JointOrientation> jointOrientations = body.JointOrientations; // Acquire coordinates on camera space // 获得 camera space 上关节点的三维坐标 int jointIndex = 0; foreach (JointType jointType in joints.Keys) { // sometimes the depth(Z) of an) inferred joint may show as negative // clamp down to 0.1f to prevent coordinatemapper from returning (-Infinity, -Infinity) cameraSpacePositions[jointIndex] = joints[jointType].Position; if (cameraSpacePositions[jointIndex].Z < 0) { cameraSpacePositions[jointIndex].Z = InferredZPositionClamp; } ++jointIndex; } // Acquire coordinates on color space // 获得 color space 上的 25 个关节点的二维坐标 MainWindow.coordinateMapper.MapCameraPointsToColorSpace(cameraSpacePositions, colorSpacePositions); // Acquire coordinates on depth space // 获得 depth space 上的 25 个关节点的二维坐标 MainWindow.coordinateMapper.MapCameraPointsToDepthSpace(cameraSpacePositions, depthSpacePositions); // Acquire orientation information // 获得关节点的旋转信息 jointIndex = 0; foreach (JointType jointType in jointOrientations.Keys) { JointOrientation tmpOrientation = jointOrientations[jointType]; orientations[jointIndex++] = tmpOrientation.Orientation; } // frame number、tracking % 6、floor ulong resizeId = body.TrackingId % 6; Vector4 floor = bodyFrame.FloorClipPlane; //String personInfo = String.Format("{0}, id = {1}, color = {2},\r\n",GlobalData.FrameNumberIncrement(GlobalData.FileType.SkeletonInfo),resizeId,bodyColors[resizeId]); // A string to store current skeleton's information in this frame // 要加入 peopleInfo 的本帧当前一具骨骼信息 personInfo String personInfo = String.Format("{0}, id = {1}, floor = {2} {3} {4} {5}", frameNumber, resizeId, floor.W, floor.X, floor.Y, floor.Z); personInfo += "\r\n"; // Append coordinates on camera space // 相机空间三维坐标 personInfo += "\tcamera_space_coordinates ="; personInfo += String.Format(" {0} {1} {2}", cameraSpacePositions[0].X, cameraSpacePositions[0].Y, cameraSpacePositions[0].Z); for (int i = 1; i < cameraSpacePositions.Length; ++i) { personInfo += String.Format(", {0} {1} {2}", cameraSpacePositions[i].X, cameraSpacePositions[i].Y, cameraSpacePositions[i].Z); } personInfo += "\r\n"; // Append coordiantes on color space // rgb骨架二维坐标 personInfo += "\tcolor_skeleton_coordinates ="; personInfo += String.Format(" {0} {1}", colorSpacePositions[0].X, colorSpacePositions[0].Y); for (int i = 1; i < colorSpacePositions.Length; ++i) { personInfo += String.Format(", {0} {1}", colorSpacePositions[i].X, colorSpacePositions[i].Y); } personInfo += "\r\n"; // Append coordinates on depth space // depth骨架二维坐标 personInfo += "\tdepth_skeleton_coordinates ="; personInfo += String.Format(" {0} {1}", depthSpacePositions[0].X, depthSpacePositions[0].Y); for (int i = 1; i < depthSpacePositions.Length; ++i) { personInfo += String.Format(", {0} {1}", depthSpacePositions[i].X, depthSpacePositions[i].Y); } personInfo += "\r\n"; personInfo += "\tskeleton_orientations ="; personInfo += String.Format(" {0} {1} {2} {3}", orientations[0].W, orientations[0].X, orientations[0].Y, orientations[0].Z); for (int i = 1; i < orientations.Length; ++i) { personInfo += String.Format(", {0} {1} {2} {3}", orientations[i].W, orientations[i].X, orientations[i].Y, orientations[i].Z); } peopleInfo += personInfo; peopleInfo += "\r\n"; } } skeletonWriter.Write(peopleInfo); } } catch (System.IO.IOException) { } // Release bodyFrame bodyFrame.Dispose(); }
/// <summary> /// Handles color /// </summary> /// <param name="colorCollectedCancelTokenSource">cancelTokenSource used to stop the task</param> private static void HandleColor(CancellationTokenSource colorCollectedCancelTokenSource) { ColorFrameArrivedEventArgs e = null; String frameNumber = String.Empty; ColorFrame colorFrame; while (true) { colorFrame = null; // Whether task is requested to be canceled or not // 检查线程是否被请求中止 if (colorCollectedCancelTokenSource.IsCancellationRequested) { break; } // Queue not empty // 若队列不空 if (colorFrameQueue.Count != 0) { // Only one thread is allowed to access the global frame information object each time // 加互斥锁, 一次只允许一个线程访问 lock (FramesAndPaths.allFrameInfo) { // The frame information has already been written to disk this round, continue // 若本回写过, 则下一次循环 if ((FramesAndPaths.allFrameInfo.allFrameFlag & 1) != 0) { continue; } // Fetch a frame try { e = colorFrameQueue.Dequeue(); } catch (InvalidOperationException) { continue; } try { colorFrame = e.FrameReference.AcquireFrame(); } catch (NullReferenceException) { } // Null frame, continue if (colorFrame == null) { continue; } // Fetch global frame number // 拿帧号 frameNumber = FramesAndPaths.allFrameInfo.frameNumber; // Label current frame to be written this around // 标记 rgb 帧已写 FramesAndPaths.allFrameInfo.allFrameFlag |= 1; // All kinds of frame information have been written to disk // 本回各种帧都已写完 if ((FramesAndPaths.allFrameInfo.allFrameFlag ^ 31) == 0) { // Set global flag to zero // 全局flag置0 FramesAndPaths.allFrameInfo.allFrameFlag = 0; // Increment the frame number // frameNumber 增加 FramesAndPaths.FrameNumberIncrement(); // Increment the number of series of frames this program processes this second ++writtenCount; } } // Write to disk // 写图 StoreFramesData.Handle_ColorFrame(colorFrame, frameNumber); } } }