mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 09:46:30 +00:00
rework to Azaion.Suite, show tabs with annotator and dataset explorer
This commit is contained in:
@@ -102,9 +102,6 @@ public partial class Annotator
|
||||
|
||||
if (LvFiles.Items.IsEmpty)
|
||||
BlinkHelp(HelpTexts.HelpTextsDict[HelpTextEnum.Initial]);
|
||||
|
||||
if (_appConfig.WindowConfig.ShowHelpOnStart)
|
||||
_helpWindow.Show();
|
||||
}
|
||||
|
||||
public void BlinkHelp(string helpText, int times = 2)
|
||||
@@ -541,7 +538,6 @@ public partial class Annotator
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
using var detector = new YOLODetector(_appConfig.AIRecognitionConfig);
|
||||
Dispatcher.Invoke(() => _autoDetectDialog.Log("Ініціалізація AI..."));
|
||||
var prevSeekTime = 0.0;
|
||||
|
||||
@@ -549,7 +545,7 @@ public partial class Annotator
|
||||
{
|
||||
try
|
||||
{
|
||||
var detections = _aiDetector.Detect(timeframe.Stream);
|
||||
var detections = await _aiDetector.Detect(timeframe.Stream, token);
|
||||
if (timeframe.Time.TotalSeconds > prevSeekTime + 1)
|
||||
{
|
||||
Dispatcher.Invoke(() => SeekTo(timeframe.Time));
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Azaion.Annotator.DTO;
|
||||
using Azaion.Common.DTO;
|
||||
using Azaion.Common.DTO.Config;
|
||||
using LibVLCSharp.Shared;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="libc.translation" Version="7.1.1" />
|
||||
<PackageReference Include="LibVLCSharp" Version="3.8.2" />
|
||||
<PackageReference Include="LibVLCSharp.WPF" Version="3.8.2" />
|
||||
<PackageReference Include="LibVLCSharp" Version="3.9.1" />
|
||||
<PackageReference Include="LibVLCSharp.WPF" Version="3.9.1" />
|
||||
<PackageReference Include="MediatR" Version="12.4.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
|
||||
@@ -26,16 +26,13 @@
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.88.9" />
|
||||
<PackageReference Include="VideoLAN.LibVLC.Windows" Version="3.0.20" />
|
||||
<PackageReference Include="VideoLAN.LibVLC.Windows" Version="3.0.21" />
|
||||
<PackageReference Include="WindowsAPICodePack" Version="7.0.4" />
|
||||
<PackageReference Include="YoloV8.Gpu" Version="5.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="logo.ico" />
|
||||
<None Update="config.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
using System.Windows.Media;
|
||||
using Azaion.Annotator.Extensions;
|
||||
using Azaion.Common.DTO;
|
||||
using Azaion.Common.DTO.Config;
|
||||
using Azaion.Common.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Azaion.Annotator.DTO;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Windows;
|
||||
using Azaion.Common.DTO.Config;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Azaion.Annotator;
|
||||
|
||||
@@ -7,14 +8,19 @@ public partial class HelpWindow : Window
|
||||
{
|
||||
private readonly WindowConfig _windowConfig;
|
||||
|
||||
public HelpWindow(WindowConfig windowConfig)
|
||||
public HelpWindow(IOptions<WindowConfig> windowConfig)
|
||||
{
|
||||
_windowConfig = windowConfig;
|
||||
Loaded += (_, _) => CbShowHelp.IsChecked = windowConfig.ShowHelpOnStart;
|
||||
_windowConfig = windowConfig.Value;
|
||||
Loaded += (_, _) => CbShowHelp.IsChecked = _windowConfig.ShowHelpOnStart;
|
||||
Closing += (sender, args) =>
|
||||
{
|
||||
args.Cancel = true;
|
||||
Visibility = Visibility.Hidden;
|
||||
};
|
||||
InitializeComponent();
|
||||
}
|
||||
private void Close(object sender, RoutedEventArgs e) => Close();
|
||||
|
||||
private void CbShowHelp_OnChecked(object sender, RoutedEventArgs e) => _windowConfig.ShowHelpOnStart = true;
|
||||
private void CbShowHelp_OnUnchecked(object sender, RoutedEventArgs e) => _windowConfig.ShowHelpOnStart = false;
|
||||
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
using Azaion.Annotator.DTO;
|
||||
using Azaion.Annotator.Extensions;
|
||||
using Azaion.Common.DTO;
|
||||
using Azaion.Common.DTO.Config;
|
||||
using Azaion.Common.Services;
|
||||
using Compunet.YoloV8;
|
||||
using Microsoft.Extensions.Options;
|
||||
using SixLabors.ImageSharp;
|
||||
@@ -12,18 +14,27 @@ namespace Azaion.Annotator;
|
||||
|
||||
public interface IAIDetector
|
||||
{
|
||||
List<Detection> Detect(Stream stream);
|
||||
Task<List<Detection>> Detect(Stream imageStream, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public class YOLODetector(AIRecognitionConfig recognitionConfig) : IAIDetector, IDisposable
|
||||
public class YOLODetector(IOptions<AIRecognitionConfig> recognitionConfig, IResourceLoader resourceLoader) : IAIDetector, IDisposable
|
||||
{
|
||||
private readonly YoloPredictor _predictor = new(recognitionConfig.AIModelPath);
|
||||
private readonly AIRecognitionConfig _recognitionConfig = recognitionConfig.Value;
|
||||
private YoloPredictor? _predictor;
|
||||
private const string YOLO_MODEL = "azaion.onnx";
|
||||
|
||||
public List<Detection> Detect(Stream stream)
|
||||
|
||||
public async Task<List<Detection>> Detect(Stream imageStream, CancellationToken cancellationToken)
|
||||
{
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
var image = Image.Load<Rgb24>(stream);
|
||||
var result = _predictor.Detect(image);
|
||||
if (_predictor == null)
|
||||
{
|
||||
await using var stream = await resourceLoader.Load(YOLO_MODEL, cancellationToken);
|
||||
_predictor = new YoloPredictor(stream.ToArray());
|
||||
}
|
||||
|
||||
imageStream.Seek(0, SeekOrigin.Begin);
|
||||
var image = Image.Load<Rgb24>(imageStream);
|
||||
var result = await _predictor.DetectAsync(image);
|
||||
|
||||
var imageSize = new System.Windows.Size(image.Width, image.Height);
|
||||
|
||||
@@ -38,7 +49,7 @@ public class YOLODetector(AIRecognitionConfig recognitionConfig) : IAIDetector,
|
||||
|
||||
private List<Detection> FilterOverlapping(List<Detection> detections)
|
||||
{
|
||||
var k = recognitionConfig.TrackingIntersectionThreshold;
|
||||
var k = _recognitionConfig.TrackingIntersectionThreshold;
|
||||
var filteredDetections = new List<Detection>();
|
||||
for (var i = 0; i < detections.Count; i++)
|
||||
{
|
||||
@@ -73,5 +84,5 @@ public class YOLODetector(AIRecognitionConfig recognitionConfig) : IAIDetector,
|
||||
return filteredDetections;
|
||||
}
|
||||
|
||||
public void Dispose() => _predictor.Dispose();
|
||||
public void Dispose() => _predictor?.Dispose();
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"VideosDirectory": "E:\\Azaion1\\Videos",
|
||||
"LabelsDirectory": "E:\\labels",
|
||||
"ImagesDirectory": "E:\\images",
|
||||
"ThumbnailsDirectory": "E:\\thumbnails",
|
||||
"ResultsDirectory": "E:\\results",
|
||||
"UnknownImages": "E:\\unknown",
|
||||
"AnnotationClasses": [
|
||||
{ "Id": 0, "Name": "Броньована техніка", "ShortName": "Бронь" },
|
||||
{ "Id": 1, "Name": "Вантажівка", "ShortName": "Вантаж" },
|
||||
{ "Id": 2, "Name": "Машина легкова", "ShortName": "Машина" },
|
||||
{ "Id": 3, "Name": "Артилерія", "ShortName": "Арта" },
|
||||
{ "Id": 4, "Name": "Тінь від техніки", "ShortName": "Тінь" },
|
||||
{ "Id": 5, "Name": "Окопи", "ShortName": "Окопи" },
|
||||
{ "Id": 6, "Name": "Військовий", "ShortName": "Військов" },
|
||||
{ "Id": 7, "Name": "Накати", "ShortName": "Накати" },
|
||||
{ "Id": 8, "Name": "Танк з захистом", "ShortName": "Танк захист" },
|
||||
{ "Id": 9, "Name": "Дим", "ShortName": "Дим" },
|
||||
{ "Id": 10, "Name": "Літак", "ShortName": "Літак" }
|
||||
],
|
||||
"MainWindowConfig": {
|
||||
"WindowSize": "1920,1080",
|
||||
"WindowLocation": "50,50",
|
||||
"FullScreen": true
|
||||
},
|
||||
"DatasetExplorerConfig": {
|
||||
"WindowSize": "1920,1080",
|
||||
"WindowLocation": "50,50",
|
||||
"FullScreen": true
|
||||
},
|
||||
"ThumbnailConfig": {
|
||||
"Size": "480,270",
|
||||
"Border": 10
|
||||
},
|
||||
"LeftPanelWidth": 300,
|
||||
"RightPanelWidth": 300,
|
||||
"ShowHelpOnStart": false,
|
||||
"VideoFormats": ["mov", "mp4"],
|
||||
"ImageFormats": ["jpg", "jpeg", "png", "bmp", "gif"],
|
||||
"AIRecognitionConfig": {
|
||||
"AIModelPath": "azaion.onnx",
|
||||
"FrameRecognitionSeconds": 2,
|
||||
"TrackingDistanceConfidence": 0.15,
|
||||
"TrackingProbabilityIncrease": 15,
|
||||
"TrackingIntersectionThreshold": 0.8
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
<PackageReference Include="MediatR" Version="12.4.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
+39
-18
@@ -5,9 +5,17 @@ namespace Azaion.Common;
|
||||
|
||||
public class Constants
|
||||
{
|
||||
#region DefaultConfig
|
||||
|
||||
public const string CONFIG_PATH = "config.json";
|
||||
public const string DEFAULT_DLL_CACHE_DIR = "DllCache";
|
||||
|
||||
#region ApiConfig
|
||||
|
||||
public const string DEFAULT_API_URL = "https://api.azaion.com/";
|
||||
public const int DEFAULT_API_RETRY_COUNT = 3;
|
||||
public const int DEFAULT_API_TIMEOUT_SECONDS = 40;
|
||||
#endregion ApiConfig
|
||||
|
||||
#region DirectoriesConfig
|
||||
|
||||
public const string DEFAULT_VIDEO_DIR = "video";
|
||||
public const string DEFAULT_LABELS_DIR = "labels";
|
||||
@@ -15,24 +23,9 @@ public class Constants
|
||||
public const string DEFAULT_RESULTS_DIR = "results";
|
||||
public const string DEFAULT_THUMBNAILS_DIR = "thumbnails";
|
||||
|
||||
public const int DEFAULT_THUMBNAIL_BORDER = 10;
|
||||
public const double DEFAULT_FRAME_RECOGNITION_SECONDS = 2;
|
||||
public const double TRACKING_DISTANCE_CONFIDENCE = 0.15;
|
||||
public const double TRACKING_PROBABILITY_INCREASE = 15;
|
||||
public const double TRACKING_INTERSECTION_THRESHOLD = 0.8;
|
||||
|
||||
public static readonly Size DefaultWindowSize = new(1280, 720);
|
||||
public static readonly Point DefaultWindowLocation = new(100, 100);
|
||||
public static readonly Size DefaultThumbnailSize = new(240, 135);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Thumbnails
|
||||
|
||||
public const string THUMBNAIL_PREFIX = "_thumb";
|
||||
public const string THUMBNAILS_CACHE_FILE = "thumbnails.cache";
|
||||
|
||||
#endregion
|
||||
#region AnnotatorConfig
|
||||
|
||||
public static readonly List<AnnotationClass> DefaultAnnotationClasses =
|
||||
[
|
||||
@@ -52,6 +45,34 @@ public class Constants
|
||||
public static readonly List<string> DefaultVideoFormats = ["mp4", "mov", "avi"];
|
||||
public static readonly List<string> DefaultImageFormats = ["jpg", "jpeg", "png", "bmp"];
|
||||
|
||||
# endregion AnnotatorConfig
|
||||
|
||||
# region AIRecognitionConfig
|
||||
|
||||
public const double DEFAULT_FRAME_RECOGNITION_SECONDS = 2;
|
||||
public const double TRACKING_DISTANCE_CONFIDENCE = 0.15;
|
||||
public const double TRACKING_PROBABILITY_INCREASE = 15;
|
||||
public const double TRACKING_INTERSECTION_THRESHOLD = 0.8;
|
||||
|
||||
# endregion AIRecognitionConfig
|
||||
|
||||
# region WindowConfig
|
||||
|
||||
public static readonly Size DefaultWindowSize = new(1280, 720);
|
||||
public static readonly Point DefaultWindowLocation = new(100, 100);
|
||||
public static readonly Size DefaultThumbnailSize = new(240, 135);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Thumbnails
|
||||
|
||||
public const int DEFAULT_THUMBNAIL_BORDER = 10;
|
||||
|
||||
public const string THUMBNAIL_PREFIX = "_thumb";
|
||||
public const string THUMBNAILS_CACHE_FILE = "thumbnails.cache";
|
||||
|
||||
#endregion
|
||||
|
||||
public static TimeSpan? GetTime(string imagePath)
|
||||
{
|
||||
var timeStr = imagePath.Split("_").LastOrDefault();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media;
|
||||
using Azaion.Common.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Azaion.Common.DTO;
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
namespace Azaion.Annotator.DTO;
|
||||
namespace Azaion.Common.DTO.Config;
|
||||
|
||||
public class AIRecognitionConfig
|
||||
{
|
||||
public string AIModelPath { get; set; } = null!;
|
||||
public double FrameRecognitionSeconds { get; set; }
|
||||
public double TrackingDistanceConfidence { get; set; }
|
||||
public double TrackingProbabilityIncrease { get; set; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Azaion.Suite.Services.DTO;
|
||||
namespace Azaion.Common.DTO.Config;
|
||||
|
||||
public class ApiConfig
|
||||
{
|
||||
@@ -6,8 +6,3 @@ public class ApiConfig
|
||||
public int RetryCount {get;set;}
|
||||
public double TimeoutSeconds { get; set; }
|
||||
}
|
||||
|
||||
public class LocalFilesConfig
|
||||
{
|
||||
public string DllPath { get; set; } = null!;
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Azaion.Annotator.DTO;
|
||||
using Azaion.Suite.Services.DTO;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Azaion.Common.DTO.Config;
|
||||
@@ -11,14 +8,14 @@ public class AppConfig
|
||||
{
|
||||
public ApiConfig ApiConfig { get; set; } = null!;
|
||||
|
||||
public DirectoriesConfig DirectoriesConfig { get; set; } = null!;
|
||||
|
||||
public AnnotationConfig AnnotationConfig { get; set; } = null!;
|
||||
|
||||
public WindowConfig WindowConfig { get; set; } = null!;
|
||||
|
||||
public AIRecognitionConfig AIRecognitionConfig { get; set; } = null!;
|
||||
|
||||
public DirectoriesConfig DirectoriesConfig { get; set; } = null!;
|
||||
|
||||
public ThumbnailConfig ThumbnailConfig { get; set; } = null!;
|
||||
}
|
||||
|
||||
@@ -40,6 +37,13 @@ public class ConfigUpdater : IConfigUpdater
|
||||
|
||||
var appConfig = new AppConfig
|
||||
{
|
||||
ApiConfig = new ApiConfig
|
||||
{
|
||||
Url = Constants.DEFAULT_API_URL,
|
||||
RetryCount = Constants.DEFAULT_API_RETRY_COUNT,
|
||||
TimeoutSeconds = Constants.DEFAULT_API_TIMEOUT_SECONDS
|
||||
},
|
||||
|
||||
AnnotationConfig = new AnnotationConfig
|
||||
{
|
||||
AnnotationClasses = Constants.DefaultAnnotationClasses,
|
||||
@@ -51,7 +55,6 @@ public class ConfigUpdater : IConfigUpdater
|
||||
{
|
||||
WindowSize = Constants.DefaultWindowSize,
|
||||
WindowLocation = Constants.DefaultWindowLocation,
|
||||
ShowHelpOnStart = true,
|
||||
FullScreen = true,
|
||||
LeftPanelWidth = 250,
|
||||
RightPanelWidth = 250,
|
||||
@@ -74,7 +77,6 @@ public class ConfigUpdater : IConfigUpdater
|
||||
|
||||
AIRecognitionConfig = new AIRecognitionConfig
|
||||
{
|
||||
AIModelPath = "azaion.onnx",
|
||||
FrameRecognitionSeconds = Constants.DEFAULT_FRAME_RECOGNITION_SECONDS,
|
||||
TrackingDistanceConfidence = Constants.TRACKING_DISTANCE_CONFIDENCE,
|
||||
TrackingProbabilityIncrease = Constants.TRACKING_PROBABILITY_INCREASE,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Azaion.Common.DTO;
|
||||
namespace Azaion.Common.DTO.Config;
|
||||
|
||||
public class DirectoriesConfig
|
||||
{
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
namespace Azaion.Suite;
|
||||
namespace Azaion.Common.DTO;
|
||||
|
||||
public class HardwareInfo
|
||||
{
|
||||
public string CPU { get; set; } = null!;
|
||||
public string GPU { get; set; } = null!;
|
||||
public string MacAddress { get; set; } = null!;
|
||||
public string Memory { get; set; } = null!;
|
||||
|
||||
public string Hash { get; set; } = null!;
|
||||
@@ -0,0 +1,10 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Azaion.Common.Extensions;
|
||||
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection ConfigureSection<T>(this IServiceCollection services, IConfiguration config) where T: class =>
|
||||
services.Configure<T>(config.GetSection(typeof(T).Name));
|
||||
}
|
||||
+11
-5
@@ -4,12 +4,12 @@ using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using Azaion.Suite.Services.DTO;
|
||||
using Azaion.Common.DTO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Azaion.Suite.Services;
|
||||
namespace Azaion.Common.Services;
|
||||
|
||||
public class AzaionApiClient(HttpClient httpClient)
|
||||
public class AzaionApiClient(HttpClient httpClient) : IDisposable
|
||||
{
|
||||
const string JSON_MEDIA = "application/json";
|
||||
|
||||
@@ -26,11 +26,11 @@ public class AzaionApiClient(HttpClient httpClient)
|
||||
Password = password.ToSecureString();
|
||||
}
|
||||
|
||||
public async Task<Stream> GetResource(string password, HardwareInfo hardware, ResourceEnum resourceEnum)
|
||||
public async Task<Stream> GetResource(string fileName, string password, HardwareInfo hardware)
|
||||
{
|
||||
var response = await Send(httpClient, new HttpRequestMessage(HttpMethod.Post, "/resources/get")
|
||||
{
|
||||
Content = new StringContent(JsonConvert.SerializeObject(new { password, hardware, resourceEnum }), Encoding.UTF8, JSON_MEDIA)
|
||||
Content = new StringContent(JsonConvert.SerializeObject(new { fileName, password, hardware }), Encoding.UTF8, JSON_MEDIA)
|
||||
});
|
||||
return await response.Content.ReadAsStreamAsync();
|
||||
}
|
||||
@@ -82,4 +82,10 @@ public class AzaionApiClient(HttpClient httpClient)
|
||||
var result = await response.Content.ReadAsStringAsync();
|
||||
throw new Exception($"Failed: {response.StatusCode}! Result: {result}");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
httpClient.Dispose();
|
||||
Password.Dispose();
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -2,8 +2,9 @@
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Azaion.Common.DTO;
|
||||
|
||||
namespace Azaion.Suite.Services;
|
||||
namespace Azaion.Common.Services;
|
||||
|
||||
public interface IHardwareService
|
||||
{
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Azaion.Common.Services;
|
||||
|
||||
public interface IResourceLoader
|
||||
{
|
||||
Task<MemoryStream> Load(string fileName, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public class ResourceLoader(string email, string password, AzaionApiClient api, IHardwareService hardwareService) : IResourceLoader
|
||||
{
|
||||
public async Task<MemoryStream> Load(string fileName, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var hardwareInfo = await hardwareService.GetHardware();
|
||||
var encryptedStream = await api.GetResource(fileName, password, hardwareInfo);
|
||||
|
||||
var key = Security.MakeEncryptionKey(email, password, hardwareInfo.Hash);
|
||||
var stream = new MemoryStream();
|
||||
await encryptedStream.DecryptTo(stream, key, cancellationToken);
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using System.Security;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace Azaion.Suite.Services;
|
||||
namespace Azaion.Common.Services;
|
||||
|
||||
public static class Security
|
||||
{
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.IO;
|
||||
using System.Windows.Input;
|
||||
using Azaion.Common.DTO;
|
||||
using Azaion.Common.DTO.Config;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<Application x:Class="Azaion.Launcher.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
StartupUri="Loader.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Azaion.Launcher;
|
||||
|
||||
public partial class App;
|
||||
@@ -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)
|
||||
)]
|
||||
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWPF>true</UseWPF>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Loader.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<XamlRuntime>Wpf</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,4 +1,4 @@
|
||||
<Window x:Class="Azaion.Suite.Loader"
|
||||
<Window x:Class="Azaion.Launcher.Loader"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Azaion.Launcher;
|
||||
|
||||
public partial class Loader : Window
|
||||
{
|
||||
public Loader()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void RunClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Process.Start("Azaion.Suite.exe", $"-e {TbEmail.Text} -p {TbPassword.Password}");
|
||||
}
|
||||
|
||||
private void CloseClick(object sender, RoutedEventArgs e) => Close();
|
||||
|
||||
private void MainMouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource is Button || e.OriginalSource is TextBox)
|
||||
return;
|
||||
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
DragMove();
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azaion.Common", "Azaion.Com
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azaion.Dataset", "Azaion.Dataset\Azaion.Dataset.csproj", "{01A5CA37-A62E-4EF3-8678-D72CD9525677}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azaion.Launcher", "Azaion.Launcher\Azaion.Launcher.csproj", "{00CC9AFE-2952-4943-BCBA-976AE03DE841}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -36,5 +38,9 @@ Global
|
||||
{01A5CA37-A62E-4EF3-8678-D72CD9525677}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{01A5CA37-A62E-4EF3-8678-D72CD9525677}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{01A5CA37-A62E-4EF3-8678-D72CD9525677}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{00CC9AFE-2952-4943-BCBA-976AE03DE841}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{00CC9AFE-2952-4943-BCBA-976AE03DE841}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{00CC9AFE-2952-4943-BCBA-976AE03DE841}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{00CC9AFE-2952-4943-BCBA-976AE03DE841}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,16 +1,21 @@
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Threading;
|
||||
using Azaion.Annotator;
|
||||
using Azaion.Annotator.DTO;
|
||||
using Azaion.Annotator.Extensions;
|
||||
using Azaion.Common;
|
||||
using Azaion.Common.DTO;
|
||||
using Azaion.Common.DTO.Config;
|
||||
using Azaion.Common.Extensions;
|
||||
using Azaion.Common.Services;
|
||||
using Azaion.Suite.Services;
|
||||
using Azaion.Suite.Services.DTO;
|
||||
using Azaion.Dataset;
|
||||
using Azaion.Suite.Services.DTO;
|
||||
using CommandLine;
|
||||
using LibVLCSharp.Shared;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@@ -18,16 +23,53 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
|
||||
namespace Azaion.Suite;
|
||||
|
||||
public partial class App : Application
|
||||
public partial class App
|
||||
{
|
||||
private readonly IHost _host;
|
||||
private readonly ILogger<App> _logger;
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
private static readonly List<string> EncryptedResources =
|
||||
[
|
||||
"Azaion.Annotator.dll",
|
||||
"Azaion.Dataset.dll"
|
||||
];
|
||||
|
||||
private static readonly IResourceLoader? ResourceLoader;
|
||||
|
||||
static App()
|
||||
{
|
||||
var result = Parser.Default.ParseArguments<SuiteCommandLineOptions>(Environment.GetCommandLineArgs());
|
||||
if (result.Errors.Any())
|
||||
return;
|
||||
|
||||
var configStr = File.ReadAllText(Constants.CONFIG_PATH);
|
||||
var apiConfig = JsonConvert.DeserializeObject<AppConfig>(configStr)!.ApiConfig;
|
||||
var api = new AzaionApiClient(new HttpClient
|
||||
{
|
||||
BaseAddress = new Uri(apiConfig.Url),
|
||||
Timeout = TimeSpan.FromSeconds(apiConfig.TimeoutSeconds)
|
||||
});
|
||||
var email = result.Value.Email;
|
||||
var password = result.Value.Password;
|
||||
|
||||
api.Login(email, password);
|
||||
|
||||
ResourceLoader = new ResourceLoader(email, password, api, new HardwareService());
|
||||
foreach (var resource in EncryptedResources)
|
||||
{
|
||||
var stream = ResourceLoader.Load(resource).GetAwaiter().GetResult();
|
||||
Assembly.Load(stream.ToArray());
|
||||
}
|
||||
|
||||
new ConfigUpdater().CheckConfig();
|
||||
}
|
||||
|
||||
public App()
|
||||
{
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
@@ -42,21 +84,30 @@ public partial class App : Application
|
||||
_host = Host.CreateDefaultBuilder()
|
||||
.ConfigureAppConfiguration((context, config) => config
|
||||
.AddCommandLine(Environment.GetCommandLineArgs())
|
||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true))
|
||||
.AddJsonFile(Constants.CONFIG_PATH, optional: true, reloadOnChange: true))
|
||||
.ConfigureServices((context, services) =>
|
||||
{
|
||||
services.AddSingleton<Loader>();
|
||||
services.AddSingleton<MainSuite>();
|
||||
services.AddSingleton<IHardwareService, HardwareService>();
|
||||
services.AddSingleton<IResourceLoader, ResourceLoader>();
|
||||
services.AddSingleton<IResourceLoader>(ResourceLoader!);
|
||||
|
||||
services.Configure<AppConfig>(context.Configuration);
|
||||
services.ConfigureSection<ApiConfig>(context.Configuration);
|
||||
services.ConfigureSection<DirectoriesConfig>(context.Configuration);
|
||||
services.ConfigureSection<AnnotationConfig>(context.Configuration);
|
||||
services.ConfigureSection<WindowConfig>(context.Configuration);
|
||||
services.ConfigureSection<AIRecognitionConfig>(context.Configuration);
|
||||
services.ConfigureSection<ThumbnailConfig>(context.Configuration);
|
||||
|
||||
services.Configure<ApiConfig>(context.Configuration.GetSection(nameof(ApiConfig)));
|
||||
services.AddSingleton<IConfigUpdater, ConfigUpdater>();
|
||||
|
||||
services.AddSingleton<Annotator.Annotator>();
|
||||
services.AddSingleton<DatasetExplorer>();
|
||||
services.AddSingleton<HelpWindow>();
|
||||
services.AddSingleton<IAIDetector, YOLODetector>();
|
||||
services.AddMediatR(c => c.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()));
|
||||
services.AddMediatR(c => c.RegisterServicesFromAssemblies(
|
||||
typeof(Annotator.Annotator).Assembly,
|
||||
typeof(DatasetExplorer).Assembly));
|
||||
services.AddSingleton<LibVLC>(_ => new LibVLC());
|
||||
services.AddSingleton<FormState>();
|
||||
services.AddSingleton<MediaPlayer>(sp =>
|
||||
@@ -93,7 +144,7 @@ public partial class App : Application
|
||||
{
|
||||
EventManager.RegisterClassHandler(typeof(UIElement), UIElement.KeyDownEvent, new RoutedEventHandler(GlobalClick));
|
||||
await _host.StartAsync();
|
||||
_host.Services.GetRequiredService<Loader>().Show();
|
||||
_host.Services.GetRequiredService<MainSuite>().Show();
|
||||
|
||||
base.OnStartup(e);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageReference Include="LibVLCSharp" Version="3.9.1" />
|
||||
<PackageReference Include="LibVLCSharp.WPF" Version="3.9.1" />
|
||||
<PackageReference Include="MediatR" Version="12.4.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
|
||||
@@ -19,13 +22,7 @@
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.4" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="appsettings.json" />
|
||||
<Content Include="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<PackageReference Include="VideoLAN.LibVLC.Windows" Version="3.0.21" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Loader;
|
||||
using Azaion.Suite.Services.DTO;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Azaion.Suite;
|
||||
|
||||
public class DynamicAssemblyLoader(IOptions<LocalFilesConfig> localFilesConfig) : AssemblyLoadContext
|
||||
{
|
||||
private static readonly Dictionary<string?, Assembly> LoadedAssemblies = new();
|
||||
|
||||
static DynamicAssemblyLoader()
|
||||
{
|
||||
LoadedAssemblies = Default.Assemblies.ToDictionary(a => a.GetName().Name, a => a);
|
||||
}
|
||||
|
||||
protected override Assembly Load(AssemblyName assemblyName)
|
||||
{
|
||||
var assembly = LoadedAssemblies.GetValueOrDefault(assemblyName.Name);
|
||||
if (assembly != null)
|
||||
return assembly;
|
||||
|
||||
var currentLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||
|
||||
var asm = Assembly.LoadFile(Path.Combine(currentLocation, localFilesConfig.Value.DllPath, $"{assemblyName.Name!}.dll"));
|
||||
return asm;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Loader;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using Azaion.Suite.Services.DTO;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Azaion.Suite;
|
||||
|
||||
public partial class Loader : Window
|
||||
{
|
||||
private readonly IResourceLoader _resourceLoader;
|
||||
private readonly IOptions<LocalFilesConfig> _localFilesConfig;
|
||||
|
||||
public Loader(IResourceLoader resourceLoader, IOptions<LocalFilesConfig> localFilesConfig)
|
||||
{
|
||||
_resourceLoader = resourceLoader;
|
||||
_localFilesConfig = localFilesConfig;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void RunClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
await _resourceLoader.LoadAnnotator(TbEmail.Text, TbPassword.Password, stream);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
var loader = new AssemblyLoadContext("DynamicContext", isCollectible: true);
|
||||
var annotatorAssembly = loader.LoadFromStream(stream);
|
||||
|
||||
var appType = annotatorAssembly.GetType("Azaion.Annotator.App");
|
||||
var appInstance = Activator.CreateInstance(appType);
|
||||
var runMethod = appType.GetMethod("Run", BindingFlags.Public | BindingFlags.Instance);
|
||||
if (runMethod != null)
|
||||
{
|
||||
runMethod.Invoke(appInstance, null);
|
||||
}
|
||||
|
||||
// var entryPoint = annotatorAssembly.EntryPoint;
|
||||
// if (entryPoint == null)
|
||||
// return;
|
||||
//
|
||||
// var o = annotatorAssembly.CreateInstance(entryPoint.Name);
|
||||
// entryPoint.Invoke(o, null);
|
||||
}
|
||||
|
||||
private void CloseClick(object sender, RoutedEventArgs e) => Close();
|
||||
|
||||
private void MainMouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource is Button || e.OriginalSource is TextBox)
|
||||
return;
|
||||
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
DragMove();
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,13 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Azaion.Suite"
|
||||
mc:Ignorable="d"
|
||||
Title="MainSuite" Height="450" Width="800">
|
||||
<Grid>
|
||||
|
||||
<TabControl Name="MainTabControl"
|
||||
TabStripPlacement="Left"
|
||||
Margin="0, 0, 0, 10"
|
||||
Background="Black">
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Azaion.Annotator.Extensions;
|
||||
using Azaion.Common.DTO.Config;
|
||||
using Azaion.Dataset;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Azaion.Suite;
|
||||
|
||||
public partial class MainSuite : Window
|
||||
public partial class MainSuite
|
||||
{
|
||||
private readonly AppConfig _appConfig;
|
||||
private readonly IConfigUpdater _configUpdater;
|
||||
private readonly Annotator.Annotator _annotator;
|
||||
private readonly DatasetExplorer _datasetExplorer;
|
||||
|
||||
public MainSuite(IOptions<AppConfig> appConfig, IConfigUpdater configUpdater)
|
||||
public MainSuite(IOptions<AppConfig> appConfig, IConfigUpdater configUpdater, Annotator.Annotator annotator, DatasetExplorer datasetExplorer)
|
||||
{
|
||||
_configUpdater = configUpdater;
|
||||
_annotator = annotator;
|
||||
_datasetExplorer = datasetExplorer;
|
||||
_appConfig = appConfig.Value;
|
||||
InitializeComponent();
|
||||
Loaded += OnLoaded;
|
||||
@@ -41,6 +47,17 @@ public partial class MainSuite : Window
|
||||
|
||||
if (_appConfig.WindowConfig.FullScreen)
|
||||
WindowState = WindowState.Maximized;
|
||||
|
||||
MainTabControl.Items.Add(new TabItem
|
||||
{
|
||||
Header = "Annotator",
|
||||
Content = _annotator.Content
|
||||
});
|
||||
MainTabControl.Items.Add(new TabItem
|
||||
{
|
||||
Header = "Dataset Explorer",
|
||||
Content = _datasetExplorer.Content
|
||||
});
|
||||
}
|
||||
|
||||
private async Task SaveUserSettings()
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Azaion.Suite.Services;
|
||||
using Azaion.Suite.Services.DTO;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Azaion.Suite;
|
||||
|
||||
public interface IResourceLoader
|
||||
{
|
||||
Task LoadAnnotator(string email, string password, Stream outStream, CancellationToken cancellationToken = default);
|
||||
Assembly LoadAssembly(string name, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public class ResourceLoader(AzaionApiClient azaionApi, IHardwareService hardwareService, IOptions<LocalFilesConfig> localFilesConfig) : IResourceLoader
|
||||
{
|
||||
public async Task LoadAnnotator(string email, string password, Stream outStream, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var hardwareInfo = await hardwareService.GetHardware();
|
||||
azaionApi.Login(email, password);
|
||||
var key = Security.MakeEncryptionKey(email, password, hardwareInfo.Hash);
|
||||
|
||||
var encryptedStream = await azaionApi.GetResource(password, hardwareInfo, ResourceEnum.AnnotatorDll);
|
||||
|
||||
await encryptedStream.DecryptTo(outStream, key, cancellationToken);
|
||||
//return Assembly.Load(stream.ToArray());
|
||||
}
|
||||
|
||||
public Assembly LoadAssembly(string name, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var dllValues = name.Split(",");
|
||||
var dllName = $"{dllValues[0]}.dll";
|
||||
var currentLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||
|
||||
var asm = Assembly.LoadFile(Path.Combine(currentLocation, localFilesConfig.Value.DllPath, dllName));
|
||||
return asm;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Azaion.Suite.Services.DTO;
|
||||
|
||||
public enum ResourceEnum
|
||||
{
|
||||
None = 0,
|
||||
AnnotatorDll = 10,
|
||||
AIModelRKNN = 20,
|
||||
AIModelONNX = 30,
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using CommandLine;
|
||||
|
||||
namespace Azaion.Suite.Services.DTO;
|
||||
|
||||
public class SuiteCommandLineOptions
|
||||
{
|
||||
[Option('e', "email", Required = true, HelpText = "The email for authorization.")]
|
||||
public string Email { get; set; } = null!;
|
||||
|
||||
[Option('p', "password", Required = true, HelpText = "The password for authorization.")]
|
||||
public string Password { get; set; } = null!;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"ApiConfig": {
|
||||
"Url": "https://api.azaion.com",
|
||||
"TimeoutSeconds": 20,
|
||||
"RetryCount": 3
|
||||
},
|
||||
"LocalFilesConfig": {
|
||||
"DllPath": "AzaionSuite"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"ApiConfig": {
|
||||
"Url": "https://api.azaion.com",
|
||||
"TimeoutSeconds": 20,
|
||||
"RetryCount": 3
|
||||
},
|
||||
|
||||
"DirectoriesConfig": {
|
||||
"VideosDirectory" : "E:\\Azaion1\\Videos",
|
||||
"LabelsDirectory" : "E:\\labels",
|
||||
"ImagesDirectory" : "E:\\images",
|
||||
"ResultsDirectory" : "E:\\results",
|
||||
"ThumbnailsDirectory" : "E:\\thumbnails",
|
||||
|
||||
"DllCacheDirectory" : "Cache"
|
||||
},
|
||||
|
||||
"AnnotationConfig" : {
|
||||
"AnnotationClasses": [
|
||||
{ "Id": 0, "Name": "Броньована техніка", "ShortName": "Бронь" },
|
||||
{ "Id": 1, "Name": "Вантажівка", "ShortName": "Вантаж" },
|
||||
{ "Id": 2, "Name": "Машина легкова", "ShortName": "Машина" },
|
||||
{ "Id": 3, "Name": "Артилерія", "ShortName": "Арта" },
|
||||
{ "Id": 4, "Name": "Тінь від техніки", "ShortName": "Тінь" },
|
||||
{ "Id": 5, "Name": "Окопи", "ShortName": "Окопи" },
|
||||
{ "Id": 6, "Name": "Військовий", "ShortName": "Військов" },
|
||||
{ "Id": 7, "Name": "Накати", "ShortName": "Накати" },
|
||||
{ "Id": 8, "Name": "Танк з захистом", "ShortName": "Танк захист" },
|
||||
{ "Id": 9, "Name": "Дим", "ShortName": "Дим" },
|
||||
{ "Id": 10, "Name": "Літак", "ShortName": "Літак" }
|
||||
],
|
||||
"LastSelectedExplorerClass": 1,
|
||||
"VideoFormats": ["mov", "mp4"],
|
||||
"ImageFormats": ["jpg", "jpeg", "png", "bmp", "gif"]
|
||||
},
|
||||
|
||||
"WindowConfig": {
|
||||
"WindowSize": "1920,1080",
|
||||
"WindowLocation": "50,50",
|
||||
"FullScreen": true,
|
||||
"LeftPanelWidth": 220,
|
||||
"RightPanelWidth": 220,
|
||||
"ShowHelpOnStart": false
|
||||
},
|
||||
|
||||
"AIRecognitionConfig": {
|
||||
"FrameRecognitionSeconds" : 2,
|
||||
"TrackingDistanceConfidence" : 0.15,
|
||||
"TrackingProbabilityIncrease" : 15,
|
||||
"TrackingIntersectionThreshold" : 0.8
|
||||
},
|
||||
|
||||
"ThumbnailConfig": {
|
||||
"Size" : "240,135",
|
||||
"Border" : 10
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Azaion.Suite;
|
||||
using Azaion.Common.Services;
|
||||
using Azaion.Suite;
|
||||
using Azaion.Suite.Services;
|
||||
using Xunit;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user