mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 22:46:30 +00:00
polish autodetection
This commit is contained in:
@@ -3,27 +3,26 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:extensions="clr-namespace:Azaion.Annotator.Extensions"
|
||||
mc:Ignorable="d"
|
||||
WindowStyle="SingleBorderWindow"
|
||||
ResizeMode="NoResize"
|
||||
Title="AutodetectDialog"
|
||||
Height="250" Width="420"
|
||||
Title="Розпізнавання"
|
||||
Height="247" Width="400"
|
||||
Background="LightGray">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="40"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="70"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0"
|
||||
FontSize="18" TextAlignment="Center" Padding="0 10 0 0">Йде розпізнавання...</TextBlock>
|
||||
<ScrollViewer Grid.Row="1">
|
||||
<TextBlock
|
||||
Name="TextBlockLog"
|
||||
Padding="10 10 5 5"/>
|
||||
<ScrollViewer Grid.Row="0"
|
||||
extensions:ScrollViewerExtensions.AlwaysScrollToEnd="True">
|
||||
<TextBlock
|
||||
Name="TextBlockLog"
|
||||
Padding="10 10 5 5"/>
|
||||
</ScrollViewer>
|
||||
<Button Grid.Row="2"
|
||||
Width="50" Height="50" ToolTip="Видалити всі аннотації. Клавіша: [X]"
|
||||
<Button Grid.Row="1"
|
||||
Width="50" Height="50" ToolTip="Зупинити розпізнавання. [Esc]"
|
||||
Background="LightGray" BorderBrush="LightGray"
|
||||
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
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Azaion.Annotator;
|
||||
|
||||
@@ -7,13 +8,15 @@ public partial class AutodetectDialog : Window
|
||||
public AutodetectDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
KeyUp += (sender, args) =>
|
||||
{
|
||||
if (args.Key == Key.Escape)
|
||||
Close();
|
||||
};
|
||||
}
|
||||
|
||||
public void Log(string message) =>
|
||||
TextBlockLog.Text = TextBlockLog.Text + Environment.NewLine + message;
|
||||
|
||||
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
private void ButtonBase_OnClick(object sender, RoutedEventArgs e) => Close();
|
||||
}
|
||||
@@ -26,6 +26,7 @@ public class AnnotationControl : Border
|
||||
set
|
||||
{
|
||||
_grid.Background = value.ColorBrush;
|
||||
_probabilityLabel.Background = value.ColorBrush;
|
||||
_classNameLabel.Text = value.Name;
|
||||
_annotationClass = value;
|
||||
}
|
||||
@@ -59,10 +60,12 @@ public class AnnotationControl : Border
|
||||
};
|
||||
_probabilityLabel = new Label
|
||||
{
|
||||
Content = probability?.ToString("F1") ?? string.Empty,
|
||||
Content = probability.HasValue ? $"{probability.Value:F0}%" : string.Empty,
|
||||
HorizontalAlignment = HorizontalAlignment.Right,
|
||||
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
|
||||
{
|
||||
@@ -81,6 +84,7 @@ public class AnnotationControl : Border
|
||||
{
|
||||
_selectionFrame,
|
||||
_classNameLabel,
|
||||
_probabilityLabel,
|
||||
AddRect("rLT", HorizontalAlignment.Left, VerticalAlignment.Top, Cursors.SizeNWSE),
|
||||
AddRect("rCT", HorizontalAlignment.Center, VerticalAlignment.Top, Cursors.SizeNS),
|
||||
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;
|
||||
_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);
|
||||
_lines = Align32(_height);
|
||||
_mediaPlayer.SetRate(PLAYBACK_RATE);
|
||||
@@ -81,7 +76,6 @@ public class VLCFrameExtractor(LibVLC libVLC)
|
||||
|
||||
yield return (frameInfo.Time, ms);
|
||||
|
||||
Console.WriteLine($"Queue size: {FramesQueue.Count}");
|
||||
frameInfo.Bitmap?.Dispose();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -489,9 +489,10 @@ public partial class MainWindow
|
||||
return;
|
||||
|
||||
_mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.Play));
|
||||
_mediaPlayer.SetPause(true);
|
||||
|
||||
var mediaInfo = (MediaFileInfo)LvFiles.SelectedItem;
|
||||
_formState.CurrentMedia = mediaInfo;
|
||||
_mediaPlayer.Stop();
|
||||
var path = mediaInfo.Path;
|
||||
|
||||
var manualCancellationSource = new CancellationTokenSource();
|
||||
@@ -505,20 +506,28 @@ public partial class MainWindow
|
||||
_autoDetectDialog.Closing += (_, _) =>
|
||||
{
|
||||
manualCancellationSource.Cancel();
|
||||
_mediaPlayer.Stop();
|
||||
_mediaPlayer.SeekTo(TimeSpan.Zero);
|
||||
Editor.RemoveAllAnns();
|
||||
};
|
||||
_autoDetectDialog.Top = Height - _autoDetectDialog.Height - 80;
|
||||
_autoDetectDialog.Left = 5;
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
using var detector = new YOLODetector(_config);
|
||||
Dispatcher.Invoke(() => _autoDetectDialog.Log("Ініціалізація AI..."));
|
||||
var prevSeekTime = 0.0;
|
||||
|
||||
await foreach (var timeframe in _vlcFrameExtractor.ExtractFrames(path, token))
|
||||
{
|
||||
try
|
||||
{
|
||||
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))
|
||||
continue;
|
||||
@@ -533,9 +542,8 @@ public partial class MainWindow
|
||||
}
|
||||
_autoDetectDialog.Close();
|
||||
}, token);
|
||||
|
||||
|
||||
_autoDetectDialog.ShowDialog();
|
||||
|
||||
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}), " +
|
||||
$"size=({det.Label.Width:F2}, {det.Label.Height:F2}), " +
|
||||
$"prob: {det.Probability:F1}%"));
|
||||
|
||||
Dispatcher.Invoke(() => _autoDetectDialog.Log(log));
|
||||
|
||||
var thumbnailDto = await _galleryManager.CreateThumbnail(imgPath, token);
|
||||
|
||||
Reference in New Issue
Block a user