update validation logic

This commit is contained in:
Alex Bezdieniezhnykh
2025-04-21 17:02:13 +03:00
parent 70148bdfdf
commit c68c293448
5 changed files with 43 additions and 19 deletions
+2
View File
@@ -35,4 +35,6 @@ public class AnnotationThumbnail(Annotation annotation) : INotifyPropertyChanged
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void UpdateUI() => OnPropertyChanged(nameof(IsSeed));
}
+3
View File
@@ -31,6 +31,9 @@ public class Annotation
[IgnoreMember]public SourceEnum Source { get; set; }
[IgnoreMember]public AnnotationStatus AnnotationStatus { get; set; }
[IgnoreMember]public DateTime ValidateDate { get; set; }
[IgnoreMember]public string ValidateEmail { get; set; } = null!;
[Key("d")] public IEnumerable<Detection> Detections { get; set; } = null!;
[Key("t")] public long Milliseconds { get; set; }
+25 -14
View File
@@ -94,7 +94,6 @@ public class AnnotationService : INotificationHandler<AnnotationsDeletedEvent>
new MemoryStream(msg.Image),
msg.CreatedRole,
msg.CreatedEmail,
generateThumbnail: true,
fromQueue: true,
token: cancellationToken);
}
@@ -106,17 +105,12 @@ public class AnnotationService : INotificationHandler<AnnotationsDeletedEvent>
{
a.Time = TimeSpan.FromMilliseconds(a.Milliseconds);
return await SaveAnnotationInner(DateTime.Now, a.OriginalMediaName, a.Time, a.Detections.ToList(),
SourceEnum.AI, new MemoryStream(a.Image), _api.CurrentUser.Role, _api.CurrentUser.Email, generateThumbnail: true, token: ct);
SourceEnum.AI, new MemoryStream(a.Image), _api.CurrentUser.Role, _api.CurrentUser.Email, token: ct);
}
//Manual
public async Task<Annotation> SaveAnnotation(string originalMediaName, TimeSpan time, List<Detection> detections, Stream? stream = null, CancellationToken token = default) =>
await SaveAnnotationInner(DateTime.UtcNow, originalMediaName, time, detections, SourceEnum.Manual, stream,
_api.CurrentUser.Role, _api.CurrentUser.Email, generateThumbnail: true, token: token);
//Manual Validate existing
public async Task ValidateAnnotation(Annotation annotation, CancellationToken token = default) =>
await SaveAnnotationInner(DateTime.UtcNow, annotation.OriginalMediaName, annotation.Time, annotation.Detections.ToList(), SourceEnum.Manual, null,
_api.CurrentUser.Role, _api.CurrentUser.Email, token: token);
// Manual save from Validators -> Validated -> stream: azaion-annotations-confirm
@@ -124,11 +118,9 @@ public class AnnotationService : INotificationHandler<AnnotationsDeletedEvent>
private async Task<Annotation> SaveAnnotationInner(DateTime createdDate, string originalMediaName, TimeSpan time, List<Detection> detections, SourceEnum source, Stream? stream,
RoleEnum userRole,
string createdEmail,
bool generateThumbnail = false,
bool fromQueue = false,
CancellationToken token = default)
{
AnnotationStatus status;
var fName = originalMediaName.ToTimeName(time);
var annotation = await _dbFactory.Run(async db =>
@@ -179,13 +171,10 @@ public class AnnotationService : INotificationHandler<AnnotationsDeletedEvent>
img.Save(annotation.ImagePath, ImageFormat.Jpeg); //todo: check png images coming from queue
}
await YoloLabel.WriteToFile(detections, annotation.LabelPath, token);
if (generateThumbnail)
{
await _galleryService.CreateThumbnail(annotation, token);
if (_uiConfig.GenerateAnnotatedImage)
await _galleryService.CreateAnnotatedImage(annotation, token);
}
if (!fromQueue) //Send to queue only if we're not getting from queue already
await _producer.SendToInnerQueue(annotation, token);
@@ -195,10 +184,32 @@ public class AnnotationService : INotificationHandler<AnnotationsDeletedEvent>
{
_dbFactory.SaveToDisk();
await Task.CompletedTask;
}, SaveTaskId, TimeSpan.FromSeconds(5));
}, SaveTaskId, TimeSpan.FromSeconds(5), true);
return annotation;
}
public async Task ValidateAnnotations(List<Annotation> annotations, CancellationToken token = default)
{
if (!_api.CurrentUser.Role.IsValidator())
return;
var annNames = annotations.Select(x => x.Name).ToHashSet();
await _dbFactory.Run(async db =>
{
await db.Annotations
.Where(x => annNames.Contains(x.Name))
.Set(x => x.AnnotationStatus, AnnotationStatus.Validated)
.Set(x => x.ValidateDate, DateTime.UtcNow)
.Set(x => x.ValidateEmail, _api.CurrentUser.Email)
.UpdateAsync(token: token);
});
ThrottleExt.Throttle(async () =>
{
_dbFactory.SaveToDisk();
await Task.CompletedTask;
}, SaveTaskId, TimeSpan.FromSeconds(5), true);
}
public async Task Handle(AnnotationsDeletedEvent notification, CancellationToken cancellationToken)
{
await _dbFactory.DeleteAnnotations(notification.Annotations, cancellationToken);
@@ -2,6 +2,7 @@
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using Azaion.Common.Database;
using Azaion.Common.DTO;
using Azaion.Common.DTO.Queue;
using Azaion.Common.Events;
@@ -96,8 +97,14 @@ public class DatasetExplorerEventHandler(
var annotations = datasetExplorer.ThumbnailsView.SelectedItems.Cast<AnnotationThumbnail>()
.Select(x => x.Annotation)
.ToList();
foreach (var annotation in annotations)
await annotationService.ValidateAnnotation(annotation, cancellationToken);
await annotationService.ValidateAnnotations(annotations, cancellationToken);
foreach (var ann in datasetExplorer.SelectedAnnotations.Where(x => annotations.Contains(x.Annotation)))
{
ann.Annotation.AnnotationStatus = AnnotationStatus.Validated;
if (datasetExplorer.SelectedAnnotationDict.TryGetValue(ann.Annotation.Name, out var value))
value.Annotation.AnnotationStatus = AnnotationStatus.Validated;
ann.UpdateUI();
}
break;
}
}
+2 -1
View File
@@ -24,6 +24,7 @@
},
"UIConfig": {
"LeftPanelWidth": 170.0,
"RightPanelWidth": 120.0
"RightPanelWidth": 120.0,
"GenerateAnnotatedImage": true
}
}