Files
annotations/Azaion.Common/Controls/DetectionControl.cs
Oleksandr Bezdieniezhnykh 55d8a5cb85 small improvements
2025-08-14 04:43:08 +03:00

166 lines
6.1 KiB
C#

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using Azaion.Common.DTO;
using Azaion.Common.Extensions;
using Annotation = Azaion.Common.Database.Annotation;
namespace Azaion.Common.Controls;
public class DetectionControl : Border
{
private readonly Action<object, MouseButtonEventArgs> _resizeStart;
private const double RESIZE_RECT_SIZE = 10;
private readonly Grid _grid;
private readonly DetectionLabelPanel _detectionLabelPanel;
public readonly Canvas DetectionLabelContainer;
public TimeSpan Time { get; set; }
private readonly List<Rectangle> _resizedRectangles = new();
private DetectionClass _detectionClass = null!;
public DetectionClass DetectionClass
{
get => _detectionClass;
set
{
var brush = new SolidColorBrush(value.Color.ToConfidenceColor());
BorderBrush = brush;
BorderThickness = new Thickness(1);
foreach (var rect in _resizedRectangles)
rect.Stroke = brush;
_detectionLabelPanel.DetectionClass = value;
_detectionClass = value;
}
}
private readonly Rectangle _selectionFrame;
private bool _isSelected;
public bool IsSelected
{
get => _isSelected;
set
{
_selectionFrame.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
_isSelected = value;
}
}
public void UpdateAdornerScale(double scale)
{
if (Math.Abs(scale) < 0.0001)
return;
var inverseScale = 1.0 / scale;
BorderThickness = new Thickness(4 * inverseScale);
foreach (var rect in _resizedRectangles)
{
rect.Width = 2 * RESIZE_RECT_SIZE * inverseScale;
rect.Height = 2 * RESIZE_RECT_SIZE * inverseScale;;
rect.Margin = new Thickness(-RESIZE_RECT_SIZE * 0.7);
}
}
public (HorizontalAlignment Horizontal, VerticalAlignment Vertical) DetectionLabelPosition
{
get => (DetectionLabelContainer.HorizontalAlignment, DetectionLabelContainer.VerticalAlignment);
set
{
DetectionLabelContainer.HorizontalAlignment = value.Horizontal;
DetectionLabelContainer.VerticalAlignment = value.Vertical;
}
}
public DetectionControl(DetectionClass detectionClass, TimeSpan time, Action<object,
MouseButtonEventArgs> resizeStart, CanvasLabel canvasLabel)
{
Width = canvasLabel.Width;
Height = canvasLabel.Height;
Time = time;
_resizeStart = resizeStart;
DetectionLabelContainer = new Canvas
{
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Top,
ClipToBounds = false,
};
_detectionLabelPanel = new DetectionLabelPanel
{
Confidence = canvasLabel.Confidence,
DetectionClass = Annotation.DetectionClassesDict[canvasLabel.ClassNumber]
};
DetectionLabelContainer.Children.Add(_detectionLabelPanel);
_selectionFrame = new Rectangle
{
Margin = new Thickness(-3),
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
Stroke = new SolidColorBrush(Colors.Black),
StrokeThickness = 2,
Visibility = Visibility.Collapsed
};
_resizedRectangles =
[
CreateResizeRect("rLT", HorizontalAlignment.Left, VerticalAlignment.Top, Cursors.SizeNWSE),
CreateResizeRect("rCT", HorizontalAlignment.Center, VerticalAlignment.Top, Cursors.SizeNS),
CreateResizeRect("rRT", HorizontalAlignment.Right, VerticalAlignment.Top, Cursors.SizeNESW),
CreateResizeRect("rLC", HorizontalAlignment.Left, VerticalAlignment.Center, Cursors.SizeWE),
CreateResizeRect("rRC", HorizontalAlignment.Right, VerticalAlignment.Center, Cursors.SizeWE),
CreateResizeRect("rLB", HorizontalAlignment.Left, VerticalAlignment.Bottom, Cursors.SizeNESW),
CreateResizeRect("rCB", HorizontalAlignment.Center, VerticalAlignment.Bottom, Cursors.SizeNS),
CreateResizeRect("rRB", HorizontalAlignment.Right, VerticalAlignment.Bottom, Cursors.SizeNWSE)
];
_grid = new Grid
{
Background = Brushes.Transparent,
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
Children = { _selectionFrame }
};
_grid.Children.Add(DetectionLabelContainer);
foreach (var rect in _resizedRectangles)
_grid.Children.Add(rect);
Child = _grid;
Cursor = Cursors.SizeAll;
DetectionClass = detectionClass;
}
//small corners
private Rectangle CreateResizeRect(string name, HorizontalAlignment ha, VerticalAlignment va, Cursor crs)
{
var rect = new Rectangle() // small rectangles at the corners and sides
{
ClipToBounds = false,
Margin = new Thickness(-1.1 * RESIZE_RECT_SIZE),
HorizontalAlignment = ha,
VerticalAlignment = va,
Width = RESIZE_RECT_SIZE,
Height = RESIZE_RECT_SIZE,
Stroke = new SolidColorBrush(Color.FromArgb(230, 20, 20, 20)), // small rectangles color
StrokeThickness = 0.8,
Fill = new SolidColorBrush(Color.FromArgb(150, 80, 80, 80)),
Cursor = crs,
Name = name,
};
rect.MouseDown += (sender, args) => _resizeStart(sender, args);
rect.MouseUp += (sender, args) => { (sender as UIElement)?.ReleaseMouseCapture(); };
return rect;
}
public CanvasLabel ToCanvasLabel() =>
new(DetectionClass.YoloId, Canvas.GetLeft(this), Canvas.GetTop(this), Width, Height);
public YoloLabel ToYoloLabel(Size canvasSize, Size? videoSize = null) =>
new(ToCanvasLabel(), canvasSize, videoSize);
}