diff --git a/Azaion.Annotator/Annotator.xaml.cs b/Azaion.Annotator/Annotator.xaml.cs index 1c52a90..829cabe 100644 --- a/Azaion.Annotator/Annotator.xaml.cs +++ b/Azaion.Annotator/Annotator.xaml.cs @@ -7,6 +7,7 @@ using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; +using System.Windows.Threading; using Azaion.Annotator.DTO; using Azaion.Annotator.Extensions; using Azaion.Common; @@ -513,10 +514,6 @@ public partial class Annotator _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.Play)); _mediaPlayer.SetPause(true); - var mediaInfo = (MediaFileInfo)LvFiles.SelectedItem; - _formState.CurrentMedia = mediaInfo; - var path = mediaInfo.Path; - var manualCancellationSource = new CancellationTokenSource(); var token = manualCancellationSource.Token; @@ -534,40 +531,81 @@ public partial class Annotator _autoDetectDialog.Top = Height - _autoDetectDialog.Height - 80; _autoDetectDialog.Left = 5; + _autoDetectDialog.Log("Ініціалізація AI..."); + _ = Task.Run(async () => { - Dispatcher.Invoke(() => _autoDetectDialog.Log("Ініціалізація AI...")); - var prevSeekTime = 0.0; - - await foreach (var timeframe in _vlcFrameExtractor.ExtractFrames(path, token)) + MediaFileInfo mediaInfo = null!; + Dispatcher.Invoke(() => { - try - { - var detections = await _aiDetector.Detect(timeframe.Stream, token); - if (timeframe.Time.TotalSeconds > prevSeekTime + 1) - { - Dispatcher.Invoke(() => SeekTo(timeframe.Time)); - prevSeekTime = timeframe.Time.TotalSeconds; - } + mediaInfo = (MediaFileInfo)LvFiles.SelectedItem; + }); - if (!IsValidDetection(timeframe.Time, detections)) - continue; - - await ProcessDetection(timeframe, detections, token); - } - catch (Exception ex) + while (mediaInfo != null) + { + _formState.CurrentMedia = mediaInfo; + if (mediaInfo.MediaType == MediaTypes.Image) { - _logger.LogError(ex, ex.Message); - await manualCancellationSource.CancelAsync(); + await DetectImage(mediaInfo, manualCancellationSource, token); } + else + await DetectVideo(mediaInfo, manualCancellationSource, token); + + mediaInfo = Dispatcher.Invoke(() => + { + LvFiles.SelectedIndex += 1; + return (MediaFileInfo)LvFiles.SelectedItem; + }); } Dispatcher.Invoke(() => _autoDetectDialog.Close()); }, token); - _autoDetectDialog.ShowDialog(); + _autoDetectDialog.ShowDialog(); Dispatcher.Invoke(() => Editor.Background = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0))); } + private async Task DetectImage(MediaFileInfo mediaInfo, CancellationTokenSource manualCancellationSource, CancellationToken token) + { + try + { + var stream = new FileStream(mediaInfo.Path, FileMode.Open); + var detections = await _aiDetector.Detect(stream, token); + await ProcessDetection((TimeSpan.FromMilliseconds(0), stream), detections, token); + } + catch (Exception e) + { + _logger.LogError(e, e.Message); + await manualCancellationSource.CancelAsync(); + } + } + + private async Task DetectVideo(MediaFileInfo mediaInfo, CancellationTokenSource manualCancellationSource, CancellationToken token) + { + var prevSeekTime = 0.0; + await foreach (var timeframe in _vlcFrameExtractor.ExtractFrames(mediaInfo.Path, token)) + { + try + { + var detections = await _aiDetector.Detect(timeframe.Stream, token); + if (timeframe.Time.TotalSeconds > prevSeekTime + 1) + { + Dispatcher.Invoke(() => SeekTo(timeframe.Time)); + prevSeekTime = timeframe.Time.TotalSeconds; + } + + if (!IsValidDetection(timeframe.Time, detections)) + continue; + + await ProcessDetection(timeframe, detections, token); + } + catch (Exception ex) + { + _logger.LogError(ex, ex.Message); + await manualCancellationSource.CancelAsync(); + } + } + } + private bool IsValidDetection(TimeSpan time, List detections) { // No AI detection, forbid diff --git a/Azaion.Common/Services/ResourceLoader.cs b/Azaion.Common/Services/ResourceLoader.cs index 8eaf052..0832521 100644 --- a/Azaion.Common/Services/ResourceLoader.cs +++ b/Azaion.Common/Services/ResourceLoader.cs @@ -23,8 +23,18 @@ public class ResourceLoader(AzaionApiClient api, ApiCredentials credentials) : I var assemblyName = resourceName.Split(',').First(); if (EncryptedResources.Contains(assemblyName)) { - var stream = Load($"{assemblyName}.dll").GetAwaiter().GetResult(); - return Assembly.Load(stream.ToArray()); + try + { + var stream = Load($"{assemblyName}.dll").GetAwaiter().GetResult(); + return Assembly.Load(stream.ToArray()); + } + catch (Exception e) + { + Console.WriteLine(e); + var currentLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!; + var dllPath = Path.Combine(currentLocation, "dummy", $"{assemblyName}.dll"); + return Assembly.LoadFile(dllPath); + } } var loadedAssembly = AppDomain.CurrentDomain.GetAssemblies() diff --git a/Azaion.Launcher/Loader.xaml b/Azaion.Launcher/Loader.xaml index 18bbea9..9f17f8b 100644 --- a/Azaion.Launcher/Loader.xaml +++ b/Azaion.Launcher/Loader.xaml @@ -74,14 +74,13 @@ BorderBrush="DimGray" BorderThickness="0,0,0,1" HorizontalAlignment="Left" - Text="admin@azaion.com"/> + /> (context.Configuration); services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/Dummy/Azaion.Annotator.dll b/Dummy/Azaion.Annotator.dll new file mode 100644 index 0000000..da7c522 Binary files /dev/null and b/Dummy/Azaion.Annotator.dll differ diff --git a/Dummy/Azaion.Annotator/Annotator.xaml b/Dummy/Azaion.Annotator/Annotator.xaml new file mode 100644 index 0000000..acd521e --- /dev/null +++ b/Dummy/Azaion.Annotator/Annotator.xaml @@ -0,0 +1,25 @@ + + + + Будь ласка перевірте правильність email чи паролю! + Також зауважте, що запуск можливий лише з одного конкретного компьютера, копіювання заборонене! + Для подальшого вирішення проблеми ви моежете зв'язатися з нами: hi@azaion.com + + Please check your email or password! + The program is restricted to start only from particular hardware, copying is forbidden! + For the further guidance, please feel free to contact us: hi@azaion.com + + diff --git a/Dummy/Azaion.Annotator/Annotator.xaml.cs b/Dummy/Azaion.Annotator/Annotator.xaml.cs new file mode 100644 index 0000000..067b45b --- /dev/null +++ b/Dummy/Azaion.Annotator/Annotator.xaml.cs @@ -0,0 +1,9 @@ +namespace Azaion.Annotator; + +public partial class Annotator +{ + public Annotator() + { + InitializeComponent(); + } +} diff --git a/Dummy/Azaion.Annotator/AnnotatorEventHandler.cs b/Dummy/Azaion.Annotator/AnnotatorEventHandler.cs new file mode 100644 index 0000000..d27500f --- /dev/null +++ b/Dummy/Azaion.Annotator/AnnotatorEventHandler.cs @@ -0,0 +1,3 @@ +namespace Azaion.Annotator; + +public class AnnotatorEventHandler; diff --git a/Dummy/Azaion.Annotator/AnnotatorModule.cs b/Dummy/Azaion.Annotator/AnnotatorModule.cs new file mode 100644 index 0000000..2df179a --- /dev/null +++ b/Dummy/Azaion.Annotator/AnnotatorModule.cs @@ -0,0 +1,54 @@ +using Azaion.Common.DTO; + +namespace Azaion.Annotator; + +public class AnnotatorModule : IAzaionModule +{ + public string Name => "Анотатор"; + + public string SvgIcon => +@" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +"; + + public Type MainWindowType => typeof(Annotator); + + public WindowEnum WindowEnum => WindowEnum.Annotator; +} \ No newline at end of file diff --git a/Dummy/Azaion.Annotator/AssemblyInfo.cs b/Dummy/Azaion.Annotator/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/Dummy/Azaion.Annotator/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/Dummy/Azaion.Annotator/Azaion.Annotator.csproj b/Dummy/Azaion.Annotator/Azaion.Annotator.csproj new file mode 100644 index 0000000..3c68237 --- /dev/null +++ b/Dummy/Azaion.Annotator/Azaion.Annotator.csproj @@ -0,0 +1,41 @@ + + + + enable + enable + true + net8.0-windows + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Dummy/Azaion.Annotator/DTO/FormState.cs b/Dummy/Azaion.Annotator/DTO/FormState.cs new file mode 100644 index 0000000..ae14d69 --- /dev/null +++ b/Dummy/Azaion.Annotator/DTO/FormState.cs @@ -0,0 +1,3 @@ +namespace Azaion.Annotator.DTO; + +public class FormState; \ No newline at end of file diff --git a/Dummy/Azaion.Annotator/Extensions/VLCFrameExtractor.cs b/Dummy/Azaion.Annotator/Extensions/VLCFrameExtractor.cs new file mode 100644 index 0000000..7887ba9 --- /dev/null +++ b/Dummy/Azaion.Annotator/Extensions/VLCFrameExtractor.cs @@ -0,0 +1,3 @@ +namespace Azaion.Annotator.Extensions; + +public class VLCFrameExtractor; \ No newline at end of file diff --git a/Dummy/Azaion.Annotator/HelpWindow.xaml b/Dummy/Azaion.Annotator/HelpWindow.xaml new file mode 100644 index 0000000..a15a573 --- /dev/null +++ b/Dummy/Azaion.Annotator/HelpWindow.xaml @@ -0,0 +1,11 @@ + + diff --git a/Dummy/Azaion.Annotator/HelpWindow.xaml.cs b/Dummy/Azaion.Annotator/HelpWindow.xaml.cs new file mode 100644 index 0000000..4031078 --- /dev/null +++ b/Dummy/Azaion.Annotator/HelpWindow.xaml.cs @@ -0,0 +1,3 @@ +namespace Azaion.Annotator; + +public partial class HelpWindow; \ No newline at end of file diff --git a/Dummy/Azaion.Annotator/YOLODetector.cs b/Dummy/Azaion.Annotator/YOLODetector.cs new file mode 100644 index 0000000..ead825e --- /dev/null +++ b/Dummy/Azaion.Annotator/YOLODetector.cs @@ -0,0 +1,5 @@ +namespace Azaion.Annotator; + +public interface IAIDetector; + +public class YOLODetector : IAIDetector; diff --git a/Dummy/Azaion.Dataset.dll b/Dummy/Azaion.Dataset.dll new file mode 100644 index 0000000..341ff74 Binary files /dev/null and b/Dummy/Azaion.Dataset.dll differ diff --git a/Dummy/Azaion.Dataset/AssemblyInfo.cs b/Dummy/Azaion.Dataset/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/Dummy/Azaion.Dataset/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/Dummy/Azaion.Dataset/Azaion.Dataset.csproj b/Dummy/Azaion.Dataset/Azaion.Dataset.csproj new file mode 100644 index 0000000..85c6517 --- /dev/null +++ b/Dummy/Azaion.Dataset/Azaion.Dataset.csproj @@ -0,0 +1,28 @@ + + + + net8.0-windows + enable + enable + true + + + + + MSBuild:Compile + Wpf + Designer + + + + + + + + + + + + + + diff --git a/Dummy/Azaion.Dataset/BitmapExtensions.cs b/Dummy/Azaion.Dataset/BitmapExtensions.cs new file mode 100644 index 0000000..cb54e6a --- /dev/null +++ b/Dummy/Azaion.Dataset/BitmapExtensions.cs @@ -0,0 +1,19 @@ +using System.IO; +using System.Windows.Media.Imaging; + +namespace Azaion.Dataset; + +public static class BitmapExtensions +{ + public static async Task OpenImage(this string imagePath) + { + var image = new BitmapImage(); + await using var stream = File.OpenRead(imagePath); + image.BeginInit(); + image.CacheOption = BitmapCacheOption.OnLoad; + image.StreamSource = stream; + image.EndInit(); + image.Freeze(); + return image; + } +} \ No newline at end of file diff --git a/Dummy/Azaion.Dataset/DatasetExplorer.xaml b/Dummy/Azaion.Dataset/DatasetExplorer.xaml new file mode 100644 index 0000000..9b78e59 --- /dev/null +++ b/Dummy/Azaion.Dataset/DatasetExplorer.xaml @@ -0,0 +1,24 @@ + + + + Будь ласка перевірте правильність email чи паролю! + Також зауважте, що запуск можливий лише з одного конкретного компьютера, копіювання заборонене! + Для подальшого вирішення проблеми ви моежете зв'язатися з нами: hi@azaion.com + + Please check your email or password! + The program is restricted to start only from particular hardware, copying is forbidden! + For the further guidance, please feel free to contact us: hi@azaion.com + + diff --git a/Dummy/Azaion.Dataset/DatasetExplorer.xaml.cs b/Dummy/Azaion.Dataset/DatasetExplorer.xaml.cs new file mode 100644 index 0000000..c7fc94e --- /dev/null +++ b/Dummy/Azaion.Dataset/DatasetExplorer.xaml.cs @@ -0,0 +1,3 @@ +namespace Azaion.Dataset; + +public partial class DatasetExplorer; \ No newline at end of file diff --git a/Dummy/Azaion.Dataset/DatasetExplorerModule.cs b/Dummy/Azaion.Dataset/DatasetExplorerModule.cs new file mode 100644 index 0000000..c907ec5 --- /dev/null +++ b/Dummy/Azaion.Dataset/DatasetExplorerModule.cs @@ -0,0 +1,25 @@ +using Azaion.Common.DTO; + +namespace Azaion.Dataset; + +public class DatasetExplorerModule : IAzaionModule +{ + public string Name => "Переглядач"; + + public string SvgIcon => + @" + + + + + + + + + +"; + + public Type MainWindowType => typeof(DatasetExplorer); + + public WindowEnum WindowEnum => WindowEnum.DatasetExplorer; +} \ No newline at end of file diff --git a/Dummy/Azaion.Dataset/GalleryManager.cs b/Dummy/Azaion.Dataset/GalleryManager.cs new file mode 100644 index 0000000..7aeb993 --- /dev/null +++ b/Dummy/Azaion.Dataset/GalleryManager.cs @@ -0,0 +1,24 @@ +using System.Collections.Concurrent; +using System.Drawing; +using System.IO; +using Azaion.Annotator.Extensions; +using Azaion.Common; +using Azaion.Common.DTO; +using Azaion.Common.Extensions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using Color = System.Drawing.Color; +using ParallelOptions = Azaion.Annotator.Extensions.ParallelOptions; +using Size = System.Windows.Size; +using System.Drawing.Imaging; +using System.Drawing.Drawing2D; +using Azaion.Common.DTO.Config; + +namespace Azaion.Dataset; + +public delegate void ThumbnailsUpdatedEventHandler(double thumbnailsPercentage); + +public class GalleryManager : IGalleryManager; + +public interface IGalleryManager; \ No newline at end of file