mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 11:16:30 +00:00
fix initialization, throttle operations
day/winter/night switcher fixes
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user