diff --git a/Azaion.Annotator/Annotator.xaml.cs b/Azaion.Annotator/Annotator.xaml.cs index ad99090..8b9a332 100644 --- a/Azaion.Annotator/Annotator.xaml.cs +++ b/Azaion.Annotator/Annotator.xaml.cs @@ -331,14 +331,11 @@ public partial class Annotator { try { - _logger.LogInformation($"remove annotation {existingResult.TimeStr} {existingResult.ClassName}!"); _formState.AnnotationResults.Remove(existingResult); - _logger.LogInformation($"removed {existingResult.TimeStr} {existingResult.ClassName} sucessfully!"); } catch (Exception e) { _logger.LogError(e, e.Message); - //Console.WriteLine(e); throw; } diff --git a/Azaion.Common/Constants.cs b/Azaion.Common/Constants.cs index 4aef98b..4f8287e 100644 --- a/Azaion.Common/Constants.cs +++ b/Azaion.Common/Constants.cs @@ -63,6 +63,7 @@ public class Constants public const int DEFAULT_THUMBNAIL_BORDER = 10; public const string THUMBNAIL_PREFIX = "_thumb"; + public const string RESULT_PREFIX = "_result"; #endregion diff --git a/Azaion.Common/Controls/DetectionControl.cs b/Azaion.Common/Controls/DetectionControl.cs index d613c6b..80d9edc 100644 --- a/Azaion.Common/Controls/DetectionControl.cs +++ b/Azaion.Common/Controls/DetectionControl.cs @@ -121,7 +121,7 @@ public class DetectionControl : Border var rect = new Rectangle() // small rectangles at the corners and sides { ClipToBounds = false, - Margin = new Thickness(-RESIZE_RECT_SIZE), + Margin = new Thickness(-RESIZE_RECT_SIZE * 0.7), HorizontalAlignment = ha, VerticalAlignment = va, Width = RESIZE_RECT_SIZE, diff --git a/Azaion.Common/DTO/Config/AppConfig.cs b/Azaion.Common/DTO/Config/AppConfig.cs index f4971d3..662a14a 100644 --- a/Azaion.Common/DTO/Config/AppConfig.cs +++ b/Azaion.Common/DTO/Config/AppConfig.cs @@ -58,6 +58,7 @@ public class ConfigUpdater : IConfigUpdater { LeftPanelWidth = Constants.DEFAULT_LEFT_PANEL_WIDTH, RightPanelWidth = Constants.DEFAULT_RIGHT_PANEL_WIDTH, + GenerateAnnotatedImage = false }, DirectoriesConfig = new DirectoriesConfig diff --git a/Azaion.Common/DTO/Config/UIConfig.cs b/Azaion.Common/DTO/Config/UIConfig.cs index ca07a01..9b4036e 100644 --- a/Azaion.Common/DTO/Config/UIConfig.cs +++ b/Azaion.Common/DTO/Config/UIConfig.cs @@ -4,4 +4,5 @@ public class UIConfig { public double LeftPanelWidth { get; set; } public double RightPanelWidth { get; set; } -} \ No newline at end of file + public bool GenerateAnnotatedImage { get; set; } +} diff --git a/Azaion.Common/Services/AnnotationService.cs b/Azaion.Common/Services/AnnotationService.cs index 97f0704..5b528bf 100644 --- a/Azaion.Common/Services/AnnotationService.cs +++ b/Azaion.Common/Services/AnnotationService.cs @@ -30,6 +30,7 @@ public class AnnotationService : INotificationHandler private readonly IAuthProvider _authProvider; private readonly QueueConfig _queueConfig; private Consumer _consumer = null!; + private readonly UIConfig _uiConfig; private static readonly Guid SaveTaskId = Guid.NewGuid(); public AnnotationService( @@ -37,6 +38,7 @@ public class AnnotationService : INotificationHandler IDbFactory dbFactory, FailsafeAnnotationsProducer producer, IOptions queueConfig, + IOptions uiConfig, IGalleryService galleryService, IMediator mediator, IHardwareService hardwareService, @@ -49,6 +51,7 @@ public class AnnotationService : INotificationHandler _hardwareService = hardwareService; _authProvider = authProvider; _queueConfig = queueConfig.Value; + _uiConfig = uiConfig.Value; Task.Run(async () => await Init()).Wait(); } @@ -184,7 +187,12 @@ public class AnnotationService : INotificationHandler } 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); diff --git a/Azaion.Common/Services/GalleryService.cs b/Azaion.Common/Services/GalleryService.cs index 2589397..65d8526 100644 --- a/Azaion.Common/Services/GalleryService.cs +++ b/Azaion.Common/Services/GalleryService.cs @@ -265,6 +265,24 @@ public class GalleryService( logger.LogError(e, e.Message); } } + + public async Task CreateAnnotatedImage(Annotation annotation, CancellationToken token) + { + var originalImage = Image.FromStream(new MemoryStream(await File.ReadAllBytesAsync(annotation.ImagePath, token))); + + using var g = Graphics.FromImage(originalImage); + foreach (var detection in annotation.Detections) + { + var detClass = _annotationConfig.DetectionClassesDict[detection.ClassNumber]; + var color = detClass.Color; + var brush = new SolidBrush(Color.FromArgb(color.A, color.R, color.G, color.B)); + var det = new CanvasLabel(detection, new Size(originalImage.Width, originalImage.Height)); + g.DrawRectangle(new Pen(brush, width: 3), (float)det.X, (float)det.Y, (float)det.Width, (float)det.Height); + var label = detection.Confidence >= 0.995 ? detClass.UIName : $"{detClass.UIName}: {detection.Confidence * 100:F0}%"; + g.DrawString(label, new Font(FontFamily.GenericSerif, 14), brush, new PointF((float)(det.X + det.Width / 2.0), (float)det.Y)); + } + originalImage.Save(Path.Combine(_dirConfig.ResultsDirectory, $"{annotation.Name}{Constants.RESULT_PREFIX}.jpg"), ImageFormat.Jpeg); + } } public interface IGalleryService @@ -275,4 +293,5 @@ public interface IGalleryService Task RefreshThumbnails(); Task ClearThumbnails(CancellationToken cancellationToken = default); + Task CreateAnnotatedImage(Annotation annotation, CancellationToken token); } \ No newline at end of file diff --git a/Azaion.Inference/azaion-inference.spec b/Azaion.Inference/azaion-inference.spec index 37f6901..a01fda6 100644 --- a/Azaion.Inference/azaion-inference.spec +++ b/Azaion.Inference/azaion-inference.spec @@ -4,8 +4,6 @@ from PyInstaller.utils.hooks import collect_all datas = [] binaries = [] hiddenimports = ['constants', 'annotation', 'credentials', 'file_data', 'user', 'security', 'secure_model', 'api_client', 'hardware_service', 'remote_command', 'ai_config', 'inference_engine', 'inference', 'remote_command_handler'] -tmp_ret = collect_all('pyyaml') -datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] tmp_ret = collect_all('jwt') datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] tmp_ret = collect_all('requests') diff --git a/Azaion.Suite/Azaion.Suite.csproj b/Azaion.Suite/Azaion.Suite.csproj index 4805b16..e4fea8c 100644 --- a/Azaion.Suite/Azaion.Suite.csproj +++ b/Azaion.Suite/Azaion.Suite.csproj @@ -32,8 +32,8 @@ - - + + @@ -61,8 +61,8 @@ - - + + diff --git a/Azaion.Suite/Login.xaml b/Azaion.Suite/Login.xaml index 64b3bce..8b419d6 100644 --- a/Azaion.Suite/Login.xaml +++ b/Azaion.Suite/Login.xaml @@ -74,7 +74,7 @@ BorderBrush="DimGray" BorderThickness="0,0,0,1" HorizontalAlignment="Left" - Text="admin@azaion.com" + Text="" /> + Password=""/>