rework to Azaion.Suite

This commit is contained in:
Alex Bezdieniezhnykh
2024-11-21 13:41:32 +02:00
parent 2cf69f4e4e
commit 5a592e9dbf
76 changed files with 1739 additions and 882 deletions
+22
View File
@@ -0,0 +1,22 @@
using System.Text.Json.Serialization;
using System.Windows.Media;
using Azaion.Common.Extensions;
namespace Azaion.Common.DTO;
public class AnnotationClass
{
public int Id { get; set; }
public string Name { get; set; } = null!;
public string ShortName { get; set; } = null!;
[JsonIgnore]
public Color Color => Id.ToColor();
[JsonIgnore]
public int ClassNumber => Id + 1;
[JsonIgnore]
public SolidColorBrush ColorBrush => new(Color);
}
@@ -0,0 +1,10 @@
namespace Azaion.Annotator.DTO;
public class AIRecognitionConfig
{
public string AIModelPath { get; set; } = null!;
public double FrameRecognitionSeconds { get; set; }
public double TrackingDistanceConfidence { get; set; }
public double TrackingProbabilityIncrease { get; set; }
public double TrackingIntersectionThreshold { get; set; }
}
@@ -0,0 +1,18 @@
using Newtonsoft.Json;
namespace Azaion.Common.DTO.Config;
public class AnnotationConfig
{
public List<AnnotationClass> AnnotationClasses { get; set; } = null!;
[JsonIgnore]
private Dictionary<int, AnnotationClass>? _annotationClassesDict;
[JsonIgnore]
public Dictionary<int, AnnotationClass> AnnotationClassesDict => _annotationClassesDict ??= AnnotationClasses.ToDictionary(x => x.Id);
public int? LastSelectedExplorerClass { get; set; }
public List<string> VideoFormats { get; set; } = null!;
public List<string> ImageFormats { get; set; } = null!;
}
+13
View File
@@ -0,0 +1,13 @@
namespace Azaion.Suite.Services.DTO;
public class ApiConfig
{
public string Url { get; set; } = null!;
public int RetryCount {get;set;}
public double TimeoutSeconds { get; set; }
}
public class LocalFilesConfig
{
public string DllPath { get; set; } = null!;
}
+91
View File
@@ -0,0 +1,91 @@
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;
public class AppConfig
{
public ApiConfig ApiConfig { 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!;
}
public interface IConfigUpdater
{
void CheckConfig();
void Save(AppConfig config);
}
public class ConfigUpdater : IConfigUpdater
{
public void CheckConfig()
{
var exePath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory)!;
var configFilePath = Path.Combine(exePath, Constants.CONFIG_PATH);
if (File.Exists(configFilePath))
return;
var appConfig = new AppConfig
{
AnnotationConfig = new AnnotationConfig
{
AnnotationClasses = Constants.DefaultAnnotationClasses,
VideoFormats = Constants.DefaultVideoFormats,
ImageFormats = Constants.DefaultImageFormats,
},
WindowConfig = new WindowConfig
{
WindowSize = Constants.DefaultWindowSize,
WindowLocation = Constants.DefaultWindowLocation,
ShowHelpOnStart = true,
FullScreen = true,
LeftPanelWidth = 250,
RightPanelWidth = 250,
},
DirectoriesConfig = new DirectoriesConfig
{
VideosDirectory = Constants.DEFAULT_VIDEO_DIR,
ImagesDirectory = Constants.DEFAULT_IMAGES_DIR,
LabelsDirectory = Constants.DEFAULT_LABELS_DIR,
ResultsDirectory = Constants.DEFAULT_RESULTS_DIR,
ThumbnailsDirectory = Constants.DEFAULT_THUMBNAILS_DIR
},
ThumbnailConfig = new ThumbnailConfig
{
Size = Constants.DefaultThumbnailSize,
Border = Constants.DEFAULT_THUMBNAIL_BORDER
},
AIRecognitionConfig = new AIRecognitionConfig
{
AIModelPath = "azaion.onnx",
FrameRecognitionSeconds = Constants.DEFAULT_FRAME_RECOGNITION_SECONDS,
TrackingDistanceConfidence = Constants.TRACKING_DISTANCE_CONFIDENCE,
TrackingProbabilityIncrease = Constants.TRACKING_PROBABILITY_INCREASE,
TrackingIntersectionThreshold = Constants.TRACKING_INTERSECTION_THRESHOLD
}
};
Save(appConfig);
}
public void Save(AppConfig config)
{
File.WriteAllText(Constants.CONFIG_PATH, JsonConvert.SerializeObject(config, Formatting.Indented), Encoding.UTF8);
}
}
@@ -0,0 +1,10 @@
namespace Azaion.Common.DTO;
public class DirectoriesConfig
{
public string VideosDirectory { get; set; } = null!;
public string LabelsDirectory { get; set; } = null!;
public string ImagesDirectory { get; set; } = null!;
public string ResultsDirectory { get; set; } = null!;
public string ThumbnailsDirectory { get; set; } = null!;
}
@@ -0,0 +1,9 @@
using System.Windows;
namespace Azaion.Common.DTO.Config;
public class ThumbnailConfig
{
public Size Size { get; set; }
public int Border { get; set; }
}
+14
View File
@@ -0,0 +1,14 @@
using System.Windows;
namespace Azaion.Common.DTO.Config;
public class WindowConfig
{
public Size WindowSize { get; set; }
public Point WindowLocation { get; set; }
public bool FullScreen { get; set; }
public double LeftPanelWidth { get; set; }
public double RightPanelWidth { get; set; }
public bool ShowHelpOnStart { get; set; }
}
+8
View File
@@ -0,0 +1,8 @@
using MediatR;
namespace Azaion.Common.DTO;
public class ImageCreatedEvent(string imagePath) : INotification
{
public string ImagePath { get; } = imagePath;
}
+11
View File
@@ -0,0 +1,11 @@
using System.Windows.Input;
using MediatR;
namespace Azaion.Common.DTO;
public class KeyEvent(object sender, KeyEventArgs args, WindowEnum windowEnum) : INotification
{
public object Sender { get; set; } = sender;
public KeyEventArgs Args { get; set; } = args;
public WindowEnum WindowEnum { get; } = windowEnum;
}
+189
View File
@@ -0,0 +1,189 @@
using System.Drawing;
using System.Globalization;
using System.IO;
using Newtonsoft.Json;
using Size = System.Windows.Size;
namespace Azaion.Common.DTO;
public abstract class Label
{
[JsonProperty(PropertyName = "cl")] public int ClassNumber { get; set; }
protected Label()
{
}
protected Label(int classNumber)
{
ClassNumber = classNumber;
}
}
public class CanvasLabel : Label
{
public double X { get; set; }
public double Y { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public double? Probability { get; }
public CanvasLabel()
{
}
public CanvasLabel(int classNumber, double x, double y, double width, double height, double? probability = null) : base(classNumber)
{
X = x;
Y = y;
Width = width;
Height = height;
Probability = probability;
}
public CanvasLabel(YoloLabel label, Size canvasSize, Size videoSize, double? probability = null)
{
var cw = canvasSize.Width;
var ch = canvasSize.Height;
var canvasAr = cw / ch;
var videoAr = videoSize.Width / videoSize.Height;
ClassNumber = label.ClassNumber;
var left = label.CenterX - label.Width / 2;
var top = label.CenterY - label.Height / 2;
if (videoAr > canvasAr) //100% width
{
var realHeight = cw / videoAr; //real video height in pixels on canvas
var blackStripHeight = (ch - realHeight) / 2.0; //height of black strips at the top and bottom
X = left * cw;
Y = top * realHeight + blackStripHeight;
Width = label.Width * cw;
Height = label.Height * realHeight;
}
else //100% height
{
var realWidth = ch * videoAr; //real video width in pixels on canvas
var blackStripWidth = (cw - realWidth) / 2.0; //height of black strips at the top and bottom
X = left * realWidth + blackStripWidth;
Y = top * ch;
Width = label.Width * realWidth;
Height = label.Height * ch;
}
Probability = probability;
}
}
public class YoloLabel : Label
{
[JsonProperty(PropertyName = "x")] public double CenterX { get; set; }
[JsonProperty(PropertyName = "y")] public double CenterY { get; set; }
[JsonProperty(PropertyName = "w")] public double Width { get; set; }
[JsonProperty(PropertyName = "h")] public double Height { get; set; }
public YoloLabel()
{
}
public YoloLabel(int classNumber, double centerX, double centerY, double width, double height) : base(classNumber)
{
CenterX = centerX;
CenterY = centerY;
Width = width;
Height = height;
}
public RectangleF ToRectangle() =>
new((float)(CenterX - Width / 2.0), (float)(CenterY - Height / 2.0), (float)Width, (float)Height);
public YoloLabel(CanvasLabel canvasLabel, Size canvasSize, Size videoSize)
{
var cw = canvasSize.Width;
var ch = canvasSize.Height;
var canvasAr = cw / ch;
var videoAr = videoSize.Width / videoSize.Height;
ClassNumber = canvasLabel.ClassNumber;
double left, top;
if (videoAr > canvasAr) //100% width
{
left = canvasLabel.X / cw;
Width = canvasLabel.Width / cw;
var realHeight = cw / videoAr; //real video height in pixels on canvas
var blackStripHeight = (ch - realHeight) / 2.0; //height of black strips at the top and bottom
top = (canvasLabel.Y - blackStripHeight) / realHeight;
Height = canvasLabel.Height / realHeight;
}
else //100% height
{
top = canvasLabel.Y / ch;
Height = canvasLabel.Height / ch;
var realWidth = ch * videoAr; //real video width in pixels on canvas
var blackStripWidth = (cw - realWidth) / 2.0; //height of black strips at the top and bottom
left = (canvasLabel.X - blackStripWidth) / realWidth;
Width = canvasLabel.Width / realWidth;
}
CenterX = left + Width / 2.0;
CenterY = top + Height / 2.0;
}
public static YoloLabel? Parse(string s)
{
if (string.IsNullOrEmpty(s))
return null;
var strings = s.Replace(',', '.').Split(' ');
if (strings.Length != 5)
throw new Exception("Wrong labels format!");
var res = new YoloLabel
{
ClassNumber = int.Parse(strings[0], CultureInfo.InvariantCulture),
CenterX = double.Parse(strings[1], CultureInfo.InvariantCulture),
CenterY = double.Parse(strings[2], CultureInfo.InvariantCulture),
Width = double.Parse(strings[3], CultureInfo.InvariantCulture),
Height = double.Parse(strings[4], CultureInfo.InvariantCulture)
};
return res;
}
public static async Task<List<YoloLabel>> ReadFromFile(string filename, CancellationToken cancellationToken = default)
{
var str = await File.ReadAllTextAsync(filename, cancellationToken);
return str.Split('\n')
.Select(Parse)
.Where(ann => ann != null)
.ToList()!;
}
public static async Task WriteToFile(IEnumerable<YoloLabel> labels, string filename, CancellationToken cancellationToken = default)
{
var labelsStr = string.Join(Environment.NewLine, labels.Select(x => x.ToString()));
await File.WriteAllTextAsync(filename, labelsStr, cancellationToken);
}
public override string ToString() => $"{ClassNumber} {CenterX:F5} {CenterY:F5} {Width:F5} {Height:F5}".Replace(',', '.');
}
public class Detection : YoloLabel
{
public Detection(YoloLabel label, double? probability = null)
{
ClassNumber = label.ClassNumber;
CenterX = label.CenterX;
CenterY = label.CenterY;
Height = label.Height;
Width = label.Width;
Probability = probability;
}
public double? Probability { get; set; }
}
+10
View File
@@ -0,0 +1,10 @@
using Newtonsoft.Json;
namespace Azaion.Common.DTO;
public class LabelInfo
{
[JsonProperty("c")] public List<int> Classes { get; set; } = null!;
[JsonProperty("d")] public DateTime ImageDateTime { get; set; }
}
+19
View File
@@ -0,0 +1,19 @@
namespace Azaion.Common.DTO;
public enum PlaybackControlEnum
{
None = 0,
Play = 1,
Pause = 2,
Stop = 3,
PreviousFrame = 4,
NextFrame = 5,
SaveAnnotations = 6,
RemoveSelectedAnns = 7,
RemoveAllAnns = 8,
TurnOffVolume = 9,
TurnOnVolume = 10,
Previous = 11,
Next = 12,
Close = 13
}
+9
View File
@@ -0,0 +1,9 @@
namespace Azaion.Annotator.DTO;
public enum SelectionState
{
None = 0,
NewAnnCreating = 1,
AnnResizing = 2,
AnnMoving = 3
}
+8
View File
@@ -0,0 +1,8 @@
namespace Azaion.Common.DTO;
public enum WindowEnum
{
None = 0,
Annotator = 10,
DatasetExplorer = 20
}