mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 22:46:30 +00:00
fix editing annotation
This commit is contained in:
@@ -48,7 +48,7 @@ public partial class App : Application
|
|||||||
});
|
});
|
||||||
services.AddSingleton<IConfigRepository, FileConfigRepository>();
|
services.AddSingleton<IConfigRepository, FileConfigRepository>();
|
||||||
services.AddSingleton<Config>(sp => sp.GetRequiredService<IConfigRepository>().Get());
|
services.AddSingleton<Config>(sp => sp.GetRequiredService<IConfigRepository>().Get());
|
||||||
services.AddSingleton<PlayerControlHandler>();
|
services.AddSingleton<MainWindowEventHandler>();
|
||||||
})
|
})
|
||||||
.UseSerilog()
|
.UseSerilog()
|
||||||
.Build();
|
.Build();
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Resource>
|
</Resource>
|
||||||
<None Update="config.json">
|
<None Update="config.json">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public class Config
|
|||||||
public List<string> ImageFormats { get; set; }
|
public List<string> ImageFormats { get; set; }
|
||||||
|
|
||||||
public ThumbnailConfig ThumbnailConfig { get; set; }
|
public ThumbnailConfig ThumbnailConfig { get; set; }
|
||||||
|
public int? LastSelectedExplorerClass { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WindowConfig
|
public class WindowConfig
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ public class FormState
|
|||||||
|
|
||||||
public int CurrentVolume { get; set; } = 100;
|
public int CurrentVolume { get; set; } = 100;
|
||||||
public ObservableCollection<AnnotationResult> AnnotationResults { get; set; } = [];
|
public ObservableCollection<AnnotationResult> AnnotationResults { get; set; } = [];
|
||||||
|
public WindowsEnum ActiveWindow { get; set; }
|
||||||
|
|
||||||
public string GetTimeName(TimeSpan ts) => $"{VideoName}_{ts:hmmssf}";
|
public string GetTimeName(TimeSpan ts) => $"{VideoName}_{ts:hmmssf}";
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Azaion.Annotator.DTO;
|
||||||
|
|
||||||
|
public enum WindowsEnum
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Main = 10,
|
||||||
|
DatasetExplorer = 20
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
@@ -24,16 +25,23 @@ public partial class DatasetExplorer
|
|||||||
private readonly string _thumbnailsCacheFile;
|
private readonly string _thumbnailsCacheFile;
|
||||||
private IConfigRepository _configRepository;
|
private IConfigRepository _configRepository;
|
||||||
private readonly FormState _formState;
|
private readonly FormState _formState;
|
||||||
|
private readonly IGalleryManager _galleryManager;
|
||||||
private static Dictionary<string, List<int>> LabelsCache { get; set; } = new();
|
private static Dictionary<string, List<int>> LabelsCache { get; set; } = new();
|
||||||
|
|
||||||
public string CurrentImage { get; set; }
|
public ThumbnailDto? CurrentThumbnail { get; set; }
|
||||||
|
|
||||||
public DatasetExplorer(Config config, ILogger<DatasetExplorer> logger, IConfigRepository configRepository, FormState formState)
|
public DatasetExplorer(
|
||||||
|
Config config,
|
||||||
|
ILogger<DatasetExplorer> logger,
|
||||||
|
IConfigRepository configRepository,
|
||||||
|
FormState formState,
|
||||||
|
IGalleryManager galleryManager)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_configRepository = configRepository;
|
_configRepository = configRepository;
|
||||||
_formState = formState;
|
_formState = formState;
|
||||||
|
_galleryManager = galleryManager;
|
||||||
_thumbnailsCacheFile = Path.Combine(config.ThumbnailsDirectory, Config.ThumbnailsCacheFile);
|
_thumbnailsCacheFile = Path.Combine(config.ThumbnailsDirectory, Config.ThumbnailsCacheFile);
|
||||||
if (File.Exists(_thumbnailsCacheFile))
|
if (File.Exists(_thumbnailsCacheFile))
|
||||||
{
|
{
|
||||||
@@ -43,19 +51,45 @@ public partial class DatasetExplorer
|
|||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
DataContext = this;
|
DataContext = this;
|
||||||
Loaded += (_, _) =>
|
Loaded += async (_, _) =>
|
||||||
{
|
{
|
||||||
AllAnnotationClasses = new ObservableCollection<AnnotationClass>(
|
AllAnnotationClasses = new ObservableCollection<AnnotationClass>(
|
||||||
new List<AnnotationClass> { new(-1, "All") }
|
new List<AnnotationClass> { new(-1, "All") }
|
||||||
.Concat(_config.AnnotationClasses));
|
.Concat(_config.AnnotationClasses));
|
||||||
LvClasses.ItemsSource = AllAnnotationClasses;
|
LvClasses.ItemsSource = AllAnnotationClasses;
|
||||||
|
|
||||||
LvClasses.SelectionChanged += async (_, _) =>
|
LvClasses.MouseUp += async (_, _) =>
|
||||||
{
|
{
|
||||||
var selectedClass = (AnnotationClass)LvClasses.SelectedItem;
|
var selectedClass = (AnnotationClass)LvClasses.SelectedItem;
|
||||||
await SelectClass(selectedClass);
|
ExplorerEditor.CurrentAnnClass = selectedClass;
|
||||||
|
config.LastSelectedExplorerClass = selectedClass.Id;
|
||||||
|
|
||||||
|
if (Switcher.SelectedIndex == 0)
|
||||||
|
await ReloadThumbnails();
|
||||||
|
else
|
||||||
|
foreach (var ann in ExplorerEditor.CurrentAnns.Where(x => x.IsSelected))
|
||||||
|
ann.AnnotationClass = selectedClass;
|
||||||
};
|
};
|
||||||
LvClasses.SelectedIndex = 0;
|
|
||||||
|
LvClasses.SelectionChanged += (_, _) =>
|
||||||
|
{
|
||||||
|
if (Switcher.SelectedIndex != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var selectedClass = (AnnotationClass)LvClasses.SelectedItem;
|
||||||
|
if (selectedClass == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ExplorerEditor.CurrentAnnClass = selectedClass;
|
||||||
|
|
||||||
|
foreach (var ann in ExplorerEditor.CurrentAnns.Where(x => x.IsSelected))
|
||||||
|
ann.AnnotationClass = selectedClass;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
LvClasses.SelectedIndex = config.LastSelectedExplorerClass ?? 0;
|
||||||
|
ExplorerEditor.CurrentAnnClass = (AnnotationClass)LvClasses.SelectedItem;
|
||||||
|
await ReloadThumbnails();
|
||||||
|
|
||||||
SizeChanged += async (_, _) => await SaveUserSettings();
|
SizeChanged += async (_, _) => await SaveUserSettings();
|
||||||
LocationChanged += async (_, _) => await SaveUserSettings();
|
LocationChanged += async (_, _) => await SaveUserSettings();
|
||||||
@@ -68,7 +102,7 @@ public partial class DatasetExplorer
|
|||||||
Visibility = Visibility.Hidden;
|
Visibility = Visibility.Hidden;
|
||||||
};
|
};
|
||||||
|
|
||||||
ThumbnailsView.KeyDown += (sender, args) =>
|
ThumbnailsView.KeyDown += async (sender, args) =>
|
||||||
{
|
{
|
||||||
switch (args.Key)
|
switch (args.Key)
|
||||||
{
|
{
|
||||||
@@ -76,29 +110,15 @@ public partial class DatasetExplorer
|
|||||||
DeleteAnnotations();
|
DeleteAnnotations();
|
||||||
break;
|
break;
|
||||||
case Key.Enter:
|
case Key.Enter:
|
||||||
EditAnnotation();
|
await EditAnnotation();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ThumbnailsView.MouseDoubleClick += async (_, _) => await EditAnnotation();
|
ThumbnailsView.MouseDoubleClick += async (_, _) => await EditAnnotation();
|
||||||
|
|
||||||
ExplorerEditor.KeyDown += (_, args) =>
|
Activated += (_, _) => { _formState.ActiveWindow = WindowsEnum.DatasetExplorer; };
|
||||||
{
|
|
||||||
var key = args.Key;
|
|
||||||
var keyNumber = (int?)null;
|
|
||||||
|
|
||||||
if ((int)key >= (int)Key.D1 && (int)key <= (int)Key.D9)
|
ExplorerEditor.GetTimeFunc = () => _formState.GetTime(CurrentThumbnail!.ImagePath)!.Value;
|
||||||
keyNumber = key - Key.D1;
|
|
||||||
if ((int)key >= (int)Key.NumPad1 && (int)key <= (int)Key.NumPad9)
|
|
||||||
keyNumber = key - Key.NumPad1;
|
|
||||||
if (!keyNumber.HasValue)
|
|
||||||
return;
|
|
||||||
|
|
||||||
LvClasses.SelectedIndex = keyNumber.Value;
|
|
||||||
};
|
|
||||||
|
|
||||||
ExplorerEditor.GetTimeFunc = () => _formState.GetTime(CurrentImage!)!.Value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task EditAnnotation()
|
private async Task EditAnnotation()
|
||||||
@@ -111,11 +131,12 @@ public partial class DatasetExplorer
|
|||||||
{
|
{
|
||||||
ImageSource = new BitmapImage(new Uri(dto.ImagePath))
|
ImageSource = new BitmapImage(new Uri(dto.ImagePath))
|
||||||
};
|
};
|
||||||
CurrentImage = dto.ImagePath;
|
CurrentThumbnail = dto;
|
||||||
|
|
||||||
Switcher.SelectedIndex = 1;
|
Switcher.SelectedIndex = 1;
|
||||||
LvClasses.SelectedIndex = 1;
|
LvClasses.SelectedIndex = 1;
|
||||||
|
|
||||||
var time = _formState.GetTime(CurrentImage)!.Value;
|
var time = _formState.GetTime(dto.ImagePath)!.Value;
|
||||||
foreach (var ann in await YoloLabel.ReadFromFile(dto.LabelPath))
|
foreach (var ann in await YoloLabel.ReadFromFile(dto.LabelPath))
|
||||||
{
|
{
|
||||||
var annClass = _config.AnnotationClasses[ann.ClassNumber];
|
var annClass = _config.AnnotationClasses[ann.ClassNumber];
|
||||||
@@ -123,33 +144,23 @@ public partial class DatasetExplorer
|
|||||||
Dispatcher.Invoke(() => ExplorerEditor.CreateAnnotation(annClass, time, annInfo));
|
Dispatcher.Invoke(() => ExplorerEditor.CreateAnnotation(annClass, time, annInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
Switcher.SelectionChanged += (_, args) =>
|
Switcher.SelectionChanged += (sender, args) =>
|
||||||
{
|
{
|
||||||
//From Explorer to Editor
|
|
||||||
if (Switcher.SelectedIndex == 1)
|
if (Switcher.SelectedIndex == 1)
|
||||||
{
|
{
|
||||||
|
//Editor
|
||||||
_tempSelectedClassIdx = LvClasses.SelectedIndex;
|
_tempSelectedClassIdx = LvClasses.SelectedIndex;
|
||||||
LvClasses.ItemsSource = _config.AnnotationClasses;
|
LvClasses.ItemsSource = _config.AnnotationClasses;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//Explorer
|
||||||
LvClasses.ItemsSource = AllAnnotationClasses;
|
LvClasses.ItemsSource = AllAnnotationClasses;
|
||||||
LvClasses.SelectedIndex = _tempSelectedClassIdx;
|
LvClasses.SelectedIndex = _tempSelectedClassIdx;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SelectClass(AnnotationClass annClass)
|
|
||||||
{
|
|
||||||
ExplorerEditor.CurrentAnnClass = annClass;
|
|
||||||
|
|
||||||
if (Switcher.SelectedIndex == 0)
|
|
||||||
await ReloadThumbnails();
|
|
||||||
else
|
|
||||||
foreach (var ann in ExplorerEditor.CurrentAnns.Where(x => x.IsSelected))
|
|
||||||
ann.AnnotationClass = annClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveUserSettings()
|
private async Task SaveUserSettings()
|
||||||
{
|
{
|
||||||
_config.DatasetExplorerConfig = this.GetConfig();
|
_config.DatasetExplorerConfig = this.GetConfig();
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using Azaion.Annotator.DTO;
|
||||||
|
using MediatR;
|
||||||
|
|
||||||
|
namespace Azaion.Annotator;
|
||||||
|
|
||||||
|
public class DatasetExplorerEventHandler(DatasetExplorer datasetExplorer,
|
||||||
|
Config config,
|
||||||
|
IGalleryManager galleryManager,
|
||||||
|
FormState formState) : INotificationHandler<KeyEvent>
|
||||||
|
{
|
||||||
|
private readonly Dictionary<Key, PlaybackControlEnum> _keysControlEnumDict = new()
|
||||||
|
{
|
||||||
|
{ Key.Enter, PlaybackControlEnum.SaveAnnotations },
|
||||||
|
{ Key.Delete, PlaybackControlEnum.RemoveSelectedAnns },
|
||||||
|
{ Key.X, PlaybackControlEnum.RemoveAllAnns }
|
||||||
|
};
|
||||||
|
|
||||||
|
public async Task Handle(KeyEvent keyEvent, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (formState.ActiveWindow != WindowsEnum.DatasetExplorer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var key = keyEvent.Args.Key;
|
||||||
|
var keyNumber = (int?)null;
|
||||||
|
|
||||||
|
if ((int)key >= (int)Key.D1 && (int)key <= (int)Key.D9) keyNumber = key - Key.D1;
|
||||||
|
if ((int)key >= (int)Key.NumPad1 && (int)key <= (int)Key.NumPad9) keyNumber = key - Key.NumPad1;
|
||||||
|
|
||||||
|
if (keyNumber.HasValue)
|
||||||
|
datasetExplorer.LvClasses.SelectedIndex = keyNumber.Value;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (datasetExplorer.Switcher.SelectedIndex == 1 && _keysControlEnumDict.TryGetValue(key, out var value))
|
||||||
|
await HandleControl(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleControl(PlaybackControlEnum controlEnum)
|
||||||
|
{
|
||||||
|
switch (controlEnum)
|
||||||
|
{
|
||||||
|
case PlaybackControlEnum.SaveAnnotations:
|
||||||
|
var currentAnns = datasetExplorer.ExplorerEditor.CurrentAnns
|
||||||
|
.Select(x => new YoloLabel(x.Info, datasetExplorer.ExplorerEditor.RenderSize, datasetExplorer.ExplorerEditor.RenderSize))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
await YoloLabel.WriteToFile(currentAnns, Path.Combine(config.LabelsDirectory, datasetExplorer.CurrentThumbnail!.LabelPath));
|
||||||
|
await galleryManager.CreateThumbnail(datasetExplorer.CurrentThumbnail.ImagePath);
|
||||||
|
|
||||||
|
datasetExplorer.Switcher.SelectedIndex = 0;
|
||||||
|
break;
|
||||||
|
case PlaybackControlEnum.RemoveSelectedAnns:
|
||||||
|
datasetExplorer.ExplorerEditor.RemoveSelectedAnns();
|
||||||
|
break;
|
||||||
|
case PlaybackControlEnum.RemoveAllAnns:
|
||||||
|
datasetExplorer.ExplorerEditor.RemoveAllAnns();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,9 +10,9 @@ public static class ThrottleExt
|
|||||||
|
|
||||||
_throttleOn = true;
|
_throttleOn = true;
|
||||||
await func();
|
await func();
|
||||||
_ = Task.Run(() =>
|
_ = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
Task.Delay(throttleTime ?? TimeSpan.FromMilliseconds(500));
|
await Task.Delay(throttleTime ?? TimeSpan.FromMilliseconds(500));
|
||||||
_throttleOn = false;
|
_throttleOn = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,16 +14,27 @@ public class GalleryManager(Config config, ILogger<GalleryManager> logger) : IGa
|
|||||||
public int ThumbnailsCount { get; set; }
|
public int ThumbnailsCount { get; set; }
|
||||||
public int ImagesCount { get; set; }
|
public int ImagesCount { get; set; }
|
||||||
|
|
||||||
public async Task RefreshThumbnails()
|
private DirectoryInfo? _thumbnailsDirectory;
|
||||||
|
private DirectoryInfo ThumbnailsDirectory
|
||||||
{
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_thumbnailsDirectory != null)
|
||||||
|
return _thumbnailsDirectory;
|
||||||
|
|
||||||
var dir = new DirectoryInfo(config.ThumbnailsDirectory);
|
var dir = new DirectoryInfo(config.ThumbnailsDirectory);
|
||||||
if (!dir.Exists)
|
if (!dir.Exists)
|
||||||
Directory.CreateDirectory(config.ThumbnailsDirectory);
|
Directory.CreateDirectory(config.ThumbnailsDirectory);
|
||||||
|
_thumbnailsDirectory = new DirectoryInfo(config.ThumbnailsDirectory);
|
||||||
|
return _thumbnailsDirectory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RefreshThumbnails()
|
||||||
|
{
|
||||||
var prefixLen = Config.ThumbnailPrefix.Length;
|
var prefixLen = Config.ThumbnailPrefix.Length;
|
||||||
var thumbnailsDir = new DirectoryInfo(config.ThumbnailsDirectory);
|
|
||||||
|
|
||||||
var thumbnails = thumbnailsDir.GetFiles()
|
var thumbnails = ThumbnailsDirectory.GetFiles()
|
||||||
.Select(x => Path.GetFileNameWithoutExtension(x.Name)[..^prefixLen])
|
.Select(x => Path.GetFileNameWithoutExtension(x.Name)[..^prefixLen])
|
||||||
.GroupBy(x => x)
|
.GroupBy(x => x)
|
||||||
.Select(gr => gr.Key)
|
.Select(gr => gr.Key)
|
||||||
@@ -38,15 +49,9 @@ public class GalleryManager(Config config, ILogger<GalleryManager> logger) : IGa
|
|||||||
var imgName = Path.GetFileNameWithoutExtension(img.Name);
|
var imgName = Path.GetFileNameWithoutExtension(img.Name);
|
||||||
if (thumbnails.Contains(imgName))
|
if (thumbnails.Contains(imgName))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var bitmap = await GenerateThumbnail(img);
|
await CreateThumbnail(img.FullName);
|
||||||
if (bitmap != null)
|
|
||||||
{
|
|
||||||
var thumbnailName = Path.Combine(thumbnailsDir.FullName, $"{imgName}{Config.ThumbnailPrefix}.jpg");
|
|
||||||
bitmap.Save(thumbnailName, ImageFormat.Jpeg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -57,15 +62,25 @@ public class GalleryManager(Config config, ILogger<GalleryManager> logger) : IGa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Bitmap?> GenerateThumbnail(FileInfo img)
|
public async Task CreateThumbnail(string imgPath)
|
||||||
|
{
|
||||||
|
var bitmap = await GenerateThumbnail(imgPath);
|
||||||
|
if (bitmap != null)
|
||||||
|
{
|
||||||
|
var thumbnailName = Path.Combine(ThumbnailsDirectory.FullName, $"{Path.GetFileNameWithoutExtension(imgPath)}{Config.ThumbnailPrefix}.jpg");
|
||||||
|
bitmap.Save(thumbnailName, ImageFormat.Jpeg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Bitmap?> GenerateThumbnail(string imgPath)
|
||||||
{
|
{
|
||||||
var width = (int)config.ThumbnailConfig.Size.Width;
|
var width = (int)config.ThumbnailConfig.Size.Width;
|
||||||
var height = (int)config.ThumbnailConfig.Size.Height;
|
var height = (int)config.ThumbnailConfig.Size.Height;
|
||||||
|
|
||||||
var imgName = Path.GetFileNameWithoutExtension(img.Name);
|
var imgName = Path.GetFileName(imgPath);
|
||||||
var labelName = Path.Combine(config.LabelsDirectory, $"{imgName}.txt");
|
var labelName = Path.Combine(config.LabelsDirectory, $"{Path.GetFileNameWithoutExtension(imgPath)}.txt");
|
||||||
|
|
||||||
var originalImage = Image.FromStream(new MemoryStream(await File.ReadAllBytesAsync(img.FullName)));
|
var originalImage = Image.FromStream(new MemoryStream(await File.ReadAllBytesAsync(imgPath)));
|
||||||
|
|
||||||
var bitmap = new Bitmap(width, height);
|
var bitmap = new Bitmap(width, height);
|
||||||
|
|
||||||
@@ -77,8 +92,8 @@ public class GalleryManager(Config config, ILogger<GalleryManager> logger) : IGa
|
|||||||
var size = new Size(originalImage.Width, originalImage.Height);
|
var size = new Size(originalImage.Width, originalImage.Height);
|
||||||
if (!File.Exists(labelName))
|
if (!File.Exists(labelName))
|
||||||
{
|
{
|
||||||
File.Move(img.FullName, Path.Combine(config.UnknownImages, Path.GetFileName(img.Name)));
|
File.Move(imgPath, Path.Combine(config.UnknownImages, imgName));
|
||||||
logger.LogInformation($"No labels found for image {img.Name}! Moved image to the {config.UnknownImages} folder.");
|
logger.LogInformation($"No labels found for image {imgName}! Moved image to the {config.UnknownImages} folder.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var labels = (await YoloLabel.ReadFromFile(labelName))
|
var labels = (await YoloLabel.ReadFromFile(labelName))
|
||||||
@@ -139,5 +154,6 @@ public interface IGalleryManager
|
|||||||
{
|
{
|
||||||
int ThumbnailsCount { get; set; }
|
int ThumbnailsCount { get; set; }
|
||||||
int ImagesCount { get; set; }
|
int ImagesCount { get; set; }
|
||||||
|
Task CreateThumbnail(string imgPath);
|
||||||
Task RefreshThumbnails();
|
Task RefreshThumbnails();
|
||||||
}
|
}
|
||||||
@@ -75,6 +75,8 @@ public partial class MainWindow
|
|||||||
Directory.CreateDirectory(_config.ResultsDirectory);
|
Directory.CreateDirectory(_config.ResultsDirectory);
|
||||||
|
|
||||||
Editor.GetTimeFunc = () => TimeSpan.FromMilliseconds(_mediaPlayer.Time);
|
Editor.GetTimeFunc = () => TimeSpan.FromMilliseconds(_mediaPlayer.Time);
|
||||||
|
|
||||||
|
Activated += (_, _) => { _formState.ActiveWindow = WindowsEnum.Main; };
|
||||||
}
|
}
|
||||||
|
|
||||||
private void VideoView_Loaded(object sender, RoutedEventArgs e)
|
private void VideoView_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
|||||||
+7
-4
@@ -8,7 +8,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
|
|
||||||
namespace Azaion.Annotator;
|
namespace Azaion.Annotator;
|
||||||
|
|
||||||
public class PlayerControlHandler :
|
public class MainWindowEventHandler :
|
||||||
INotificationHandler<KeyEvent>,
|
INotificationHandler<KeyEvent>,
|
||||||
INotificationHandler<AnnClassSelectedEvent>,
|
INotificationHandler<AnnClassSelectedEvent>,
|
||||||
INotificationHandler<PlaybackControlEvent>,
|
INotificationHandler<PlaybackControlEvent>,
|
||||||
@@ -19,7 +19,7 @@ public class PlayerControlHandler :
|
|||||||
private readonly MainWindow _mainWindow;
|
private readonly MainWindow _mainWindow;
|
||||||
private readonly FormState _formState;
|
private readonly FormState _formState;
|
||||||
private readonly Config _config;
|
private readonly Config _config;
|
||||||
private readonly ILogger<PlayerControlHandler> _logger;
|
private readonly ILogger<MainWindowEventHandler> _logger;
|
||||||
|
|
||||||
private const int STEP = 20;
|
private const int STEP = 20;
|
||||||
private const int LARGE_STEP = 5000;
|
private const int LARGE_STEP = 5000;
|
||||||
@@ -37,12 +37,12 @@ public class PlayerControlHandler :
|
|||||||
{ Key.PageDown, PlaybackControlEnum.Next },
|
{ Key.PageDown, PlaybackControlEnum.Next },
|
||||||
};
|
};
|
||||||
|
|
||||||
public PlayerControlHandler(LibVLC libVLC,
|
public MainWindowEventHandler(LibVLC libVLC,
|
||||||
MediaPlayer mediaPlayer,
|
MediaPlayer mediaPlayer,
|
||||||
MainWindow mainWindow,
|
MainWindow mainWindow,
|
||||||
FormState formState,
|
FormState formState,
|
||||||
Config config,
|
Config config,
|
||||||
ILogger<PlayerControlHandler> logger)
|
ILogger<MainWindowEventHandler> logger)
|
||||||
{
|
{
|
||||||
_libVLC = libVLC;
|
_libVLC = libVLC;
|
||||||
_mediaPlayer = mediaPlayer;
|
_mediaPlayer = mediaPlayer;
|
||||||
@@ -69,6 +69,9 @@ public class PlayerControlHandler :
|
|||||||
|
|
||||||
public async Task Handle(KeyEvent notification, CancellationToken cancellationToken)
|
public async Task Handle(KeyEvent notification, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
if (_formState.ActiveWindow != WindowsEnum.Main)
|
||||||
|
return;
|
||||||
|
|
||||||
var key = notification.Args.Key;
|
var key = notification.Args.Key;
|
||||||
var keyNumber = (int?)null;
|
var keyNumber = (int?)null;
|
||||||
|
|
||||||
Reference in New Issue
Block a user