/// <summary> /// Raises the corresponding event. /// </summary> private void onExportFinished(object parameter) { object[] parameters = parameter as object[]; OpenNIRecordingController sender = parameters[0] as OpenNIRecordingController; DirectoryInfo exportDir = parameters[1] as DirectoryInfo; List <int> frames = parameters[2] as List <int>; List <int> userIDs = parameters[3] as List <int>; ImageDictionary exported_file_information2D = parameters[4] as ImageDictionary; ImageDictionary exported_file_information3D = parameters[5] as ImageDictionary; bool ExportRelativePathNames = (bool)parameters[6]; String export_filename_suffix = parameters[7] as String; if (exportThread != null && exportThread.IsAlive) { exportThread.Join(); } if (ExportFinished != null) { ExportFinished(sender, exportDir, frames, userIDs, exported_file_information2D, exported_file_information3D, ExportRelativePathNames, export_filename_suffix); } }
/// <summary> /// Starts to record the current stream. The stream must have been /// initialized when calling this method by using the method /// <see cref="StartGenerating"/>. /// </summary> /// <param name="captureFolder">The folder to create to recording in.</param> /// <param name="SaveUserPosition">Whether to record the user position /// in a separate file.</param> /// <exception cref="Exception">Thrown if initialization of the recording /// fails.</exception> internal void StartRecording(DirectoryInfo captureFolder, bool SaveUserPosition) { lock (RUN_CONTROL_LOCK) { if (!shouldRun || recording) { return; } else { // Change display options to get possibly smooth // recording.W shouldDrawBackground = true; shouldDrawHighlight = false; shouldDrawPixels = false; shouldDrawSkeleton = true; // Setup datastructures for recording. movementData = new ImageDictionary(true); if (SaveUserPosition) { Stream file_stream = new FileStream( Path.Combine(captureFolder.FullName, MAP_FILE_NAME), FileMode.Create); Stream write_stream; if (COMPRESS_USER_DATA) { write_stream = file_stream; } else { write_stream = file_stream; } // A writer for the user data file. userInformationWriter = new BinaryWriter(write_stream); } lock (HARDWARELOCK) { recorder = new Recorder(context); recorder.SetDestination(RecordMedium.File, Path.Combine(captureFolder.FullName, ONI_FILE_NAME)); recorder.AddNodeToRecording(imageGenerator); recorder.AddNodeToRecording(depthGenerator); } FileInfo movementDataFileInfo = new FileInfo( Path.Combine(captureFolder.FullName, USER_ANNOTATION_FILENAME)); movementDataFileName = movementDataFileInfo.FullName; } recording = true; onStartedRecording(); } }
private void listBoxResultDataSets_SelectedIndexChanged(object sender, EventArgs e) { listBoxUserResults.ClearSelected(); listBoxUserResults.Items.Clear(); onEvaluationRangeChanged(-1, -1); OpenNIRecordingController source = (videoDataSource.Source as OpenNIRecordingController); if (source != null) { source.AdditionalSkeletonInformation = null; source.AdditionalSkeletonIDs.Clear(); source.RequestUpdate(true); } if (listBoxResultDataSets.SelectedItem == null) { listBoxUserResults.Enabled = false; } else { String resultfilename = Path.Combine(current_take_dir.FullName, (String)listBoxResultDataSets.SelectedItem); try { using (FileStream file = File.Open(resultfilename, FileMode.Open)) { resultDictionary = (ImageDictionary)movementDataSerializer.Deserialize(file); } Dictionary <int, int> userActivities = resultDictionary.GetUserStatistics(null); foreach (int userID in userActivities.Keys) { listBoxUserResults.Items.Add("User " + userID); } if (source != null) { source.AdditionalSkeletonInformation = resultDictionary; onEvaluationRangeChanged(resultDictionary.Keys.Min(), resultDictionary.Keys.Max()); } listBoxUserResults.Enabled = true; } catch (Exception ex) { listBoxUserResults.ClearSelected(); listBoxUserResults.Items.Clear(); listBoxUserResults.Enabled = false; MessageBox.Show(this, "An Error occured loading the results file:\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }
/// <summary> /// Reports success and tries to generate data index file. /// </summary> private void exportFinished( OpenNIRecordingController sender, DirectoryInfo exportDir, List <int> frames, List <int> userIDs, ImageDictionary exportedFiles2D, ImageDictionary exportedFiles3D, bool ExportRelativePathNames, String export_filename_suffix) { // Report success. lazyInvoke((MethodInvoker) delegate { exportForm.textBoxProgress.Text = "Exporting images finished. Generating data index file..."; }); try { if (exportedFiles2D != null) { using (FileStream write_to = File.OpenWrite( Path.Combine(exportDir.FullName, "Export2D" + export_filename_suffix + ".xml"))) { movementDataSerializer.Serialize(write_to, exportedFiles2D); } } if (exportedFiles3D != null) { using (FileStream write_to = File.OpenWrite( Path.Combine(exportDir.FullName, "Export3D" + export_filename_suffix + ".xml"))) { movementDataSerializer.Serialize(write_to, exportedFiles3D); } } } catch (Exception e) { showException("Error creating data index file: \n" + e.Message); } // Report success. lazyInvoke((MethodInvoker) delegate { exportForm.Hide(); textBoxExport.Text = "Last export successful to folder " + exportDir.FullName; }); sender.ResetExportEventHandlers(); }
/// <summary> /// Creates a new control instance with a recording as data /// source. The current image data can be obtained by the /// <see cref="Image"/>-property. The /// <see cref="NewImageDataAvailable"/> event informs about when the /// data is updated, the <see cref="ErrorOccured"/>-event about /// errors. /// </summary> /// <exception cref="System.Exception">Thrown if the stream could not /// be initialized properly.</exception> public OpenNIRecordingController(String recording_filename, String movementDataFileName, String userAnnotationFilename) { // Create a new context and the data-generating nodes. context = new Context(); context.OpenFileRecording(recording_filename); this.recording_filename = recording_filename; _userInformationReader = new BinaryReader( new FileStream(movementDataFileName, FileMode.Open)); using (FileStream annotation_stream = File.OpenRead(userAnnotationFilename)) { _userLocationInformation = (ImageDictionary)movementDataSerializer.Deserialize(annotation_stream); } // Image imageGenerator = (ImageGenerator)context.FindExistingNode(NodeType.Image); // Depth depthGenerator = (DepthGenerator)context.FindExistingNode(NodeType.Depth); histogram = new int[depthGenerator.DeviceMaxDepth]; // Player player = (Player)context.FindExistingNode(NodeType.Player); player.PlaybackSpeed = 1.0; if (depthGenerator == null || imageGenerator == null || player == null) { throw new Exception("Could not initialize recording stream."); } // Error handling context.ErrorStateChanged += context_ErrorStateChanged; context.StartGeneratingAll(); }
/// <summary> /// Sets the data for the statistics object. The statistic values /// are calculated in this method. The results and truth dictionaries /// must contain at least a key for every frame between minimal and /// maximal frame number. /// </summary> /// <param name="truth">The ground truth dictionary.</param> /// <param name="results">The result dictionary.</param> /// <param name="truth_id">The id of the user to compare to as truth in /// the truth data ids.</param> /// <param name="results_id">The id of the result user to compare with /// in the result data ids.</param> /// <param name="converter">A function to convert 3d data to 2d data /// if necessary.</param> /// <exception cref="Exception">Thrown if the frames are not continuous /// from first to last.</exception> internal void SetData(ImageDictionary truth, ImageDictionary results, int truth_id, int results_id, To2DConverter converter) { // Reset. GlobalMean = 0.0; FrameMean = 0.0; FrameValue = 0.0; NumberOfPoints = 0; first_frame = int.MaxValue; last_frame = -1; isInBatchMode = false; errors = new Dictionary <SkeletonJoint, List <DifferenceData> >(); foreach (JointTranslationTuple translation in JointDictionary.JointTranslationList) { errors.Add(translation.joint_type, new List <DifferenceData>()); } resultDict = results; truthDict = truth; work_in_3D = results.Is3DData; if (work_in_3D && !truth.Is3DData) { throw new ArgumentException("Trying to compare data with insufficient information."); } // Check converter availability if necessary if (!resultDict.Is3DData && truth.Is3DData && converter == null) { throw new ArgumentException("Must convert data to 2D, but no converter was specified."); } // Start calculating data. foreach (int frame in results.Keys) { if (frame < first_frame) { first_frame = frame; } if (frame > last_frame) { last_frame = frame; } // Convert the data if necessary JointDictionary frame_data_truth = new JointDictionary(work_in_3D); JointDictionary frame_data_results = new JointDictionary(work_in_3D); bool user_in_truth = false; bool user_in_results = false; if (results[frame].ContainsKey(results_id)) { user_in_results = true; if (results.Is3DData && !work_in_3D) { frame_data_results = converter(results[frame][results_id]); } else { frame_data_results = results[frame][results_id]; } } if (truth[frame].ContainsKey(truth_id)) { user_in_truth = true; if (truth.Is3DData && !work_in_3D) { frame_data_truth = converter(truth[frame][truth_id]); } else { frame_data_truth = truth[frame][truth_id]; } } foreach (SkeletonJoint joint in errors.Keys) { DifferenceData data = new DifferenceData(); data.frame = frame; data.Difference = double.NaN; Point3D resultsPoint = new Point3D(), truthPoint = new Point3D(); if (user_in_results && frame_data_results.ContainsKey(joint)) { data.inResultData = true; resultsPoint = frame_data_results[joint].Position; } if (user_in_truth && frame_data_truth.ContainsKey(joint)) { data.inTruthData = true; data.Confidence = frame_data_truth[joint].Confidence; truthPoint = frame_data_truth[joint].Position; } if (data.inTruthData && data.inResultData) { if (work_in_3D) { data.Difference = Math.Sqrt( Math.Pow(truthPoint.X - resultsPoint.X, 2.0) + Math.Pow(truthPoint.Y - resultsPoint.Y, 2.0) + Math.Pow(truthPoint.Z - resultsPoint.Z, 2.0)); } else { data.Difference = Math.Sqrt( Math.Pow(truthPoint.X - resultsPoint.X, 2.0) + Math.Pow(truthPoint.Y - resultsPoint.Y, 2.0)); } } int position = 0; List <DifferenceData> to_insert_in = errors[joint]; for (int i = 0; i < to_insert_in.Count; i++) { if (frame > to_insert_in[i].frame) { break; } else { position++; } } errors[joint].Add(data); } } // Check that list is complete!!! int range = last_frame - first_frame + 1; bool failed = false; foreach (SkeletonJoint joint in errors.Keys) { if (errors[joint].Count != range) { failed = true; break; } } if (failed) { errors.Clear(); throw new Exception("The algorithm results did not contain every " + "frame from the first to the last."); } }
/// <summary> /// The export logic. /// </summary> /// <param name="parameter">An object[] with the real parameters. /// Have a look at <see cref="ExportFrames"/> for a usage /// example.</param> private void doExport(object parameter) { object[] parameters = parameter as object[]; if (parameters == null) { return; } // Export directory DirectoryInfo exportDir = parameters[10] as DirectoryInfo; if (exportDir == null) { return; } // Frame list List <int> frames = parameters[0] as List <int>; if (frames == null || frames.Count == 0) { return; } frames.Sort(); // User list List <int> userIDs = parameters[1] as List <int>; if (userIDs == null) { return; } // Ignore List List <int> formerIgnoreList = new List <int>(UsersToIgnore); UsersToIgnore.Clear(); List <int> occuringUsers = GetUserStatistics(frames).Keys.ToList <int>(); foreach (int user in occuringUsers) { if (!userIDs.Contains(user)) { UsersToIgnore.Add(user); } } // The rest of parameters bool AnnotationsIn2D = (bool)parameters[2]; bool AnnotationsIn3D = (bool)parameters[3]; bool ExportRelativePathNames = (bool)parameters[4]; bool ImageOrDepth = (bool)parameters[5]; bool DrawBackground = (bool)parameters[6]; bool DrawSkeleton = (bool)parameters[7]; bool DrawHighlights = (bool)parameters[8]; bool DrawLabels = (bool)parameters[9]; // Number format int max = frames[frames.Count - 1]; int characters; if (max == 0) { characters = 1; } else { characters = (int)Math.Ceiling(Math.Log10(max)); } String exportFormatString = "d" + characters; // The export xml files. ImageDictionary exportedIndex2D = new ImageDictionary(false); exportedIndex2D.XmlExportFrameFileList = new Dictionary <int, string>(); exportedIndex2D.XmlOmitPoints = (userIDs.Count == 0); ImageDictionary exportedIndex3D = new ImageDictionary(true); exportedIndex3D.XmlExportFrameFileList = new Dictionary <int, string>(); exportedIndex3D.XmlOmitPoints = (userIDs.Count == 0); String filename; String export_filename_suffix = ""; lock (RUN_CONTROL_LOCK) { try { StopPlayback(); lock (EXPORT_LOCK) { // Configure for export DrawSkeletonMesh = DrawSkeleton; DrawSensorData = true; this.ImageOrDepth = ImageOrDepth; this.DrawBackground = DrawBackground; this.DrawUserHighlight = DrawHighlights; this.DrawUserInformation = DrawLabels; if (DrawSkeleton) { export_filename_suffix += "s"; } if (!DrawSensorData) { export_filename_suffix += "a"; } if (!ImageOrDepth) { export_filename_suffix += "d"; } if (!DrawBackground) { export_filename_suffix += "b"; } if (DrawUserHighlight) { export_filename_suffix += "h"; } if (DrawUserInformation) { export_filename_suffix += "l"; } if (export_filename_suffix.Length > 0) { export_filename_suffix = "-" + export_filename_suffix; } for (int frameIndex = 0; frameIndex < frames.Count; frameIndex++) { SeekFrame(frames[frameIndex]); RequestUpdate(false); String relative_filename = frames[frameIndex].ToString(exportFormatString) + export_filename_suffix + ".png"; filename = Path.Combine(exportDir.FullName, relative_filename); lock (ImageLock) { bitmap.Save(filename, ImageFormat.Png); } // Get the user positions in this frame Dictionary <int, JointDictionary> frame_positions2D = new Dictionary <int, JointDictionary>(); Dictionary <int, JointDictionary> frame_positions3D = new Dictionary <int, JointDictionary>(); if (UserLocationInformation.ContainsKey(frames[frameIndex])) { foreach (int user in UserLocationInformation[frames[frameIndex]].Keys) { if (userIDs.Contains(user)) { frame_positions3D.Add(user, new JointDictionary( UserLocationInformation[frames[frameIndex]][user])); frame_positions2D.Add(user, new JointDictionary( Convert3Dto2D(UserLocationInformation[frames[frameIndex]][user], depthGenerator))); } } } exportedIndex2D.Add(frames[frameIndex], frame_positions2D); if (!ExportRelativePathNames) { exportedIndex2D.XmlExportFrameFileList.Add( frames[frameIndex], filename); } else { exportedIndex2D.XmlExportFrameFileList.Add( frames[frameIndex], relative_filename); } exportedIndex3D.Add(frames[frameIndex], frame_positions3D); if (!ExportRelativePathNames) { exportedIndex3D.XmlExportFrameFileList.Add( frames[frameIndex], filename); } else { exportedIndex3D.XmlExportFrameFileList.Add( frames[frameIndex], relative_filename); } onExportMadeProgress( (float)(frameIndex + 1) / (float)frames.Count * 100, frameIndex + 1, frames.Count); if (export_cancelled) { return; } } } } catch (Exception e) { onExportFailed(e.Message); return; } // Reset ignore list UsersToIgnore.Clear(); UsersToIgnore.AddRange(formerIgnoreList); if (!AnnotationsIn2D) { exportedIndex2D = null; } if (!AnnotationsIn3D) { exportedIndex3D = null; } } // Report success. Thread reporter = new Thread(onExportFinished); reporter.Start(new object[] { this, exportDir, frames, userIDs, exportedIndex2D, exportedIndex3D, ExportRelativePathNames, export_filename_suffix }); }
/// <summary> /// Reconfigures the exporting parameters and starts the second part /// of the batch export. /// </summary> private void batchExportPart1Finished( OpenNIRecordingController sender, DirectoryInfo exportDir, List <int> frames, List <int> userIDs, ImageDictionary exportedFiles2D, ImageDictionary exportedFiles3D, bool ExportRelativePathNames, String export_filename_suffix) { // Report success. lazyInvoke((MethodInvoker) delegate { exportForm.textBoxProgress.Text = "Exporting standard images finished (Batch export part 1)." + "Generating data index file..."; }); try { if (exportedFiles2D != null) { using (FileStream write_to = File.OpenWrite( Path.Combine(exportDir.FullName, "Export2D" + export_filename_suffix + ".xml"))) { movementDataSerializer.Serialize(write_to, exportedFiles2D); } } if (exportedFiles3D != null) { using (FileStream write_to = File.OpenWrite( Path.Combine(exportDir.FullName, "Export3D" + export_filename_suffix + ".xml"))) { movementDataSerializer.Serialize(write_to, exportedFiles3D); } } } catch (Exception e) { showException("Error creating data index file: \n" + e.Message); } // Configure for the second export. // Check whether the user selected to do a batch export. OpenNIRecordingController exportVideo = sender; exportVideo.ExportFinished -= batchExportPart1Finished; exportVideo.ExportFinished += batchExportPart2Finished; // Reset progress bar. lazyInvoke((MethodInvoker) delegate { exportForm.progressBar.Value = 0; exportForm.textBoxProgress.Text = "Initializing batch export part 2..."; }); // Begin exporting. exportVideo.ExportFrames( frames, userIDs, (exportedFiles2D != null), (exportedFiles3D != null), ExportRelativePathNames, true, true, true, false, false, exportDir); }