add db WIP 2, 80%

refactor, renames
This commit is contained in:
Alex Bezdieniezhnykh
2024-12-24 06:07:13 +02:00
parent 5fa18aa514
commit 48c9ccbfda
32 changed files with 499 additions and 459 deletions
+43 -37
View File
@@ -1,6 +1,5 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.IO;
using System.Windows;
using System.Windows.Controls;
@@ -8,13 +7,14 @@ using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Azaion.Annotator.DTO;
using Azaion.Annotator.Extensions;
using Azaion.Common;
using Azaion.Common.DTO;
using Azaion.Common.DTO.Config;
using Azaion.Common.DTO.Queue;
using Azaion.Common.Extensions;
using Azaion.Common.Services;
using LibVLCSharp.Shared;
using MediatR;
using Microsoft.WindowsAPICodePack.Dialogs;
@@ -40,9 +40,10 @@ public partial class Annotator
private readonly ILogger<Annotator> _logger;
private readonly VLCFrameExtractor _vlcFrameExtractor;
private readonly IAIDetector _aiDetector;
private readonly AnnotationService _annotationService;
private readonly CancellationTokenSource _cancellationTokenSource = new();
private ObservableCollection<AnnotationClass> AnnotationClasses { get; set; } = new();
private ObservableCollection<DetectionClass> AnnotationClasses { get; set; } = new();
private bool _suspendLayout;
private readonly TimeSpan _thresholdBefore = TimeSpan.FromMilliseconds(100);
@@ -52,7 +53,7 @@ public partial class Annotator
private ObservableCollection<MediaFileInfo> AllMediaFiles { get; set; } = new();
private ObservableCollection<MediaFileInfo> FilteredMediaFiles { get; set; } = new();
public IntervalTree<TimeSpan, List<YoloLabel>> Annotations { get; set; } = new();
public IntervalTree<TimeSpan, List<Detection>> Detections { get; set; } = new();
private AutodetectDialog _autoDetectDialog = new() { Topmost = true };
public Annotator(
@@ -64,7 +65,8 @@ public partial class Annotator
HelpWindow helpWindow,
ILogger<Annotator> logger,
VLCFrameExtractor vlcFrameExtractor,
IAIDetector aiDetector)
IAIDetector aiDetector,
AnnotationService annotationService)
{
InitializeComponent();
_appConfig = appConfig.Value;
@@ -77,6 +79,7 @@ public partial class Annotator
_logger = logger;
_vlcFrameExtractor = vlcFrameExtractor;
_aiDetector = aiDetector;
_annotationService = annotationService;
Loaded += OnLoaded;
Closed += OnFormClosed;
@@ -98,7 +101,7 @@ public partial class Annotator
ReloadFiles();
AnnotationClasses = new ObservableCollection<AnnotationClass>(_appConfig.AnnotationConfig.AnnotationClasses);
AnnotationClasses = new ObservableCollection<DetectionClass>(_appConfig.AnnotationConfig.AnnotationClasses);
LvClasses.ItemsSource = AnnotationClasses;
LvClasses.SelectedIndex = 0;
@@ -152,7 +155,7 @@ public partial class Annotator
LvClasses.SelectionChanged += (_, _) =>
{
var selectedClass = (AnnotationClass)LvClasses.SelectedItem;
var selectedClass = (DetectionClass)LvClasses.SelectedItem;
Editor.CurrentAnnClass = selectedClass;
_mediator.Publish(new AnnClassSelectedEvent(selectedClass));
};
@@ -188,7 +191,7 @@ public partial class Annotator
OpenAnnotationResult((AnnotationResult)DgAnnotations.SelectedItem);
break;
case Key.Delete:
var result = MessageBox.Show(Application.Current.MainWindow, "Чи дійсно видалити аннотації?","Підтвердження видалення", MessageBoxButton.OKCancel, MessageBoxImage.Question);
var result = MessageBox.Show("Чи дійсно видалити аннотації?","Підтвердження видалення", MessageBoxButton.OKCancel, MessageBoxImage.Question);
if (result != MessageBoxResult.OK)
return;
@@ -202,7 +205,7 @@ public partial class Annotator
File.Delete(Path.Combine(_appConfig.DirectoriesConfig.LabelsDirectory, $"{imgName}.txt"));
File.Delete(thumbnailPath);
_formState.AnnotationResults.Remove(annotationResult);
Annotations.Remove(Annotations.Query(annotationResult.Time));
Detections.Remove(Detections.Query(annotationResult.Time));
}
break;
}
@@ -251,7 +254,7 @@ public partial class Annotator
Editor.ClearExpiredAnnotations(time);
});
var annotations = Annotations.Query(time).SelectMany(x => x).Select(x => new Detection(x));
var annotations = Detections.Query(time).SelectMany(x => x).Select(x => new Detection(_formState.GetTimeName(time), x));
AddAnnotationsToCanvas(time, annotations);
}
@@ -285,7 +288,7 @@ public partial class Annotator
private async Task ReloadAnnotations(CancellationToken ct = default)
{
_formState.AnnotationResults.Clear();
Annotations.Clear();
Detections.Clear();
Editor.RemoveAllAnns();
var labelDir = new DirectoryInfo(_appConfig.DirectoriesConfig.LabelsDirectory);
@@ -294,22 +297,21 @@ public partial class Annotator
var labelFiles = labelDir.GetFiles($"{_formState.VideoName}_??????.txt");
foreach (var file in labelFiles)
{
var name = Path.GetFileNameWithoutExtension(file.Name);
var time = Constants.GetTime(name);
await AddAnnotations(time, await YoloLabel.ReadFromFile(file.FullName, ct), ct);
}
await AddAnnotations(Path.GetFileNameWithoutExtension(file.Name), await YoloLabel.ReadFromFile(file.FullName, ct), ct);
}
public async Task AddAnnotations(TimeSpan? time, List<YoloLabel> annotations, CancellationToken ct = default)
=> await AddAnnotations(time, annotations.Select(x => new Detection(x)).ToList(), ct);
//Load from yolo label file
public async Task AddAnnotations(string name, List<YoloLabel> annotations, CancellationToken ct = default)
=> await AddAnnotations(name, annotations.Select(x => new Detection(name, x)).ToList(), ct);
public async Task AddAnnotations(TimeSpan? time, List<Detection> detections, CancellationToken ct = default)
//Add manually
public async Task AddAnnotations(string name, List<Detection> detections, CancellationToken ct = default)
{
var time = Constants.GetTime(name);
var timeValue = time ?? TimeSpan.FromMinutes(0);
var previousAnnotations = Annotations.Query(timeValue);
Annotations.Remove(previousAnnotations);
Annotations.Add(timeValue.Subtract(_thresholdBefore), timeValue.Add(_thresholdAfter), detections.Cast<YoloLabel>().ToList());
var previousAnnotations = Detections.Query(timeValue);
Detections.Remove(previousAnnotations);
Detections.Add(timeValue.Subtract(_thresholdBefore), timeValue.Add(_thresholdAfter), detections);
var existingResult = _formState.AnnotationResults.FirstOrDefault(x => x.Time == time);
if (existingResult != null)
@@ -345,15 +347,15 @@ public partial class Annotator
return (-1).ToColor();
return colorNumber >= detectionClasses.Count
? _appConfig.AnnotationConfig.AnnotationClassesDict[detectionClasses.LastOrDefault()].Color
: _appConfig.AnnotationConfig.AnnotationClassesDict[detectionClasses[colorNumber]].Color;
? _appConfig.AnnotationConfig.DetectionClassesDict[detectionClasses.LastOrDefault()].Color
: _appConfig.AnnotationConfig.DetectionClassesDict[detectionClasses[colorNumber]].Color;
}
var detectionClasses = detections.Select(x => x.ClassNumber).Distinct().ToList();
annotationResult.ClassName = detectionClasses.Count > 1
? string.Join(", ", detectionClasses.Select(x => _appConfig.AnnotationConfig.AnnotationClassesDict[x].ShortName))
: _appConfig.AnnotationConfig.AnnotationClassesDict[detectionClasses.FirstOrDefault()].Name;
? string.Join(", ", detectionClasses.Select(x => _appConfig.AnnotationConfig.DetectionClassesDict[x].ShortName))
: _appConfig.AnnotationConfig.DetectionClassesDict[detectionClasses.FirstOrDefault()].Name;
annotationResult.ClassColor0 = GetAnnotationClass(detectionClasses, 0);
annotationResult.ClassColor1 = GetAnnotationClass(detectionClasses, 1);
@@ -442,8 +444,8 @@ public partial class Annotator
// private void AddClassBtnClick(object sender, RoutedEventArgs e)
// {
// LvClasses.IsReadOnly = false;
// AnnotationClasses.Add(new AnnotationClass(AnnotationClasses.Count));
// LvClasses.SelectedIndex = AnnotationClasses.Count - 1;
// DetectionClasses.Add(new DetectionClass(DetectionClasses.Count));
// LvClasses.SelectedIndex = DetectionClasses.Count - 1;
// }
private async void OpenFolderItemClick(object sender, RoutedEventArgs e) => await OpenFolder();
private async void OpenFolderButtonClick(object sender, RoutedEventArgs e) => await OpenFolder();
@@ -578,9 +580,10 @@ public partial class Annotator
{
try
{
var fName = Path.GetFileNameWithoutExtension(mediaInfo.Path);
var stream = new FileStream(mediaInfo.Path, FileMode.Open);
var detections = await _aiDetector.Detect(stream, token);
await ProcessDetection((TimeSpan.FromMilliseconds(0), stream), detections, token);
var detections = await _aiDetector.Detect(fName, stream, token);
await ProcessDetection((TimeSpan.FromMilliseconds(0), stream), Path.GetExtension(mediaInfo.Path), detections, token);
if (detections.Count != 0)
mediaInfo.HasAnnotations = true;
}
@@ -599,7 +602,8 @@ public partial class Annotator
Console.WriteLine($"Detect time: {timeframe.Time}");
try
{
var detections = await _aiDetector.Detect(timeframe.Stream, token);
var fName = _formState.GetTimeName(timeframe.Time);
var detections = await _aiDetector.Detect(fName, timeframe.Stream, token);
var isValid = IsValidDetection(timeframe.Time, detections);
if (timeframe.Time.TotalSeconds > prevSeekTime + 1)
@@ -628,7 +632,7 @@ public partial class Annotator
continue;
mediaInfo.HasAnnotations = true;
await ProcessDetection(timeframe, detections, token);
await ProcessDetection(timeframe, "jpg", detections, token);
}
catch (Exception ex)
{
@@ -685,7 +689,7 @@ public partial class Annotator
return false;
}
private async Task ProcessDetection((TimeSpan Time, Stream Stream) timeframe, List<Detection> detections, CancellationToken token = default)
private async Task ProcessDetection((TimeSpan Time, Stream Stream) timeframe, string imageExtension, List<Detection> detections, CancellationToken token = default)
{
_previousDetection = (timeframe.Time, detections);
await Dispatcher.Invoke(async () =>
@@ -695,22 +699,24 @@ public partial class Annotator
var time = timeframe.Time;
var fName = _formState.GetTimeName(timeframe.Time);
var imgPath = Path.Combine(_appConfig.DirectoriesConfig.ImagesDirectory, $"{fName}.jpg");
var imgPath = Path.Combine(_appConfig.DirectoriesConfig.ImagesDirectory, $"{fName}.{imageExtension}");
Editor.Background = new ImageBrush { ImageSource = await imgPath.OpenImage() };
Editor.RemoveAllAnns();
AddAnnotationsToCanvas(time, detections, true);
await AddAnnotations(timeframe.Time, detections, token);
await AddAnnotations(fName, detections, token);
await _annotationService.SaveAnnotation(fName, imageExtension, detections, SourceEnum.AI, timeframe.Stream, token);
var log = string.Join(Environment.NewLine, detections.Select(det =>
$"{_appConfig.AnnotationConfig.AnnotationClassesDict[det.ClassNumber].Name}: " +
$"{_appConfig.AnnotationConfig.DetectionClassesDict[det.ClassNumber].Name}: " +
$"xy=({det.CenterX:F2},{det.CenterY:F2}), " +
$"size=({det.Width:F2}, {det.Height:F2}), " +
$"prob: {det.Probability:F1}%"));
Dispatcher.Invoke(() => _autoDetectDialog.Log(log));
await _mediator.Publish(new ImageCreatedEvent(imgPath), token);
}
catch (Exception e)
{