polish autodetection

This commit is contained in:
Alex Bezdieniezhnykh
2024-11-02 20:59:51 +02:00
parent 418a2116b7
commit addf7ccc11
6 changed files with 90 additions and 27 deletions
+7 -8
View File
@@ -3,27 +3,26 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:extensions="clr-namespace:Azaion.Annotator.Extensions"
mc:Ignorable="d" mc:Ignorable="d"
WindowStyle="SingleBorderWindow" WindowStyle="SingleBorderWindow"
ResizeMode="NoResize" ResizeMode="NoResize"
Title="AutodetectDialog" Title="Розпізнавання"
Height="250" Width="420" Height="247" Width="400"
Background="LightGray"> Background="LightGray">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="40"></RowDefinition>
<RowDefinition Height="*"></RowDefinition> <RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="70"></RowDefinition> <RowDefinition Height="70"></RowDefinition>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Grid.Row="0" <ScrollViewer Grid.Row="0"
FontSize="18" TextAlignment="Center" Padding="0 10 0 0">Йде розпізнавання...</TextBlock> extensions:ScrollViewerExtensions.AlwaysScrollToEnd="True">
<ScrollViewer Grid.Row="1">
<TextBlock <TextBlock
Name="TextBlockLog" Name="TextBlockLog"
Padding="10 10 5 5"/> Padding="10 10 5 5"/>
</ScrollViewer> </ScrollViewer>
<Button Grid.Row="2" <Button Grid.Row="1"
Width="50" Height="50" ToolTip="Видалити всі аннотації. Клавіша: [X]" Width="50" Height="50" ToolTip="Зупинити розпізнавання. [Esc]"
Background="LightGray" BorderBrush="LightGray" Background="LightGray" BorderBrush="LightGray"
Click="ButtonBase_OnClick"> Click="ButtonBase_OnClick">
<Path Stretch="Fill" Fill="Gray" Data="M12,2 C17.5228,2 22,6.47715 22,12 C22,17.5228 17.5228,22 12,22 C6.47715,22 2,17.5228 2,12 C2,6.47715 6.47715,2 12,2 Z <Path Stretch="Fill" Fill="Gray" Data="M12,2 C17.5228,2 22,6.47715 22,12 C22,17.5228 17.5228,22 12,22 C6.47715,22 2,17.5228 2,12 C2,6.47715 6.47715,2 12,2 Z
+7 -4
View File
@@ -1,4 +1,5 @@
using System.Windows; using System.Windows;
using System.Windows.Input;
namespace Azaion.Annotator; namespace Azaion.Annotator;
@@ -7,13 +8,15 @@ public partial class AutodetectDialog : Window
public AutodetectDialog() public AutodetectDialog()
{ {
InitializeComponent(); InitializeComponent();
KeyUp += (sender, args) =>
{
if (args.Key == Key.Escape)
Close();
};
} }
public void Log(string message) => public void Log(string message) =>
TextBlockLog.Text = TextBlockLog.Text + Environment.NewLine + message; TextBlockLog.Text = TextBlockLog.Text + Environment.NewLine + message;
private void ButtonBase_OnClick(object sender, RoutedEventArgs e) private void ButtonBase_OnClick(object sender, RoutedEventArgs e) => Close();
{
Close();
}
} }
@@ -26,6 +26,7 @@ public class AnnotationControl : Border
set set
{ {
_grid.Background = value.ColorBrush; _grid.Background = value.ColorBrush;
_probabilityLabel.Background = value.ColorBrush;
_classNameLabel.Text = value.Name; _classNameLabel.Text = value.Name;
_annotationClass = value; _annotationClass = value;
} }
@@ -59,10 +60,12 @@ public class AnnotationControl : Border
}; };
_probabilityLabel = new Label _probabilityLabel = new Label
{ {
Content = probability?.ToString("F1") ?? string.Empty, Content = probability.HasValue ? $"{probability.Value:F0}%" : string.Empty,
HorizontalAlignment = HorizontalAlignment.Right, HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Top, VerticalAlignment = VerticalAlignment.Top,
Margin = new Thickness(0, -15, 0, 0), Margin = new Thickness(0, -32, 0, 0),
FontSize = 16,
Visibility = Visibility.Visible
}; };
_selectionFrame = new Rectangle _selectionFrame = new Rectangle
{ {
@@ -81,6 +84,7 @@ public class AnnotationControl : Border
{ {
_selectionFrame, _selectionFrame,
_classNameLabel, _classNameLabel,
_probabilityLabel,
AddRect("rLT", HorizontalAlignment.Left, VerticalAlignment.Top, Cursors.SizeNWSE), AddRect("rLT", HorizontalAlignment.Left, VerticalAlignment.Top, Cursors.SizeNWSE),
AddRect("rCT", HorizontalAlignment.Center, VerticalAlignment.Top, Cursors.SizeNS), AddRect("rCT", HorizontalAlignment.Center, VerticalAlignment.Top, Cursors.SizeNS),
AddRect("rRT", HorizontalAlignment.Right, VerticalAlignment.Top, Cursors.SizeNESW), AddRect("rRT", HorizontalAlignment.Right, VerticalAlignment.Top, Cursors.SizeNESW),
@@ -0,0 +1,54 @@
using System.Windows;
using System.Windows.Controls;
namespace Azaion.Annotator.Extensions;
public class ScrollViewerExtensions
{
public static readonly DependencyProperty AlwaysScrollToEndProperty =
DependencyProperty.RegisterAttached("AlwaysScrollToEnd", typeof(bool), typeof(ScrollViewerExtensions), new PropertyMetadata(false, AlwaysScrollToEndChanged));
private static bool _autoScroll;
private static void AlwaysScrollToEndChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (sender is not ScrollViewer scroll)
throw new InvalidOperationException("The attached AlwaysScrollToEnd property can only be applied to ScrollViewer instances.");
var alwaysScrollToEnd = e.NewValue != null && (bool)e.NewValue;
if (alwaysScrollToEnd)
{
scroll.ScrollToEnd();
scroll.ScrollChanged += ScrollChanged;
}
else
scroll.ScrollChanged -= ScrollChanged;
}
public static bool GetAlwaysScrollToEnd(ScrollViewer scroll)
{
if (scroll == null)
throw new ArgumentNullException("scroll");
return (bool)scroll.GetValue(AlwaysScrollToEndProperty);
}
public static void SetAlwaysScrollToEnd(ScrollViewer scroll, bool alwaysScrollToEnd)
{
if (scroll == null)
throw new ArgumentNullException("scroll");
scroll.SetValue(AlwaysScrollToEndProperty, alwaysScrollToEnd);
}
private static void ScrollChanged(object sender, ScrollChangedEventArgs e)
{
var scroll = sender as ScrollViewer;
if (scroll == null)
throw new InvalidOperationException("The attached AlwaysScrollToEnd property can only be applied to ScrollViewer instances.");
if (e.ExtentHeightChange == 0)
_autoScroll = scroll.VerticalOffset == scroll.ScrollableHeight;
if (_autoScroll && e.ExtentHeightChange != 0)
scroll.ScrollToVerticalOffset(scroll.ExtentHeight);
}
}
@@ -47,11 +47,6 @@ public class VLCFrameExtractor(LibVLC libVLC)
_width = videoTrack.Data.Video.Width; _width = videoTrack.Data.Video.Width;
_height = videoTrack.Data.Video.Height; _height = videoTrack.Data.Video.Height;
//rescaling to DEFAULT_WIDTH
//TODO: probably rescaling is not necessary, should be checked
//_width = DEFAULT_WIDTH;
//_height = (uint)(DEFAULT_WIDTH * _height / (double)_width);
_pitch = Align32(_width * RGBA_BYTES); _pitch = Align32(_width * RGBA_BYTES);
_lines = Align32(_height); _lines = Align32(_height);
_mediaPlayer.SetRate(PLAYBACK_RATE); _mediaPlayer.SetRate(PLAYBACK_RATE);
@@ -81,7 +76,6 @@ public class VLCFrameExtractor(LibVLC libVLC)
yield return (frameInfo.Time, ms); yield return (frameInfo.Time, ms);
Console.WriteLine($"Queue size: {FramesQueue.Count}");
frameInfo.Bitmap?.Dispose(); frameInfo.Bitmap?.Dispose();
} }
else else
+13 -4
View File
@@ -489,9 +489,10 @@ public partial class MainWindow
return; return;
_mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.Play)); _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.Play));
_mediaPlayer.SetPause(true);
var mediaInfo = (MediaFileInfo)LvFiles.SelectedItem; var mediaInfo = (MediaFileInfo)LvFiles.SelectedItem;
_formState.CurrentMedia = mediaInfo; _formState.CurrentMedia = mediaInfo;
_mediaPlayer.Stop();
var path = mediaInfo.Path; var path = mediaInfo.Path;
var manualCancellationSource = new CancellationTokenSource(); var manualCancellationSource = new CancellationTokenSource();
@@ -505,20 +506,28 @@ public partial class MainWindow
_autoDetectDialog.Closing += (_, _) => _autoDetectDialog.Closing += (_, _) =>
{ {
manualCancellationSource.Cancel(); manualCancellationSource.Cancel();
_mediaPlayer.Stop(); _mediaPlayer.SeekTo(TimeSpan.Zero);
Editor.RemoveAllAnns();
}; };
_autoDetectDialog.Top = Height - _autoDetectDialog.Height - 80; _autoDetectDialog.Top = Height - _autoDetectDialog.Height - 80;
_autoDetectDialog.Left = 5;
_ = Task.Run(async () => _ = Task.Run(async () =>
{ {
using var detector = new YOLODetector(_config); using var detector = new YOLODetector(_config);
Dispatcher.Invoke(() => _autoDetectDialog.Log("Ініціалізація AI...")); Dispatcher.Invoke(() => _autoDetectDialog.Log("Ініціалізація AI..."));
var prevSeekTime = 0.0;
await foreach (var timeframe in _vlcFrameExtractor.ExtractFrames(path, token)) await foreach (var timeframe in _vlcFrameExtractor.ExtractFrames(path, token))
{ {
try try
{ {
var detections = _aiDetector.Detect(timeframe.Stream); var detections = _aiDetector.Detect(timeframe.Stream);
if (timeframe.Time.TotalSeconds > prevSeekTime + 1)
{
Dispatcher.Invoke(() => SeekTo(timeframe.Time));
prevSeekTime = timeframe.Time.TotalSeconds;
}
if (!IsValidDetection(timeframe.Time, detections)) if (!IsValidDetection(timeframe.Time, detections))
continue; continue;
@@ -533,9 +542,8 @@ public partial class MainWindow
} }
_autoDetectDialog.Close(); _autoDetectDialog.Close();
}, token); }, token);
_autoDetectDialog.ShowDialog(); _autoDetectDialog.ShowDialog();
Dispatcher.Invoke(() => Editor.Background = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0))); Dispatcher.Invoke(() => Editor.Background = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0)));
} }
@@ -613,6 +621,7 @@ public partial class MainWindow
$"xy=({det.Label.CenterX:F2},{det.Label.CenterY:F2}), " + $"xy=({det.Label.CenterX:F2},{det.Label.CenterY:F2}), " +
$"size=({det.Label.Width:F2}, {det.Label.Height:F2}), " + $"size=({det.Label.Width:F2}, {det.Label.Height:F2}), " +
$"prob: {det.Probability:F1}%")); $"prob: {det.Probability:F1}%"));
Dispatcher.Invoke(() => _autoDetectDialog.Log(log)); Dispatcher.Invoke(() => _autoDetectDialog.Log(log));
var thumbnailDto = await _galleryManager.CreateThumbnail(imgPath, token); var thumbnailDto = await _galleryManager.CreateThumbnail(imgPath, token);