mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 21:46:30 +00:00
83ae6a0ae9
forbid non validators to read from queue create better visualization in detector control make colors for detection classes more distinguishable fix bug with removing detection (probably completely)
207 lines
6.7 KiB
C#
207 lines
6.7 KiB
C#
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using MessagePack;
|
|
using Newtonsoft.Json;
|
|
using Size = System.Windows.Size;
|
|
|
|
namespace Azaion.Common.DTO;
|
|
|
|
[MessagePackObject]
|
|
public abstract class Label
|
|
{
|
|
[JsonProperty(PropertyName = "cl")][Key("c")] 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 Confidence { get; set; }
|
|
|
|
public CanvasLabel()
|
|
{
|
|
}
|
|
|
|
public CanvasLabel(int classNumber, double x, double y, double width, double height, double confidence = 1) : base(classNumber)
|
|
{
|
|
X = x;
|
|
Y = y;
|
|
Width = width;
|
|
Height = height;
|
|
Confidence = confidence;
|
|
}
|
|
|
|
public CanvasLabel(YoloLabel label, Size canvasSize, Size? videoSize = null, double confidence = 1)
|
|
{
|
|
var cw = canvasSize.Width;
|
|
var ch = canvasSize.Height;
|
|
var canvasAr = cw / ch;
|
|
var videoAr = videoSize.HasValue
|
|
? videoSize.Value.Width / videoSize.Value.Height
|
|
: canvasAr;
|
|
|
|
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;
|
|
}
|
|
Confidence = confidence;
|
|
}
|
|
}
|
|
|
|
[MessagePackObject]
|
|
public class YoloLabel : Label
|
|
{
|
|
[JsonProperty(PropertyName = "x")][Key("x")] public double CenterX { get; set; }
|
|
|
|
[JsonProperty(PropertyName = "y")][Key("y")] public double CenterY { get; set; }
|
|
|
|
[JsonProperty(PropertyName = "w")][Key("w")] public double Width { get; set; }
|
|
|
|
[JsonProperty(PropertyName = "h")][Key("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 = null)
|
|
{
|
|
var cw = canvasSize.Width;
|
|
var ch = canvasSize.Height;
|
|
var canvasAr = cw / ch;
|
|
var videoAr = videoSize.HasValue
|
|
? videoSize.Value.Width / videoSize.Value.Height
|
|
: canvasAr;
|
|
|
|
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 Deserialize(str);
|
|
}
|
|
|
|
public static async Task WriteToFile(IEnumerable<YoloLabel> labels, string filename, CancellationToken cancellationToken = default)
|
|
{
|
|
var labelsStr = Serialize(labels);
|
|
await File.WriteAllTextAsync(filename, labelsStr, cancellationToken);
|
|
}
|
|
|
|
public static string Serialize(IEnumerable<YoloLabel> labels) =>
|
|
string.Join(Environment.NewLine, labels.Select(x => x.ToString()));
|
|
|
|
public static List<YoloLabel> Deserialize(string str) =>
|
|
str.Split('\n')
|
|
.Select(Parse)
|
|
.Where(ann => ann != null)
|
|
.ToList()!;
|
|
|
|
|
|
public override string ToString() => $"{ClassNumber} {CenterX:F5} {CenterY:F5} {Width:F5} {Height:F5}".Replace(',', '.');
|
|
}
|
|
|
|
[MessagePackObject]
|
|
public class Detection : YoloLabel
|
|
{
|
|
[JsonProperty(PropertyName = "an")][Key("an")] public string AnnotationName { get; set; } = null!;
|
|
[JsonProperty(PropertyName = "p")][Key("p")] public double Confidence { get; set; }
|
|
|
|
//For db & serialization
|
|
public Detection(){}
|
|
|
|
public Detection(string annotationName, YoloLabel label, double confidence = 1)
|
|
{
|
|
AnnotationName = annotationName;
|
|
ClassNumber = label.ClassNumber;
|
|
CenterX = label.CenterX;
|
|
CenterY = label.CenterY;
|
|
Height = label.Height;
|
|
Width = label.Width;
|
|
Confidence = confidence;
|
|
}
|
|
} |