mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 09:46:30 +00:00
fix initialization, throttle operations
day/winter/night switcher fixes
This commit is contained in:
@@ -51,7 +51,7 @@ public partial class Annotator
|
||||
|
||||
private readonly TimeSpan _thresholdBefore = TimeSpan.FromMilliseconds(100);
|
||||
private readonly TimeSpan _thresholdAfter = TimeSpan.FromMilliseconds(300);
|
||||
|
||||
private static readonly Guid SaveConfigTaskId = Guid.NewGuid();
|
||||
|
||||
public ObservableCollection<MediaFileInfo> AllMediaFiles { get; set; } = new();
|
||||
public ObservableCollection<MediaFileInfo> FilteredMediaFiles { get; set; } = new();
|
||||
@@ -72,6 +72,7 @@ public partial class Annotator
|
||||
IInferenceService inferenceService)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_appConfig = appConfig.Value;
|
||||
_configUpdater = configUpdater;
|
||||
_libVLC = libVLC;
|
||||
@@ -119,9 +120,7 @@ public partial class Annotator
|
||||
_suspendLayout = false;
|
||||
TbFolder.Text = _appConfig.DirectoriesConfig.VideosDirectory;
|
||||
|
||||
AnnotationClasses = new ObservableCollection<DetectionClass>(_appConfig.AnnotationConfig.AnnotationClasses);
|
||||
LvClasses.DetectionDataGrid.ItemsSource = AnnotationClasses;
|
||||
LvClasses.SelectNum(0);
|
||||
LvClasses.Init(_appConfig.AnnotationConfig.DetectionClasses);
|
||||
|
||||
if (LvFiles.Items.IsEmpty)
|
||||
BlinkHelp(HelpTexts.HelpTextsDict[HelpTextEnum.Initial]);
|
||||
@@ -261,7 +260,7 @@ public partial class Annotator
|
||||
{
|
||||
_configUpdater.Save(_appConfig);
|
||||
return Task.CompletedTask;
|
||||
}, TimeSpan.FromSeconds(5));
|
||||
}, SaveConfigTaskId, TimeSpan.FromSeconds(5));
|
||||
}
|
||||
|
||||
private void ShowTimeAnnotations(TimeSpan time)
|
||||
@@ -295,7 +294,7 @@ public partial class Annotator
|
||||
}
|
||||
foreach (var detection in annotation.Detections)
|
||||
{
|
||||
var annClass = _appConfig.AnnotationConfig.AnnotationClasses[detection.ClassNumber];
|
||||
var annClass = _appConfig.AnnotationConfig.DetectionClasses[detection.ClassNumber];
|
||||
var canvasLabel = new CanvasLabel(detection, canvasSize, videoSize, detection.Probability);
|
||||
Editor.CreateDetectionControl(annClass, annotation.Time, canvasLabel);
|
||||
}
|
||||
@@ -312,6 +311,7 @@ public partial class Annotator
|
||||
var annotations = await _dbFactory.Run(async db =>
|
||||
await db.Annotations.LoadWith(x => x.Detections)
|
||||
.Where(x => x.OriginalMediaName == _formState.VideoName)
|
||||
.OrderBy(x => x.Time)
|
||||
.ToListAsync(token: MainCancellationSource.Token));
|
||||
|
||||
TimedAnnotations.Clear();
|
||||
@@ -425,12 +425,6 @@ public partial class Annotator
|
||||
private void SeekTo(TimeSpan time) =>
|
||||
SeekTo((long)time.TotalMilliseconds);
|
||||
|
||||
// private void AddClassBtnClick(object sender, RoutedEventArgs e)
|
||||
// {
|
||||
// LvClasses.IsReadOnly = false;
|
||||
// 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();
|
||||
|
||||
@@ -521,8 +515,8 @@ public partial class Annotator
|
||||
{
|
||||
//Take not annotataed medias
|
||||
files = (LvFiles.ItemsSource as IEnumerable<MediaFileInfo>)?.Skip(LvFiles.SelectedIndex)
|
||||
.Take(Constants.DETECTION_BATCH_SIZE)
|
||||
.Where(x => !x.HasAnnotations)
|
||||
.Take(Constants.DETECTION_BATCH_SIZE)
|
||||
.Select(x => x.Path)
|
||||
.ToList() ?? [];
|
||||
if (files.Count != 0)
|
||||
|
||||
@@ -51,7 +51,8 @@
|
||||
CanUserResizeRows="False"
|
||||
CanUserResizeColumns="False"
|
||||
SelectionChanged="DetectionDataGrid_SelectionChanged"
|
||||
x:FieldModifier="public">
|
||||
x:FieldModifier="public"
|
||||
>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTemplateColumn Width="50" Header="Клавіша" CanUserSort="False">
|
||||
<DataGridTemplateColumn.HeaderStyle>
|
||||
@@ -90,13 +91,13 @@
|
||||
IsChecked="True"
|
||||
Style="{StaticResource ButtonRadioButtonStyle}"/>
|
||||
<RadioButton x:Name="EveningModeRadioButton"
|
||||
Tag="1"
|
||||
Tag="20"
|
||||
Content="Зима"
|
||||
GroupName="Mode"
|
||||
Checked="ModeRadioButton_Checked" Margin="10,0,0,0"
|
||||
Style="{StaticResource ButtonRadioButtonStyle}"/>
|
||||
<RadioButton x:Name="NightModeRadioButton"
|
||||
Tag="2"
|
||||
Tag="40"
|
||||
Content="Ніч"
|
||||
GroupName="Mode"
|
||||
Checked="ModeRadioButton_Checked" Margin="10,0,0,0"
|
||||
|
||||
@@ -4,16 +4,26 @@ using Azaion.Common.DTO;
|
||||
|
||||
namespace Azaion.Common.Controls;
|
||||
|
||||
public class DetectionClassChangedEventArgs(DetectionClass? detectionClass, int classNumber) : EventArgs
|
||||
public class DetectionClassChangedEventArgs(DetectionClass detectionClass, int classNumber) : EventArgs
|
||||
{
|
||||
public DetectionClass? DetectionClass { get; } = detectionClass;
|
||||
public DetectionClass DetectionClass { get; } = detectionClass;
|
||||
public int ClassNumber { get; } = classNumber;
|
||||
}
|
||||
|
||||
public partial class DetectionClasses
|
||||
{
|
||||
public event EventHandler<DetectionClassChangedEventArgs>? DetectionClassChanged;
|
||||
public DetectionClasses() => InitializeComponent();
|
||||
|
||||
public DetectionClasses()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void Init(List<DetectionClass> detectionClasses)
|
||||
{
|
||||
DetectionDataGrid.ItemsSource = detectionClasses;
|
||||
DetectionDataGrid.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
public int CurrentClassNumber { get; private set; } = 0;
|
||||
public DetectionClass? CurrentDetectionClass { get; set; }
|
||||
@@ -27,26 +37,25 @@ public partial class DetectionClasses
|
||||
private void RaiseDetectionClassChanged()
|
||||
{
|
||||
var detClass = (DetectionClass)DetectionDataGrid.SelectedItem;
|
||||
var baseClassNumber = detClass?.Id ?? 0;
|
||||
if (detClass == null)
|
||||
return;
|
||||
|
||||
var modeAmplifier = 0;
|
||||
foreach (var child in ModeSwitcherPanel.Children)
|
||||
if (child is RadioButton { IsChecked: true } rb)
|
||||
if (int.TryParse(rb.Tag?.ToString(), out int modeIndex))
|
||||
{
|
||||
if (detClass != null)
|
||||
detClass.PhotoMode = (PhotoMode)modeIndex;
|
||||
modeAmplifier += modeIndex * 20;
|
||||
detClass.PhotoMode = (PhotoMode)modeIndex;
|
||||
modeAmplifier += modeIndex;
|
||||
}
|
||||
|
||||
CurrentDetectionClass = detClass;
|
||||
CurrentClassNumber = baseClassNumber + modeAmplifier;
|
||||
CurrentClassNumber = detClass.Id + modeAmplifier;
|
||||
|
||||
DetectionClassChanged?.Invoke(this, new DetectionClassChangedEventArgs(detClass, CurrentClassNumber));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void SelectNum(int keyNumber)
|
||||
{
|
||||
DetectionDataGrid.SelectedIndex = keyNumber;
|
||||
|
||||
@@ -50,7 +50,7 @@ public class DetectionControl : Border
|
||||
_resizeStart = resizeStart;
|
||||
_classNameLabel = new TextBlock
|
||||
{
|
||||
Text = detectionClass.Name,
|
||||
Text = detectionClass.UIName,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
VerticalAlignment = VerticalAlignment.Top,
|
||||
Margin = new Thickness(0, 15, 0, 0),
|
||||
@@ -120,7 +120,7 @@ public class DetectionControl : Border
|
||||
|
||||
public YoloLabel GetLabel(Size canvasSize, Size? videoSize = null)
|
||||
{
|
||||
var label = new CanvasLabel(DetectionClass.Id, Canvas.GetLeft(this), Canvas.GetTop(this), Width, Height);
|
||||
var label = new CanvasLabel(DetectionClass.YoloId, Canvas.GetLeft(this), Canvas.GetTop(this), Width, Height);
|
||||
return new YoloLabel(label, canvasSize, videoSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ public class AnnotationResult
|
||||
var detectionClasses = detections.Select(x => x.ClassNumber).Distinct().ToList();
|
||||
|
||||
ClassName = detectionClasses.Count > 1
|
||||
? string.Join(", ", detectionClasses.Select(x => allDetectionClasses[x].ShortName))
|
||||
: allDetectionClasses[detectionClasses.FirstOrDefault()].Name;
|
||||
? string.Join(", ", detectionClasses.Select(x => allDetectionClasses[x].UIName))
|
||||
: allDetectionClasses[detectionClasses.FirstOrDefault()].UIName;
|
||||
|
||||
ClassColor0 = GetAnnotationClass(detectionClasses, 0);
|
||||
ClassColor1 = GetAnnotationClass(detectionClasses, 1);
|
||||
|
||||
@@ -4,12 +4,32 @@ namespace Azaion.Common.DTO.Config;
|
||||
|
||||
public class AnnotationConfig
|
||||
{
|
||||
public List<DetectionClass> AnnotationClasses { get; set; } = null!;
|
||||
public List<DetectionClass> DetectionClasses { get; set; } = null!;
|
||||
|
||||
[JsonIgnore]
|
||||
private Dictionary<int, DetectionClass>? _detectionClassesDict;
|
||||
|
||||
[JsonIgnore]
|
||||
public Dictionary<int, DetectionClass> DetectionClassesDict => _detectionClassesDict ??= AnnotationClasses.ToDictionary(x => x.Id);
|
||||
public Dictionary<int, DetectionClass> DetectionClassesDict
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_detectionClassesDict != null)
|
||||
return _detectionClassesDict;
|
||||
|
||||
var photoModes = Enum.GetValues(typeof(PhotoMode)).Cast<PhotoMode>().ToList();
|
||||
|
||||
_detectionClassesDict = DetectionClasses.SelectMany(cls => photoModes.Select(mode => new DetectionClass
|
||||
{
|
||||
Id = cls.Id,
|
||||
Name = cls.Name,
|
||||
ShortName = cls.ShortName,
|
||||
PhotoMode = mode
|
||||
}))
|
||||
.ToDictionary(x => x.YoloId, x => x);
|
||||
return _detectionClassesDict;
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> VideoFormats { get; set; } = null!;
|
||||
public List<string> ImageFormats { get; set; } = null!;
|
||||
|
||||
@@ -41,7 +41,7 @@ public class ConfigUpdater : IConfigUpdater
|
||||
{
|
||||
AnnotationConfig = new AnnotationConfig
|
||||
{
|
||||
AnnotationClasses = Constants.DefaultAnnotationClasses,
|
||||
DetectionClasses = Constants.DefaultAnnotationClasses,
|
||||
VideoFormats = Constants.DefaultVideoFormats,
|
||||
ImageFormats = Constants.DefaultImageFormats,
|
||||
|
||||
|
||||
@@ -11,6 +11,23 @@ public class DetectionClass
|
||||
public string Name { get; set; } = null!;
|
||||
public string ShortName { get; set; } = null!;
|
||||
|
||||
public string UIName
|
||||
{
|
||||
get
|
||||
{
|
||||
var mode = PhotoMode switch
|
||||
{
|
||||
PhotoMode.Night => "(ніч)",
|
||||
PhotoMode.Winter => "(зим)",
|
||||
PhotoMode.Regular => "",
|
||||
_ => ""
|
||||
};
|
||||
return ShortName + mode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[JsonIgnore]
|
||||
public PhotoMode PhotoMode { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
@@ -19,6 +36,9 @@ public class DetectionClass
|
||||
[JsonIgnore] //For UI
|
||||
public int ClassNumber => Id + 1;
|
||||
|
||||
[JsonIgnore]
|
||||
public int YoloId => (int)PhotoMode + Id;
|
||||
|
||||
[JsonIgnore]
|
||||
public SolidColorBrush ColorBrush => new(Color);
|
||||
}
|
||||
|
||||
@@ -1,34 +1,55 @@
|
||||
namespace Azaion.Common.Extensions;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Azaion.Common.Extensions;
|
||||
|
||||
public static class ThrottleExt
|
||||
{
|
||||
private static bool _throttleRunFirstOn;
|
||||
public static async Task ThrottleRunFirst(this Func<Task> func, TimeSpan? throttleTime = null, CancellationToken cancellationToken = default)
|
||||
private static ConcurrentDictionary<Guid, bool> _taskStates = new();
|
||||
|
||||
public static async Task ThrottleRunFirst(Func<Task> func, Guid actionId, TimeSpan? throttleTime = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (_throttleRunFirstOn)
|
||||
if (_taskStates.ContainsKey(actionId) && _taskStates[actionId])
|
||||
return;
|
||||
|
||||
_throttleRunFirstOn = true;
|
||||
await func();
|
||||
_taskStates[actionId] = true;
|
||||
try
|
||||
{
|
||||
await func();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(throttleTime ?? TimeSpan.FromMilliseconds(500), cancellationToken);
|
||||
_throttleRunFirstOn = false;
|
||||
_taskStates[actionId] = false;
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
private static bool _throttleRunAfter;
|
||||
public static async Task ThrottleRunAfter(this Func<Task> func, TimeSpan? throttleTime = null, CancellationToken cancellationToken = default)
|
||||
public static async Task ThrottleRunAfter(Func<Task> func, Guid actionId, TimeSpan? throttleTime = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (_throttleRunAfter)
|
||||
if (_taskStates.ContainsKey(actionId) && _taskStates[actionId])
|
||||
return;
|
||||
|
||||
_throttleRunAfter = true;
|
||||
_taskStates[actionId] = true;
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(throttleTime ?? TimeSpan.FromMilliseconds(500), cancellationToken);
|
||||
await func();
|
||||
_throttleRunAfter = false;
|
||||
try
|
||||
{
|
||||
await Task.Delay(throttleTime ?? TimeSpan.FromMilliseconds(500), cancellationToken);
|
||||
await func();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_taskStates[actionId] = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_taskStates[actionId] = false;
|
||||
}
|
||||
|
||||
}, cancellationToken);
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ public class AnnotationService : INotificationHandler<AnnotationsDeletedEvent>
|
||||
private readonly IAuthProvider _authProvider;
|
||||
private readonly QueueConfig _queueConfig;
|
||||
private Consumer _consumer = null!;
|
||||
private static readonly Guid SaveTaskId = Guid.NewGuid();
|
||||
|
||||
public AnnotationService(
|
||||
IResourceLoader resourceLoader,
|
||||
@@ -95,7 +96,7 @@ public class AnnotationService : INotificationHandler<AnnotationsDeletedEvent>
|
||||
{
|
||||
_dbFactory.SaveToDisk();
|
||||
return Task.CompletedTask;
|
||||
}, TimeSpan.FromSeconds(3), cancellationToken);
|
||||
}, SaveTaskId, TimeSpan.FromSeconds(3), cancellationToken);
|
||||
|
||||
}
|
||||
});
|
||||
@@ -184,7 +185,7 @@ public class AnnotationService : INotificationHandler<AnnotationsDeletedEvent>
|
||||
{
|
||||
_dbFactory.SaveToDisk();
|
||||
return Task.CompletedTask;
|
||||
}, TimeSpan.FromSeconds(5), token);
|
||||
}, SaveTaskId, TimeSpan.FromSeconds(5), token);
|
||||
return annotation;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ public class PythonResourceLoader : IResourceLoader, IAuthProvider
|
||||
|
||||
public PythonResourceLoader(PythonConfig config)
|
||||
{
|
||||
//StartPython();
|
||||
StartPython();
|
||||
_dealer.Options.Identity = Encoding.UTF8.GetBytes(_clientId.ToString("N"));
|
||||
_dealer.Connect($"tcp://{config.ZeroMqHost}:{config.ZeroMqPort}");
|
||||
}
|
||||
|
||||
@@ -57,16 +57,13 @@
|
||||
<RowDefinition Height="32"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="150" />
|
||||
<ColumnDefinition Width="200" />
|
||||
<ColumnDefinition Width="4"/>
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<controls:DetectionClasses
|
||||
x:Name="LvClasses"
|
||||
<controls:DetectionClasses x:Name="LvClasses"
|
||||
Grid.Column="0"
|
||||
Grid.Row="0">
|
||||
</controls:DetectionClasses>
|
||||
|
||||
Grid.Row="0" />
|
||||
<TabControl
|
||||
Name="Switcher"
|
||||
Grid.Column="2"
|
||||
|
||||
@@ -22,10 +22,10 @@ public partial class DatasetExplorer
|
||||
private readonly AnnotationConfig _annotationConfig;
|
||||
private readonly DirectoriesConfig _directoriesConfig;
|
||||
|
||||
private Dictionary<int, List<Annotation>> _annotationsDict = new();
|
||||
private readonly Dictionary<int, List<Annotation>> _annotationsDict;
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
public ObservableCollection<DetectionClass> AllDetectionClasses { get; set; } = new();
|
||||
public List<DetectionClass> AllDetectionClasses { get; set; }
|
||||
public ObservableCollection<AnnotationThumbnail> SelectedAnnotations { get; set; } = new();
|
||||
public readonly Dictionary<string, AnnotationThumbnail> SelectedAnnotationDict = new();
|
||||
|
||||
@@ -34,6 +34,8 @@ public partial class DatasetExplorer
|
||||
private readonly IDbFactory _dbFactory;
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
public readonly List<DetectionClass> AnnotationsClasses;
|
||||
|
||||
|
||||
public bool ThumbnailLoading { get; set; }
|
||||
|
||||
@@ -48,6 +50,8 @@ public partial class DatasetExplorer
|
||||
IDbFactory dbFactory,
|
||||
IMediator mediator)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_directoriesConfig = directoriesConfig.Value;
|
||||
_annotationConfig = annotationConfig.Value;
|
||||
_logger = logger;
|
||||
@@ -55,7 +59,13 @@ public partial class DatasetExplorer
|
||||
_dbFactory = dbFactory;
|
||||
_mediator = mediator;
|
||||
|
||||
InitializeComponent();
|
||||
var photoModes = Enum.GetValues(typeof(PhotoMode)).Cast<PhotoMode>().ToList();
|
||||
_annotationsDict = _annotationConfig.DetectionClasses.SelectMany(cls => photoModes.Select(mode => (int)mode + cls.Id))
|
||||
.ToDictionary(x => x, _ => new List<Annotation>());
|
||||
_annotationsDict.Add(-1, []);
|
||||
|
||||
AnnotationsClasses = annotationConfig.Value.DetectionClasses;
|
||||
|
||||
Loaded += OnLoaded;
|
||||
Activated += (_, _) => formState.ActiveWindow = WindowEnum.DatasetExplorer;
|
||||
|
||||
@@ -86,15 +96,29 @@ public partial class DatasetExplorer
|
||||
Dispatcher.Invoke(() => RefreshThumbBar.Value = thumbnailsPercentage);
|
||||
};
|
||||
Closing += (_, _) => _cts.Cancel();
|
||||
|
||||
AllDetectionClasses = new List<DetectionClass>(
|
||||
new List<DetectionClass> { new() {Id = -1, Name = "All", ShortName = "All"}}
|
||||
.Concat(_annotationConfig.DetectionClasses));
|
||||
LvClasses.Init(AllDetectionClasses);
|
||||
|
||||
_dbFactory.Run(async db =>
|
||||
{
|
||||
var allAnnotations = await db.Annotations
|
||||
.LoadWith(x => x.Detections)
|
||||
.OrderBy(x => x.AnnotationStatus)
|
||||
.ThenByDescending(x => x.CreatedDate)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var annotation in allAnnotations)
|
||||
AddAnnotationToDict(annotation);
|
||||
}).GetAwaiter().GetResult();
|
||||
|
||||
DataContext = this;
|
||||
}
|
||||
|
||||
private async void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AllDetectionClasses = new ObservableCollection<DetectionClass>(
|
||||
new List<DetectionClass> { new() {Id = -1, Name = "All", ShortName = "All"}}
|
||||
.Concat(_annotationConfig.AnnotationClasses));
|
||||
LvClasses.DetectionDataGrid.ItemsSource = AllDetectionClasses;
|
||||
|
||||
LvClasses.DetectionClassChanged += async (_, args) =>
|
||||
{
|
||||
ExplorerEditor.CurrentAnnClass = args.DetectionClass;
|
||||
@@ -106,20 +130,8 @@ public partial class DatasetExplorer
|
||||
ann.DetectionClass = args.DetectionClass;
|
||||
};
|
||||
|
||||
ExplorerEditor.CurrentAnnClass = (DetectionClass)LvClasses.CurrentDetectionClass;
|
||||
ExplorerEditor.CurrentAnnClass = LvClasses.CurrentDetectionClass ?? _annotationConfig.DetectionClasses.First();
|
||||
|
||||
await _dbFactory.Run(async db =>
|
||||
{
|
||||
var allAnnotations = await db.Annotations
|
||||
.LoadWith(x => x.Detections)
|
||||
.OrderBy(x => x.AnnotationStatus)
|
||||
.ThenByDescending(x => x.CreatedDate)
|
||||
.ToListAsync();
|
||||
_annotationsDict = AllDetectionClasses.ToDictionary(x => x.Id, _ => new List<Annotation>());
|
||||
|
||||
foreach (var annotation in allAnnotations)
|
||||
AddAnnotationToDict(annotation);
|
||||
});
|
||||
await ReloadThumbnails();
|
||||
await LoadClassDistribution();
|
||||
|
||||
@@ -239,7 +251,7 @@ public partial class DatasetExplorer
|
||||
AnnotationsTab.Visibility = Visibility.Collapsed;
|
||||
EditorTab.Visibility = Visibility.Visible;
|
||||
_tempSelectedClassIdx = LvClasses.CurrentClassNumber;
|
||||
LvClasses.DetectionDataGrid.ItemsSource = _annotationConfig.AnnotationClasses;
|
||||
LvClasses.DetectionDataGrid.ItemsSource = _annotationConfig.DetectionClasses;
|
||||
|
||||
Switcher.SelectedIndex = 1;
|
||||
LvClasses.SelectNum(Math.Max(0, _tempSelectedClassIdx - 1));
|
||||
|
||||
@@ -35,6 +35,7 @@ public partial class App
|
||||
|
||||
private PythonResourceLoader _resourceLoader = null!;
|
||||
private Stream _securedConfig = null!;
|
||||
private static readonly Guid KeyPressTaskId = Guid.NewGuid();
|
||||
|
||||
private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
|
||||
{
|
||||
@@ -199,7 +200,7 @@ public partial class App
|
||||
{
|
||||
var args = (KeyEventArgs)e;
|
||||
var keyEvent = new KeyEvent(sender, args, _formState.ActiveWindow);
|
||||
_ = ThrottleExt.ThrottleRunFirst(() => _mediator.Publish(keyEvent), TimeSpan.FromMilliseconds(50));
|
||||
_ = ThrottleExt.ThrottleRunFirst(() => _mediator.Publish(keyEvent), KeyPressTaskId, TimeSpan.FromMilliseconds(50));
|
||||
}
|
||||
|
||||
protected override async void OnExit(ExitEventArgs e)
|
||||
|
||||
@@ -9,7 +9,6 @@ using Azaion.Common.DTO.Config;
|
||||
using Azaion.Common.Extensions;
|
||||
using Azaion.Common.Services;
|
||||
using Azaion.CommonSecurity.Services;
|
||||
using Azaion.Dataset;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using SharpVectors.Converters;
|
||||
@@ -26,6 +25,7 @@ public partial class MainSuite
|
||||
private readonly IDbFactory _dbFactory;
|
||||
private readonly Dictionary<WindowEnum, Window> _openedWindows = new();
|
||||
private readonly IResourceLoader _resourceLoader;
|
||||
private static readonly Guid SaveConfigTaskId = Guid.NewGuid();
|
||||
|
||||
public MainSuite(IOptions<AppConfig> appConfig,
|
||||
IConfigUpdater configUpdater,
|
||||
@@ -89,6 +89,7 @@ public partial class MainSuite
|
||||
};
|
||||
lvItem.MouseUp += (lv, _) => OpenWindow((lv as ListViewItem)!);
|
||||
ListView.Items.Add(lvItem);
|
||||
_ = _sp.GetRequiredService(azaionModule.MainWindowType) as Window;
|
||||
}
|
||||
|
||||
_ = Task.Run(async () => await _galleryService.RefreshThumbnails());
|
||||
@@ -126,7 +127,7 @@ public partial class MainSuite
|
||||
{
|
||||
_configUpdater.Save(_appConfig);
|
||||
return Task.CompletedTask;
|
||||
}, TimeSpan.FromSeconds(2));
|
||||
}, SaveConfigTaskId, TimeSpan.FromSeconds(2));
|
||||
}
|
||||
|
||||
private void OnFormClosed(object? sender, EventArgs e)
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
"ZeroMqHost": "127.0.0.1",
|
||||
"ZeroMqPort": 5128,
|
||||
"RetryCount": 25,
|
||||
"TimeoutSeconds": 5
|
||||
"TimeoutSeconds": 5,
|
||||
"ResourcesFolder": "stage"
|
||||
},
|
||||
"DirectoriesConfig": {
|
||||
"VideosDirectory": "E:\\Azaion6",
|
||||
@@ -13,16 +14,16 @@
|
||||
"ThumbnailsDirectory": "E:\\thumbnails"
|
||||
},
|
||||
"AnnotationConfig": {
|
||||
"AnnotationClasses": [
|
||||
{ "Id": 0, "Name": "Броньована техніка", "ShortName": "Бронь" },
|
||||
{ "Id": 1, "Name": "Вантажівка", "ShortName": "Вантаж" },
|
||||
"DetectionClasses": [
|
||||
{ "Id": 0, "Name": "Броньована техніка", "ShortName": "Броня" },
|
||||
{ "Id": 1, "Name": "Вантажівка", "ShortName": "Вантаж." },
|
||||
{ "Id": 2, "Name": "Машина легкова", "ShortName": "Машина" },
|
||||
{ "Id": 3, "Name": "Артилерія", "ShortName": "Арта" },
|
||||
{ "Id": 4, "Name": "Тінь від техніки", "ShortName": "Тінь" },
|
||||
{ "Id": 5, "Name": "Окопи", "ShortName": "Окопи" },
|
||||
{ "Id": 6, "Name": "Військовий", "ShortName": "Військов" },
|
||||
{ "Id": 7, "Name": "Накати", "ShortName": "Накати" },
|
||||
{ "Id": 8, "Name": "Танк з захистом", "ShortName": "Танк захист" },
|
||||
{ "Id": 8, "Name": "Танк з захистом", "ShortName": "Танк.захист" },
|
||||
{ "Id": 9, "Name": "Дим", "ShortName": "Дим" },
|
||||
{ "Id": 10, "Name": "Літак", "ShortName": "Літак" },
|
||||
{ "Id": 11, "Name": "Мотоцикл", "ShortName": "Мото" }
|
||||
|
||||
+6
-2
@@ -1,6 +1,5 @@
|
||||
@echo off
|
||||
|
||||
|
||||
cd Azaion.Suite
|
||||
echo Build .net app
|
||||
dotnet build -c Release
|
||||
@@ -17,7 +16,7 @@ move dist\Azaion.Annotator.dll dist\dummy\
|
||||
move dist\Azaion.Dataset.dll dist\dummy\
|
||||
|
||||
echo Build Cython app
|
||||
cd Azaion.Inference\
|
||||
cd Azaion.Inference
|
||||
call ".\venv\Scripts\activate.bat"
|
||||
pyinstaller --onefile ^
|
||||
--collect-all jwt ^
|
||||
@@ -43,3 +42,8 @@ pyinstaller --onefile ^
|
||||
--hidden-import remote_command_handler ^
|
||||
start.py
|
||||
move dist\start.exe ..\dist\azaion-inference.exe
|
||||
copy config.yaml ..\dist
|
||||
|
||||
echo Copy ico
|
||||
cd ..
|
||||
copy logo.ico dist\
|
||||
Reference in New Issue
Block a user