mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 08:06:31 +00:00
add results pane
differentiate already processed videos
This commit is contained in:
@@ -6,9 +6,13 @@ public class AnnotationResult
|
||||
{
|
||||
[JsonProperty(PropertyName = "f")]
|
||||
public string Image { get; set; } = null!;
|
||||
|
||||
[JsonProperty(PropertyName = "t")]
|
||||
public TimeSpan Time { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string TimeStr => $"{Time:h\\:mm\\:ss}";
|
||||
|
||||
[JsonProperty(PropertyName = "p")]
|
||||
public double Percentage { get; set; }
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
public class VideoFileInfo
|
||||
{
|
||||
public string Name { get; set; } = null!;
|
||||
public string Path { get; set; } = null!;
|
||||
public TimeSpan Duration { get; set; }
|
||||
public string Name { get; set; } = null!;
|
||||
public string Path { get; set; } = null!;
|
||||
public TimeSpan Duration { get; set; }
|
||||
public bool HasAnnotations { get; set; }
|
||||
}
|
||||
@@ -105,9 +105,18 @@
|
||||
<ListView Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Name="LvFiles"
|
||||
Background="Black"
|
||||
Background="Black"
|
||||
SelectedItem="{Binding Path=SelectedVideo}" Foreground="#FFA4AFCC"
|
||||
>
|
||||
<ListView.Resources>
|
||||
<Style TargetType="{x:Type ListViewItem}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasAnnotations}" Value="true">
|
||||
<Setter Property="Background" Value="Gray"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ListView.Resources>
|
||||
<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Width="Auto"
|
||||
@@ -197,24 +206,20 @@
|
||||
CanUserResizeRows="False"
|
||||
CanUserResizeColumns="False">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTemplateColumn
|
||||
Width="120"
|
||||
<DataGridTextColumn
|
||||
Width="120"
|
||||
Header="Кадр"
|
||||
CanUserSort="False">
|
||||
<DataGridTemplateColumn.HeaderStyle>
|
||||
CanUserSort="False"
|
||||
Binding="{Binding Path=TimeStr}">
|
||||
<DataGridTextColumn.HeaderStyle>
|
||||
<Style TargetType="DataGridColumnHeader">
|
||||
<Setter Property="Background" Value="#252525"></Setter>
|
||||
</Style>
|
||||
</DataGridTemplateColumn.HeaderStyle>
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Path=ClassNumber}"></TextBlock>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
</DataGridTextColumn.HeaderStyle>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn
|
||||
Width="*"
|
||||
Header="Клас"
|
||||
Header="Клас"
|
||||
Binding="{Binding Path=Name}"
|
||||
CanUserSort="False">
|
||||
<DataGridTextColumn.HeaderStyle>
|
||||
|
||||
@@ -153,6 +153,7 @@ public partial class MainWindow
|
||||
{
|
||||
Annotations = LoadAnnotations();
|
||||
_formState.AnnotationResults = LoadAnnotationResults();
|
||||
DgAnnotations.ItemsSource = _formState.AnnotationResults;
|
||||
}
|
||||
|
||||
private Dictionary<TimeSpan, List<YoloLabel>> LoadAnnotations()
|
||||
@@ -205,16 +206,23 @@ public partial class MainWindow
|
||||
var dir = new DirectoryInfo(_config.VideosDirectory);
|
||||
if (!dir.Exists)
|
||||
return;
|
||||
|
||||
var labelNames = new DirectoryInfo(_config.LabelsDirectory).GetFiles()
|
||||
.Select(x => x.Name[..^11])
|
||||
.GroupBy(x => x)
|
||||
.Select(gr => gr.Key)
|
||||
.ToDictionary(x => x);
|
||||
|
||||
var files = dir.GetFiles("mp4", "mov").Select(x =>
|
||||
{
|
||||
_mediaPlayer.Media = new Media(_libVLC, x.FullName);
|
||||
|
||||
|
||||
return new VideoFileInfo
|
||||
{
|
||||
Name = x.Name,
|
||||
Path = x.FullName,
|
||||
Duration = TimeSpan.FromMilliseconds(_mediaPlayer.Media.Duration)
|
||||
Duration = TimeSpan.FromMilliseconds(_mediaPlayer.Media.Duration),
|
||||
HasAnnotations = labelNames.ContainsKey(Path.GetFileNameWithoutExtension(x.Name).Replace(" ", ""))
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
|
||||
@@ -9,21 +9,21 @@ using Newtonsoft.Json;
|
||||
namespace Azaion.Annotator;
|
||||
|
||||
public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWindow mainWindow, FormState formState, Config config) :
|
||||
INotificationHandler<KeyEvent>,
|
||||
INotificationHandler<AnnClassSelectedEvent>,
|
||||
INotificationHandler<PlaybackControlEvent>,
|
||||
INotificationHandler<VolumeChangedEvent>
|
||||
INotificationHandler<KeyEvent>,
|
||||
INotificationHandler<AnnClassSelectedEvent>,
|
||||
INotificationHandler<PlaybackControlEvent>,
|
||||
INotificationHandler<VolumeChangedEvent>
|
||||
{
|
||||
private const int STEP = 20;
|
||||
private const int LARGE_STEP = 5000;
|
||||
private const int RESULT_WIDTH = 1280;
|
||||
|
||||
|
||||
private static readonly string[] CatchSenders = ["ForegroundWindow", "ScrollViewer", "VideoView"];
|
||||
|
||||
private readonly Dictionary<Key, PlaybackControlEnum> KeysControlEnumDict = new()
|
||||
{
|
||||
{ Key.Space, PlaybackControlEnum.Pause },
|
||||
{ Key.Left, PlaybackControlEnum.PreviousFrame },
|
||||
{ Key.Left, PlaybackControlEnum.PreviousFrame },
|
||||
{ Key.Right, PlaybackControlEnum.NextFrame },
|
||||
{ Key.Enter, PlaybackControlEnum.SaveAnnotations },
|
||||
{ Key.Delete, PlaybackControlEnum.RemoveSelectedAnns },
|
||||
@@ -34,13 +34,13 @@ public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWi
|
||||
{
|
||||
SelectClass(notification.AnnotationClass);
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void SelectClass(AnnotationClass annClass)
|
||||
{
|
||||
mainWindow.Editor.CurrentAnnClass = annClass;
|
||||
foreach (var ann in mainWindow.Editor.CurrentAnns.Where(x => x.IsSelected))
|
||||
foreach (var ann in mainWindow.Editor.CurrentAnns.Where(x => x.IsSelected))
|
||||
ann.AnnotationClass = annClass;
|
||||
mainWindow.LvClasses.SelectedIndex = annClass.Id;
|
||||
}
|
||||
@@ -49,18 +49,18 @@ public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWi
|
||||
{
|
||||
if (!CatchSenders.Contains(notification.Sender.GetType().Name))
|
||||
return;
|
||||
|
||||
|
||||
var key = notification.Args.Key;
|
||||
var keyNumber = (int?)null;
|
||||
|
||||
if ((int)key >= (int)Key.D1 && (int)key <= (int)Key.D9)
|
||||
|
||||
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)
|
||||
if ((int)key >= (int)Key.NumPad1 && (int)key <= (int)Key.NumPad9)
|
||||
keyNumber = key - Key.NumPad1;
|
||||
if (keyNumber.HasValue)
|
||||
SelectClass(mainWindow.AnnotationClasses[keyNumber.Value]);
|
||||
|
||||
if (KeysControlEnumDict.TryGetValue(key, out var value))
|
||||
|
||||
if (KeysControlEnumDict.TryGetValue(key, out var value))
|
||||
await ControlPlayback(value);
|
||||
|
||||
await VolumeControl(key);
|
||||
@@ -80,7 +80,7 @@ public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWi
|
||||
case Key.VolumeUp:
|
||||
var vUp = Math.Min(100, mediaPlayer.Volume + 5);
|
||||
ChangeVolume(vUp);
|
||||
mainWindow.Volume.Value = vUp;
|
||||
mainWindow.Volume.Value = vUp;
|
||||
break;
|
||||
case Key.Down:
|
||||
case Key.VolumeDown:
|
||||
@@ -111,7 +111,7 @@ public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWi
|
||||
break;
|
||||
case PlaybackControlEnum.Pause:
|
||||
mediaPlayer.Pause();
|
||||
if (!mediaPlayer.IsPlaying)
|
||||
if (!mediaPlayer.IsPlaying)
|
||||
mainWindow.BlinkHelp(HelpTexts.HelpTextsDict[HelpTextEnum.AnnotationHelp]);
|
||||
break;
|
||||
case PlaybackControlEnum.Stop:
|
||||
@@ -171,7 +171,7 @@ public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWi
|
||||
formState.CurrentVolume = volume;
|
||||
mediaPlayer.Volume = volume;
|
||||
}
|
||||
|
||||
|
||||
private void Play()
|
||||
{
|
||||
if (mainWindow.LvFiles.SelectedItem == null)
|
||||
@@ -180,12 +180,12 @@ public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWi
|
||||
|
||||
formState.CurrentFile = fileInfo.Name;
|
||||
mainWindow.LoadExistingAnnotations();
|
||||
|
||||
|
||||
mediaPlayer.Stop();
|
||||
mediaPlayer.Play(new Media(libVLC, fileInfo.Path));
|
||||
mainWindow.BlinkHelp(HelpTexts.HelpTextsDict[HelpTextEnum.PauseForAnnotations]);
|
||||
}
|
||||
|
||||
|
||||
private async Task SaveAnnotations()
|
||||
{
|
||||
if (string.IsNullOrEmpty(formState.CurrentFile))
|
||||
@@ -204,18 +204,18 @@ public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWi
|
||||
Directory.CreateDirectory(config.ImagesDirectory);
|
||||
if (!Directory.Exists(config.ResultsDirectory))
|
||||
Directory.CreateDirectory(config.ResultsDirectory);
|
||||
|
||||
|
||||
await File.WriteAllTextAsync($"{config.LabelsDirectory}/{fName}.txt", labels);
|
||||
|
||||
formState.AnnotationResults.Add(new AnnotationResult(time, fName, currentAnns));
|
||||
await File.WriteAllTextAsync($"{config.ResultsDirectory}/{fName}.json", JsonConvert.SerializeObject(formState.AnnotationResults));
|
||||
|
||||
var resultHeight = (uint)Math.Round(RESULT_WIDTH / formState.CurrentVideoSize.Width * formState.CurrentVideoSize.Height);
|
||||
|
||||
|
||||
var resultHeight = (uint)Math.Round(RESULT_WIDTH / formState.CurrentVideoSize.Width * formState.CurrentVideoSize.Height);
|
||||
|
||||
mediaPlayer.TakeSnapshot(0, $"{config.ImagesDirectory}/{fName}.jpg", RESULT_WIDTH, resultHeight);
|
||||
|
||||
|
||||
mainWindow.Annotations[time] = currentAnns;
|
||||
mainWindow.Editor.RemoveAllAnns();
|
||||
mediaPlayer.Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"VideosDirectory": "E:\\Azaion3\\Videos",
|
||||
"VideosDirectory": "E:\\Azaion3\\VideosDone",
|
||||
"LabelsDirectory": "E:\\labels",
|
||||
"ImagesDirectory": "E:\\images",
|
||||
"ResultsDirectory": "E:\\results",
|
||||
|
||||
Reference in New Issue
Block a user