From 961d2499deceb6d4ab41bac12d2bc713e43b9b3b Mon Sep 17 00:00:00 2001 From: Alex Bezdieniezhnykh Date: Fri, 14 Feb 2025 09:00:04 +0200 Subject: [PATCH] fix inference fix small issues --- Azaion.Annotator/Annotator.xaml.cs | 17 +++++++++++------ Azaion.Common/DTO/Config/AIRecognitionConfig.cs | 4 ++-- Azaion.Common/Database/Annotation.cs | 2 +- Azaion.Common/Database/DbFactory.cs | 1 + Azaion.Common/Extensions/ThrottleExtensions.cs | 1 + .../Services/PythonResourceLoader.cs | 2 +- Azaion.Dataset/DatasetExplorer.xaml.cs | 4 +++- Azaion.Dataset/DatasetExplorerEventHandler.cs | 2 ++ Azaion.Inference/ai_config.pxd | 1 + Azaion.Inference/ai_config.pyx | 14 ++++++++++---- Azaion.Inference/api_client.pxd | 2 +- Azaion.Inference/api_client.pyx | 8 ++++---- Azaion.Inference/inference.pyx | 5 ++--- Azaion.Inference/main.pyx | 3 ++- Dummy/Azaion.Annotator/YOLODetector.cs | 5 ----- 15 files changed, 42 insertions(+), 29 deletions(-) delete mode 100644 Dummy/Azaion.Annotator/YOLODetector.cs diff --git a/Azaion.Annotator/Annotator.xaml.cs b/Azaion.Annotator/Annotator.xaml.cs index d72454b..d3ee97e 100644 --- a/Azaion.Annotator/Annotator.xaml.cs +++ b/Azaion.Annotator/Annotator.xaml.cs @@ -520,21 +520,26 @@ public partial class Annotator var files = new List(); await Dispatcher.Invoke(async () => { + //Take not annotated medias files = (LvFiles.ItemsSource as IEnumerable)?.Skip(LvFiles.SelectedIndex) .Take(Constants.DETECTION_BATCH_SIZE) + .Where(x => !x.HasAnnotations) .Select(x => x.Path) - .ToList(); - await _mediator.Publish(new AnnotatorControlEvent(PlaybackControlEnum.Play), ct); - await ReloadAnnotations(); + .ToList() ?? []; + if (files.Count != 0) + { + await _mediator.Publish(new AnnotatorControlEvent(PlaybackControlEnum.Play), ct); + await ReloadAnnotations(); + } }); + if (files.Count == 0) + break; + await _inferenceService.RunInference(files, async annotationImage => await ProcessDetection(annotationImage), ct); Dispatcher.Invoke(() => { - if (LvFiles.SelectedIndex + files.Count >= LvFiles.Items.Count) - DetectionCancellationSource.Cancel(); - LvFiles.SelectedIndex += files.Count; LvFiles.Items.Refresh(); }); diff --git a/Azaion.Common/DTO/Config/AIRecognitionConfig.cs b/Azaion.Common/DTO/Config/AIRecognitionConfig.cs index 6b4f894..e4087cb 100644 --- a/Azaion.Common/DTO/Config/AIRecognitionConfig.cs +++ b/Azaion.Common/DTO/Config/AIRecognitionConfig.cs @@ -13,6 +13,6 @@ public class AIRecognitionConfig [Key(nameof(TrackingProbabilityIncrease))] public double TrackingProbabilityIncrease { get; set; } [Key(nameof(TrackingIntersectionThreshold))] public double TrackingIntersectionThreshold { get; set; } - [Key(nameof(Data))] public byte[] Data { get; set; } - [Key(nameof(Paths))] public List Paths { get; set; } + [Key(nameof(Data))] public byte[] Data { get; set; } = null!; + [Key(nameof(Paths))] public List Paths { get; set; } = null!; } \ No newline at end of file diff --git a/Azaion.Common/Database/Annotation.cs b/Azaion.Common/Database/Annotation.cs index 00c8dbf..b77e41e 100644 --- a/Azaion.Common/Database/Annotation.cs +++ b/Azaion.Common/Database/Annotation.cs @@ -49,7 +49,7 @@ public class Annotation [MessagePackObject] public class AnnotationImage : Annotation { - [Key("i")] public byte[] Image { get; set; } + [Key("i")] public byte[] Image { get; set; } = null!; } public enum AnnotationStatus diff --git a/Azaion.Common/Database/DbFactory.cs b/Azaion.Common/Database/DbFactory.cs index f4cc148..ba59c0e 100644 --- a/Azaion.Common/Database/DbFactory.cs +++ b/Azaion.Common/Database/DbFactory.cs @@ -105,6 +105,7 @@ public class DbFactory : IDbFactory await db.Detections.DeleteAsync(x => names.Contains(x.AnnotationName), token: cancellationToken); await db.Annotations.DeleteAsync(x => names.Contains(x.Name), token: cancellationToken); }); + SaveToDisk(); } } diff --git a/Azaion.Common/Extensions/ThrottleExtensions.cs b/Azaion.Common/Extensions/ThrottleExtensions.cs index 7a38aee..dfacee2 100644 --- a/Azaion.Common/Extensions/ThrottleExtensions.cs +++ b/Azaion.Common/Extensions/ThrottleExtensions.cs @@ -30,6 +30,7 @@ public static class ThrottleExt await func(); _throttleRunAfter = false; }, cancellationToken); + await Task.CompletedTask; } } \ No newline at end of file diff --git a/Azaion.CommonSecurity/Services/PythonResourceLoader.cs b/Azaion.CommonSecurity/Services/PythonResourceLoader.cs index 5968477..1af161f 100644 --- a/Azaion.CommonSecurity/Services/PythonResourceLoader.cs +++ b/Azaion.CommonSecurity/Services/PythonResourceLoader.cs @@ -25,7 +25,7 @@ public class PythonResourceLoader : IResourceLoader, IAuthProvider private readonly DealerSocket _dealer = new(); private readonly Guid _clientId = Guid.NewGuid(); - public User CurrentUser { get; set; } + public User CurrentUser { get; set; } = null!; public PythonResourceLoader() { diff --git a/Azaion.Dataset/DatasetExplorer.xaml.cs b/Azaion.Dataset/DatasetExplorer.xaml.cs index b9fb4f7..d5c1561 100644 --- a/Azaion.Dataset/DatasetExplorer.xaml.cs +++ b/Azaion.Dataset/DatasetExplorer.xaml.cs @@ -22,7 +22,7 @@ public partial class DatasetExplorer private readonly AnnotationConfig _annotationConfig; private readonly DirectoriesConfig _directoriesConfig; - private Dictionary> _annotationsDict; + private Dictionary> _annotationsDict = new(); private readonly CancellationTokenSource _cts = new(); public ObservableCollection AllDetectionClasses { get; set; } = new(); @@ -191,6 +191,7 @@ public partial class DatasetExplorer ClassDistribution.Plot.FigureBackground.Color = new("#888888"); ClassDistribution.Refresh(); + await Task.CompletedTask; } private async void RefreshThumbnailsBtnClick(object sender, RoutedEventArgs e) @@ -294,6 +295,7 @@ public partial class DatasetExplorer SelectedAnnotations.Add(annThumb); SelectedAnnotationDict.Add(annThumb.Annotation.Name, annThumb); } + await Task.CompletedTask; } private async void ValidateAnnotationsClick(object sender, RoutedEventArgs e) diff --git a/Azaion.Dataset/DatasetExplorerEventHandler.cs b/Azaion.Dataset/DatasetExplorerEventHandler.cs index 3a0951a..10fa47f 100644 --- a/Azaion.Dataset/DatasetExplorerEventHandler.cs +++ b/Azaion.Dataset/DatasetExplorerEventHandler.cs @@ -100,6 +100,7 @@ public class DatasetExplorerEventHandler( datasetExplorer.SelectedAnnotations.Add(annThumb); datasetExplorer.SelectedAnnotationDict.Add(annThumb.Annotation.Name, annThumb); } + await Task.CompletedTask; } public async Task Handle(AnnotationsDeletedEvent notification, CancellationToken cancellationToken) @@ -114,5 +115,6 @@ public class DatasetExplorerEventHandler( datasetExplorer.SelectedAnnotations.Remove(annThumb); datasetExplorer.SelectedAnnotationDict.Remove(annThumb.Annotation.Name); } + await Task.CompletedTask; } } diff --git a/Azaion.Inference/ai_config.pxd b/Azaion.Inference/ai_config.pxd index 9bc63b8..b0d32aa 100644 --- a/Azaion.Inference/ai_config.pxd +++ b/Azaion.Inference/ai_config.pxd @@ -8,6 +8,7 @@ cdef class AIRecognitionConfig: cdef public double tracking_intersection_threshold cdef public bytes file_data + cdef public list[str] paths @staticmethod cdef from_msgpack(bytes data) \ No newline at end of file diff --git a/Azaion.Inference/ai_config.pyx b/Azaion.Inference/ai_config.pyx index 3f222ce..d9667ae 100644 --- a/Azaion.Inference/ai_config.pyx +++ b/Azaion.Inference/ai_config.pyx @@ -10,7 +10,8 @@ cdef class AIRecognitionConfig: tracking_probability_increase, tracking_intersection_threshold, - file_data + file_data, + paths ): self.frame_period_recognition = frame_period_recognition self.frame_recognition_seconds = frame_recognition_seconds @@ -21,10 +22,14 @@ cdef class AIRecognitionConfig: self.tracking_intersection_threshold = tracking_intersection_threshold self.file_data = file_data + self.paths = paths def __str__(self): return (f'frame_seconds : {self.frame_recognition_seconds}, distance_confidence : {self.tracking_distance_confidence}, ' - f'probability_increase : {self.tracking_probability_increase}, intersection_threshold : {self.tracking_intersection_threshold}, frame_period_recognition : {self.frame_period_recognition}') + f'probability_increase : {self.tracking_probability_increase}, ' + f'intersection_threshold : {self.tracking_intersection_threshold}, ' + f'frame_period_recognition : {self.frame_period_recognition}, ' + f'paths: {self.paths}') @staticmethod cdef from_msgpack(bytes data): @@ -38,5 +43,6 @@ cdef class AIRecognitionConfig: unpacked.get("TrackingProbabilityIncrease", 0.0), unpacked.get("TrackingIntersectionThreshold", 0.0), - - unpacked.get("Data", b'')) \ No newline at end of file + unpacked.get("Data", b''), + unpacked.get("Paths", []), + ) \ No newline at end of file diff --git a/Azaion.Inference/api_client.pxd b/Azaion.Inference/api_client.pxd index eae86b8..4407551 100644 --- a/Azaion.Inference/api_client.pxd +++ b/Azaion.Inference/api_client.pxd @@ -12,7 +12,7 @@ cdef class ApiClient: cdef set_token(self, str token) cdef get_user(self) - cdef load_bytes(self, FileData file_data) + cdef load_bytes(self, str filename, str folder=*) cdef load_ai_model(self) cdef load_queue_config(self) diff --git a/Azaion.Inference/api_client.pyx b/Azaion.Inference/api_client.pyx index f82a477..aef5732 100644 --- a/Azaion.Inference/api_client.pyx +++ b/Azaion.Inference/api_client.pyx @@ -60,8 +60,8 @@ cdef class ApiClient: self.login() return self.user - cdef load_bytes(self, FileData file_data): - folder = file_data.folder or self.credentials.folder + cdef load_bytes(self, str filename, str folder=None): + folder = folder or self.credentials.folder hardware_service = HardwareService() cdef HardwareInfo hardware = hardware_service.get_hardware_info() @@ -78,7 +78,7 @@ cdef class ApiClient: { "password": self.credentials.password, "hardware": hardware.to_json_object(), - "fileName": file_data.filename + "fileName": filename }, indent=4) response = requests.post(url, data=payload, headers=headers, stream=True) @@ -97,7 +97,7 @@ cdef class ApiClient: stream = BytesIO(response.raw.read()) data = Security.decrypt_to(stream, key) - print(f'loaded file: {file_data.filename}, {len(data)} bytes') + print(f'loaded file: {filename}, {len(data)} bytes') return data cdef load_ai_model(self): diff --git a/Azaion.Inference/inference.pyx b/Azaion.Inference/inference.pyx index be46b4f..d59e5bd 100644 --- a/Azaion.Inference/inference.pyx +++ b/Azaion.Inference/inference.pyx @@ -20,7 +20,7 @@ cdef class Inference: self.model_width = 0 self.model_height = 0 self.class_names = None - self.ai_config = AIRecognitionConfig(4, 2, 0.25, 0.15, 15, 0.8, b'') + self.ai_config = AIRecognitionConfig(4, 2, 0.25, 0.15, 15, 0.8, b'', []) def init_ai(self): model_bytes = self.api_client.load_ai_model() @@ -114,7 +114,6 @@ cdef class Inference: return chunks cdef run_inference(self, RemoteCommand cmd): - cdef list[str] medias = json.loads( cmd.filename) cdef list[str] videos = [] cdef list[str] images = [] @@ -123,7 +122,7 @@ cdef class Inference: if self.session is None: self.init_ai() - for m in medias: + for m in self.ai_config.paths: if self.is_video(m): videos.append(m) else: diff --git a/Azaion.Inference/main.pyx b/Azaion.Inference/main.pyx index 452821e..96f06dc 100644 --- a/Azaion.Inference/main.pyx +++ b/Azaion.Inference/main.pyx @@ -66,7 +66,8 @@ cdef class CommandProcessor: self.remote_handler.send(command.client_id, user.serialize()) cdef load_file(self, RemoteCommand command): - response = self.api_client.load_bytes(FileData.from_msgpack(command.data)) + cdef FileData file_data = FileData.from_msgpack(command.data) + response = self.api_client.load_bytes(file_data.filename, file_data.folder) self.remote_handler.send(command.client_id, response) cdef on_annotation(self, RemoteCommand cmd, Annotation annotation): diff --git a/Dummy/Azaion.Annotator/YOLODetector.cs b/Dummy/Azaion.Annotator/YOLODetector.cs deleted file mode 100644 index ead825e..0000000 --- a/Dummy/Azaion.Annotator/YOLODetector.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Azaion.Annotator; - -public interface IAIDetector; - -public class YOLODetector : IAIDetector;