/// <summary> /// Triggered when the file picker button is clicked /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void UIButtonFilePick_Click(object sender, RoutedEventArgs e) { // Pick image file var imageFiles = await GetFilesPickedAsync(); if (imageFiles == null || imageFiles.Count == 0) { return; } await UIParameterDialog.ShowAsync(); UIResultPanel.Items.Clear(); m_imageToProcessTotal = imageFiles.Count; UIProgressMaxValue.Text = m_imageToProcessTotal.ToString(); m_hashTags = ImmutableHashSet.CreateBuilder(new TagEqualityComparer()); // Disable UI UIOptionPanel.IsEnabled = false; UIButtonFilePick.IsEnabled = false; UIHashTagBrowser.IsEnabled = false; UIClearFilterButton.IsEnabled = false; NotifyUser("", NotifyType.ClearMessage); // Start our stopwatch to measure the time it takes to process all of this m_perfWatch.Restart(); m_e2eRunTime = (float)m_perfWatch.ElapsedTicks / Stopwatch.Frequency * 1000f; m_imageProcessedCount = 0; UIFilterPanel.Visibility = Visibility.Collapsed; UIProgressPanel.Visibility = Visibility.Visible; UIExecutionProgressRing.Visibility = Visibility.Visible; UIExecutionProgressRing.IsActive = true; // Process each image selected foreach (var file in imageFiles) { // Take a lock for using a binding if one is available, or wait if not await m_bindingLock.WaitAsync(); // Display a staging content in our UI ResultItemUserControl resultItem = new ResultItemUserControl(); UIResultPanel.Items.Add(resultItem); // Start a task that will Load the frame, display it in the UI, binf it and schedule // execution of the skill against that binding // (fire and forget) var bindingTask = Task.Run(async() => { ConceptTaggerBinding binding = null; // Execute concept tag skill try { // Load the VideoFrame from the image file var frame = await LoadVideoFrameFromFileAsync(file); if (frame == null) { throw new Exception($"Error reading image file: {file.Path}"); } if (!m_bindingQueue.TryDequeue(out binding)) { throw new Exception("Could not access binding"); } var baseTime = (float)m_perfWatch.ElapsedTicks / Stopwatch.Frequency * 1000f; // Bind input image await binding.SetInputImageAsync(frame); // Record bind time for display resultItem.BindTime = (float)m_perfWatch.ElapsedTicks / Stopwatch.Frequency * 1000f - baseTime; // Display image and results await Dispatcher.RunAsync( CoreDispatcherPriority.Normal, async() => { await resultItem.UpdateResultItemImageAsync(frame.SoftwareBitmap); }); // Evaluate binding (fire and forget) var evalTask = Task.Run(() => EvaluateBinding(binding, resultItem)); } catch (Exception ex) { NotifyUser(ex.Message, NotifyType.ErrorMessage); if (binding != null) { m_bindingQueue.Enqueue(binding); } m_bindingLock.Release(); m_imageToProcessTotal--; await UIProgressMaxValue.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => UIProgressMaxValue.Text = m_imageToProcessTotal.ToString()); } }); } // Enable UI UIOptionPanel.IsEnabled = true; UIButtonFilePick.IsEnabled = true; UIHashTagBrowser.IsEnabled = true; UIClearFilterButton.IsEnabled = true; UIFilterPanel.Visibility = Visibility.Visible; UIExecutionProgressRing.Visibility = Visibility.Collapsed; UIExecutionProgressRing.IsActive = false; }
/// <summary> /// Evaluate the specified ConceptTaggerBinding and update the specified ResultItem with the outcome /// </summary> /// <param name="binding"></param> /// <param name="resultItem"></param> /// <returns></returns> private async Task EvaluateBinding(ConceptTaggerBinding binding, ResultItemUserControl resultItem) { // Take a lock for using a skill if one is available, or wait if not m_evaluationLock.Wait(); ConceptTaggerSkill skill = null; try { if (!m_skillQueue.TryDequeue(out skill)) { throw new Exception("Could not access skill"); } var baseTime = (float)m_perfWatch.ElapsedTicks / Stopwatch.Frequency * 1000f; // Evaluate binding await skill.EvaluateAsync(binding); // Record evaluation time for display resultItem.EvalTime = (float)m_perfWatch.ElapsedTicks / Stopwatch.Frequency * 1000f - baseTime; m_skillQueue.Enqueue(skill); m_evaluationLock.Release(); } catch (Exception ex) { NotifyUser(ex.Message, NotifyType.ErrorMessage); if (binding != null) { m_bindingQueue.Enqueue(binding); } m_bindingLock.Release(); if (skill != null) { m_skillQueue.Enqueue(skill); } m_evaluationLock.Release(); return; } m_imageProcessedCount++; // Attempt to obtain top 5 concept tags identified in image that scored a confidence of above 0.7 var result = binding.GetTopXTagsAboveThreshold(m_topX, (float)m_threshold); m_bindingQueue.Enqueue(binding); m_bindingLock.Release(); if (result != null) { foreach (var conceptTag in result) { m_hashTags.Add(conceptTag); } } // Display image and results await UIResultPanel.Dispatcher.RunAsync( CoreDispatcherPriority.Normal, () => { resultItem.UpdateResultItemScore(result); UITotalTime.Content = $"{((float)m_perfWatch.ElapsedTicks / Stopwatch.Frequency - m_e2eRunTime)}s"; UIProgressTick.Text = m_imageProcessedCount.ToString(); // Refresh the set of hashtag filters in the UI if we reached the end if (m_imageProcessedCount == m_imageToProcessTotal) { UIHashTagBrowser.ItemsSource = null; UIHashTagBrowser.ItemsSource = m_hashTags; } }); }