mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 11:06:30 +00:00
remove fix, todo: test
This commit is contained in:
@@ -2,12 +2,11 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Azaion.Common;
|
||||
using Azaion.Common.Database;
|
||||
using Azaion.Common.DTO;
|
||||
using Azaion.Common.DTO.Config;
|
||||
using Azaion.Common.Events;
|
||||
using Azaion.Common.Services;
|
||||
using Azaion.CommonSecurity.Services;
|
||||
using LinqToDB;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -17,28 +16,28 @@ using Color = ScottPlot.Color;
|
||||
|
||||
namespace Azaion.Dataset;
|
||||
|
||||
public partial class DatasetExplorer : INotificationHandler<AnnotationCreatedEvent>
|
||||
public partial class DatasetExplorer : INotificationHandler<AnnotationCreatedEvent>, INotificationHandler<AnnotationsDeletedEvent>
|
||||
{
|
||||
private readonly ILogger<DatasetExplorer> _logger;
|
||||
private readonly AnnotationConfig _annotationConfig;
|
||||
private readonly DirectoriesConfig _directoriesConfig;
|
||||
|
||||
private Dictionary<int, List<Annotation>> _annotationsDict;
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
public ObservableCollection<AnnotationImageView> SelectedAnnotations { get; set; } = new();
|
||||
public ObservableCollection<DetectionClass> AllAnnotationClasses { get; set; } = new();
|
||||
public ObservableCollection<DetectionClass> AllDetectionClasses { get; set; } = new();
|
||||
public ObservableCollection<AnnotationThumbnail> SelectedAnnotations { get; set; } = new();
|
||||
|
||||
private Dictionary<string, LabelInfo> LabelsCache { get; set; } = new();
|
||||
|
||||
private int _tempSelectedClassIdx = 0;
|
||||
private readonly IGalleryService _galleryService;
|
||||
private readonly IDbFactory _dbFactory;
|
||||
private readonly IMediator _mediator;
|
||||
private readonly AzaionApiClient _apiClient;
|
||||
private readonly Dictionary<string, AnnotationThumbnail> _selectedAnnotationDict = new();
|
||||
|
||||
public bool ThumbnailLoading { get; set; }
|
||||
|
||||
public AnnotationImageView? CurrentAnnotation { get; set; }
|
||||
public AnnotationThumbnail? CurrentAnnotation { get; set; }
|
||||
|
||||
public DatasetExplorer(
|
||||
IOptions<DirectoriesConfig> directoriesConfig,
|
||||
@@ -47,8 +46,7 @@ public partial class DatasetExplorer : INotificationHandler<AnnotationCreatedEve
|
||||
IGalleryService galleryService,
|
||||
FormState formState,
|
||||
IDbFactory dbFactory,
|
||||
IMediator mediator,
|
||||
AzaionApiClient apiClient)
|
||||
IMediator mediator)
|
||||
{
|
||||
_directoriesConfig = directoriesConfig.Value;
|
||||
_annotationConfig = annotationConfig.Value;
|
||||
@@ -56,18 +54,17 @@ public partial class DatasetExplorer : INotificationHandler<AnnotationCreatedEve
|
||||
_galleryService = galleryService;
|
||||
_dbFactory = dbFactory;
|
||||
_mediator = mediator;
|
||||
_apiClient = apiClient;
|
||||
|
||||
InitializeComponent();
|
||||
Loaded += OnLoaded;
|
||||
Activated += (_, _) => formState.ActiveWindow = WindowEnum.DatasetExplorer;
|
||||
|
||||
ThumbnailsView.KeyDown += async (sender, args) =>
|
||||
ThumbnailsView.KeyDown += async (sender, args) =>
|
||||
{
|
||||
switch (args.Key)
|
||||
{
|
||||
case Key.Delete:
|
||||
DeleteAnnotations();
|
||||
await DeleteAnnotations();
|
||||
break;
|
||||
case Key.Enter:
|
||||
await EditAnnotation();
|
||||
@@ -79,19 +76,24 @@ public partial class DatasetExplorer : INotificationHandler<AnnotationCreatedEve
|
||||
ThumbnailsView.SelectionChanged += (_, _) =>
|
||||
{
|
||||
StatusText.Text = $"Обрано: {ThumbnailsView.SelectedItems.Count} | {ThumbnailsView.SelectedIndex} / {SelectedAnnotations.Count}";
|
||||
ValidateBtn.Visibility = ThumbnailsView.SelectedItems.Cast<AnnotationImageView>().Any(x => x.IsSeed)
|
||||
ValidateBtn.Visibility = ThumbnailsView.SelectedItems.Cast<AnnotationThumbnail>().Any(x => x.IsSeed)
|
||||
? Visibility.Visible
|
||||
: Visibility.Hidden;
|
||||
};
|
||||
ExplorerEditor.GetTimeFunc = () => Constants.GetTime(CurrentAnnotation!.Annotation.ImagePath);
|
||||
ExplorerEditor.GetTimeFunc = () => CurrentAnnotation!.Annotation.Time;
|
||||
_galleryService.ThumbnailsUpdate += thumbnailsPercentage =>
|
||||
{
|
||||
Dispatcher.Invoke(() => RefreshThumbBar.Value = thumbnailsPercentage);
|
||||
};
|
||||
Closing += (_, _) => _cts.Cancel();
|
||||
}
|
||||
|
||||
private async void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AllAnnotationClasses = new ObservableCollection<DetectionClass>(
|
||||
AllDetectionClasses = new ObservableCollection<DetectionClass>(
|
||||
new List<DetectionClass> { new() {Id = -1, Name = "All", ShortName = "All"}}
|
||||
.Concat(_annotationConfig.AnnotationClasses));
|
||||
LvClasses.ItemsSource = AllAnnotationClasses;
|
||||
LvClasses.ItemsSource = AllDetectionClasses;
|
||||
|
||||
LvClasses.MouseUp += async (_, _) =>
|
||||
{
|
||||
@@ -128,9 +130,10 @@ public partial class DatasetExplorer : INotificationHandler<AnnotationCreatedEve
|
||||
{
|
||||
var allAnnotations = await db.Annotations
|
||||
.LoadWith(x => x.Detections)
|
||||
.OrderByDescending(x => x.CreatedDate)
|
||||
.OrderBy(x => x.AnnotationStatus)
|
||||
.ThenByDescending(x => x.CreatedDate)
|
||||
.ToListAsync();
|
||||
_annotationsDict = AllAnnotationClasses.ToDictionary(x => x.Id, _ => new List<Annotation>());
|
||||
_annotationsDict = AllDetectionClasses.ToDictionary(x => x.Id, _ => new List<Annotation>());
|
||||
|
||||
foreach (var annotation in allAnnotations)
|
||||
AddAnnotationToDict(annotation);
|
||||
@@ -150,15 +153,14 @@ public partial class DatasetExplorer : INotificationHandler<AnnotationCreatedEve
|
||||
|
||||
private async Task LoadClassDistribution()
|
||||
{
|
||||
var data = LabelsCache
|
||||
.SelectMany(x => x.Value.Classes)
|
||||
.GroupBy(x => x)
|
||||
.Select(x => new
|
||||
var data = _annotationsDict
|
||||
.Where(x => x.Key != -1)
|
||||
.Select(gr => new
|
||||
{
|
||||
x.Key,
|
||||
_annotationConfig.DetectionClassesDict[x.Key].Name,
|
||||
_annotationConfig.DetectionClassesDict[x.Key].Color,
|
||||
ClassCount = x.Count()
|
||||
gr.Key,
|
||||
_annotationConfig.DetectionClassesDict[gr.Key].Name,
|
||||
_annotationConfig.DetectionClassesDict[gr.Key].Color,
|
||||
ClassCount = gr.Value.Count
|
||||
})
|
||||
.ToList();
|
||||
|
||||
@@ -191,14 +193,20 @@ public partial class DatasetExplorer : INotificationHandler<AnnotationCreatedEve
|
||||
ClassDistribution.Refresh();
|
||||
}
|
||||
|
||||
private void ReloadThumbnailsItemClick(object sender, RoutedEventArgs e)
|
||||
private async void RefreshThumbnailsBtnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RefreshThumbnailsButtonItem.Visibility = Visibility.Hidden;
|
||||
RefreshProgressBarItem.Visibility = Visibility.Visible;
|
||||
|
||||
var result = MessageBox.Show($"Видалити всі іконки і згенерувати нову базу іконок в {_directoriesConfig.ThumbnailsDirectory}?",
|
||||
"Підтвердження оновлення іконок", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
if (result != MessageBoxResult.Yes)
|
||||
return;
|
||||
_galleryService.ClearThumbnails();
|
||||
_galleryService.RefreshThumbnails();
|
||||
await _galleryService.ClearThumbnails();
|
||||
await _galleryService.RefreshThumbnails();
|
||||
|
||||
RefreshProgressBarItem.Visibility = Visibility.Hidden;
|
||||
RefreshThumbnailsButtonItem.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private async Task EditAnnotation()
|
||||
@@ -210,7 +218,7 @@ public partial class DatasetExplorer : INotificationHandler<AnnotationCreatedEve
|
||||
if (ThumbnailsView.SelectedItem == null)
|
||||
return;
|
||||
|
||||
CurrentAnnotation = (ThumbnailsView.SelectedItem as AnnotationImageView)!;
|
||||
CurrentAnnotation = (ThumbnailsView.SelectedItem as AnnotationThumbnail)!;
|
||||
var ann = CurrentAnnotation.Annotation;
|
||||
ExplorerEditor.Background = new ImageBrush
|
||||
{
|
||||
@@ -218,13 +226,13 @@ public partial class DatasetExplorer : INotificationHandler<AnnotationCreatedEve
|
||||
};
|
||||
SwitchTab(toEditor: true);
|
||||
|
||||
var time = Constants.GetTime(ann.ImagePath);
|
||||
var time = ann.Time;
|
||||
ExplorerEditor.RemoveAllAnns();
|
||||
foreach (var deetection in ann.Detections)
|
||||
{
|
||||
var annClass = _annotationConfig.DetectionClassesDict[deetection.ClassNumber];
|
||||
var canvasLabel = new CanvasLabel(deetection, ExplorerEditor.RenderSize, ExplorerEditor.RenderSize);
|
||||
ExplorerEditor.CreateAnnotation(annClass, time, canvasLabel);
|
||||
ExplorerEditor.CreateDetectionControl(annClass, time, canvasLabel);
|
||||
}
|
||||
|
||||
ThumbnailLoading = false;
|
||||
@@ -257,26 +265,23 @@ public partial class DatasetExplorer : INotificationHandler<AnnotationCreatedEve
|
||||
{
|
||||
AnnotationsTab.Visibility = Visibility.Visible;
|
||||
EditorTab.Visibility = Visibility.Collapsed;
|
||||
LvClasses.ItemsSource = AllAnnotationClasses;
|
||||
LvClasses.ItemsSource = AllDetectionClasses;
|
||||
LvClasses.SelectedIndex = _tempSelectedClassIdx;
|
||||
Switcher.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteAnnotations()
|
||||
private async Task DeleteAnnotations()
|
||||
{
|
||||
var tempSelected = ThumbnailsView.SelectedIndex;
|
||||
var result = MessageBox.Show("Чи дійсно видалити аннотації?","Підтвердження видалення", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
if (result != MessageBoxResult.Yes)
|
||||
return;
|
||||
|
||||
var selected = ThumbnailsView.SelectedItems.Count;
|
||||
for (var i = 0; i < selected; i++)
|
||||
{
|
||||
var dto = (ThumbnailsView.SelectedItems[0] as AnnotationImageView)!;
|
||||
dto.Delete();
|
||||
SelectedAnnotations.Remove(dto);
|
||||
}
|
||||
var annotations = ThumbnailsView.SelectedItems.Cast<AnnotationThumbnail>().Select(x => x.Annotation)
|
||||
.ToList();
|
||||
|
||||
await _mediator.Publish(new AnnotationsDeletedEvent(annotations));
|
||||
ThumbnailsView.SelectedIndex = Math.Min(SelectedAnnotations.Count, tempSelected);
|
||||
}
|
||||
|
||||
@@ -284,7 +289,11 @@ public partial class DatasetExplorer : INotificationHandler<AnnotationCreatedEve
|
||||
{
|
||||
SelectedAnnotations.Clear();
|
||||
foreach (var ann in _annotationsDict[ExplorerEditor.CurrentAnnClass.Id])
|
||||
SelectedAnnotations.Add(new AnnotationImageView(ann));
|
||||
{
|
||||
var annThumb = new AnnotationThumbnail(ann);
|
||||
SelectedAnnotations.Add(annThumb);
|
||||
_selectedAnnotationDict.Add(annThumb.Annotation.Name, annThumb);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Handle(AnnotationCreatedEvent notification, CancellationToken cancellationToken)
|
||||
@@ -298,15 +307,36 @@ public partial class DatasetExplorer : INotificationHandler<AnnotationCreatedEve
|
||||
AddAnnotationToDict(annotation);
|
||||
if (annotation.Classes.Contains(selectedClass.Value))
|
||||
{
|
||||
SelectedAnnotations.Add(new AnnotationImageView(annotation));
|
||||
var annThumb = new AnnotationThumbnail(annotation);
|
||||
SelectedAnnotations.Add(annThumb);
|
||||
_selectedAnnotationDict.Add(annThumb.Annotation.Name, annThumb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async Task Handle(AnnotationsDeletedEvent notification, CancellationToken cancellationToken)
|
||||
{
|
||||
var names = notification.Annotations.Select(x => x.Name).ToList();
|
||||
var annThumbs = _selectedAnnotationDict
|
||||
.Where(x => names.Contains(x.Key))
|
||||
.Select(x => x.Value)
|
||||
.ToList();
|
||||
foreach (var annThumb in annThumbs)
|
||||
{
|
||||
SelectedAnnotations.Remove(annThumb);
|
||||
_selectedAnnotationDict.Remove(annThumb.Annotation.Name);
|
||||
}
|
||||
}
|
||||
|
||||
private async void ValidateAnnotationsClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var result = MessageBox.Show("Підтверджуєте валідність обраних аннотацій?","Підтвердження валідності", MessageBoxButton.OKCancel, MessageBoxImage.Question);
|
||||
if (result != MessageBoxResult.OK)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
await _mediator.Publish(new DatasetExplorerControlEvent(PlaybackControlEnum.ValidateAnnotations));
|
||||
await _mediator.Publish(new DatasetExplorerControlEvent(PlaybackControlEnum.ValidateAnnotations), _cts.Token);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user