// This method is executed by the ThreadPoolTimer, it performs the evaluation on a copy of the VideoFrame private async void EvaluateVideoFrame(ThreadPoolTimer timer) { // If a lock is being held, or WinML isn't fully initialized, return if (!semaphore.Wait(0) || !modelBindingComplete) { return; } try { using (evaluatableVideoFrame) { // ************ WinML Evaluate Frame ************ // Debug.WriteLine($"RelativeTime in Seconds: {evaluatableVideoFrame.RelativeTime?.Seconds}"); await model.EvaluateAsync(binding, "TinyYOLO"); // Remove overlapping and low confidence bounding boxes filteredBoxes = parser.NonMaxSuppress(parser.ParseOutputs(outputArray.ToArray()), 5, .5F); Debug.WriteLine(filteredBoxes.Count <= 0 ? $"No Valid Bounding Boxes" : $"Valid Bounding Boxes: {filteredBoxes.Count}"); } } catch (Exception ex) { Debug.WriteLine($"EvaluateFrameException: {ex}"); } finally { semaphore.Release(); } }
private async Task EvaluateVideoFrameWithYoloAsync(VideoFrame inputFrame) { if (inputFrame != null) { try { // Create bindings for the input and output buffer var binding = new LearningModelBindingPreview(model); // R4 WinML does needs the output pre-allocated for multi-dimensional tensors var outputArray = new List <float>(); outputArray.AddRange(new float[21125]); // Total size of TinyYOLO output binding.Bind(inputImageDescription.Name, inputFrame); binding.Bind(outputTensorDescription.Name, outputArray); // Process the frame with the model var stopwatch = Stopwatch.StartNew(); //var results = await model.EvaluateAsync(binding, "TinyYOLO"); var results = await model.EvaluateAsync(binding, "TinyYOLOv2"); stopwatch.Stop(); var resultProbabilities = results.Outputs[outputTensorDescription.Name] as List <float>; // Use out helper to parse to the YOLO outputs into bounding boxes with labels boxes = parser.ParseOutputs(resultProbabilities.ToArray(), .3F); await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { Duration.Text = $"{1000f / stopwatch.ElapsedMilliseconds,4:f1} fps"; StatusBlock.Text = "TinyYoloModel Evaluation Completed"; }); } catch (Exception ex) { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => StatusBlock.Text = $"EvaluateVideoFrameWithYoloAsync Error: {ex.Message}"); } await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => EvaluateImageButton.IsEnabled = true); } }
// This method is executed by the ThreadPoolTimer, it performs the evaluation on a copy of the VideoFrame private async void EvaluateVideoFrame(ThreadPoolTimer timer) { if (semaphore == null) { return; } if (!modelCreated) { Debug.WriteLine($"EvaluateVideoFrame Skipped - LearningModel Not Ready."); return; } // If a lock is being held, or WinML isn't fully initialized, return if (!semaphore.Wait(0)) { Debug.WriteLine($"EvaluateVideoFrame Skipped - Waiting Semaphore Access"); return; } if (session == null) { try { Debug.WriteLine($"Attempting to create LearningModelSession using DeviceKind: {detectedDeviceKind}"); session = new LearningModelSession(model, new LearningModelDevice(detectedDeviceKind)); Debug.WriteLine($"LearningModelSession successfully created."); } catch (Exception ex) { Debug.WriteLine($"Error Creating Session: {ex.Message}"); model = null; return; } } Debug.WriteLine($"*************** Evaluating Video Frame [START] ***************"); try { using (videoFrameToProcess) { // ************ WinML Evaluate Frame ************ // Debug.WriteLine($"VideoFrame RelativeTime: {videoFrameToProcess.RelativeTime?.Seconds}s"); // Create a binding object from the session binding = new LearningModelBinding(session); // Create an image tensor from a video frame var image = ImageFeatureValue.CreateFromVideoFrame(videoFrameToProcess); // The YOLO model's input name is "image" and output name is "grid" var inputName = "image"; var outputName = "grid"; // Bind the image to the input binding.Bind(inputName, image); // Process the frame with the model var results = await session.EvaluateAsync(binding, $"YoloRun {++runCount}"); Debug.WriteLine($"Evaluation Result Success? {results.Succeeded} "); if (!results.Succeeded) { return; } Debug.WriteLine($" **** {results.Outputs.Count} Outputs Available ***** "); foreach (var output in results.Outputs) { Debug.WriteLine($" - {output.Key}"); } // Retrieve the results of evaluation var resultTensor = results.Outputs[outputName] as TensorFloat; Debug.WriteLine($"Result Feature Kind: {resultTensor?.Kind.ToString()} "); var resultVector = resultTensor?.GetAsVectorView(); // Remove overlapping and low confidence bounding boxes filteredBoxes = parser.NonMaxSuppress(parser.ParseOutputs(resultVector?.ToArray()), 5, .5F); Debug.WriteLine(filteredBoxes.Count <= 0 ? $"No Valid Bounding Boxes" : $"Valid Bounding Boxes: {filteredBoxes.Count}"); } } catch (Exception ex) { Debug.WriteLine($"Error: EvaluateFrameException: {ex}"); } finally { semaphore?.Release(); Debug.WriteLine($"*************** Evaluating Video Frame [END] ***************"); } }