add manual Tile Processor

zoom on video on pause (temp image)
This commit is contained in:
Oleksandr Bezdieniezhnykh
2025-07-28 12:39:52 +03:00
parent fefd054ea0
commit fc6e5db795
34 changed files with 716 additions and 209 deletions
+16 -9
View File
@@ -6,6 +6,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Azaion.Common.DTO;
using Azaion.Common.Events;
using MediatR;
using Color = System.Windows.Media.Color;
using Image = System.Windows.Controls.Image;
@@ -34,10 +35,10 @@ public class CanvasEditor : Canvas
private Point _panStartPoint;
private bool _isZoomedIn;
private const int MIN_SIZE = 20;
private const int MIN_SIZE = 12;
private readonly TimeSpan _viewThreshold = TimeSpan.FromMilliseconds(400);
private Image _backgroundImage { get; set; } = new() { Stretch = Stretch.Fill };
public Image BackgroundImage { get; set; } = new() { Stretch = Stretch.Uniform };
public IMediator Mediator { get; set; } = null!;
public static readonly DependencyProperty GetTimeFuncProp =
@@ -113,7 +114,7 @@ public class CanvasEditor : Canvas
MouseUp += CanvasMouseUp;
SizeChanged += CanvasResized;
Cursor = Cursors.Cross;
Children.Insert(0, _backgroundImage);
Children.Insert(0, BackgroundImage);
Children.Add(_newAnnotationRect);
Children.Add(_horizontalLine);
Children.Add(_verticalLine);
@@ -127,7 +128,7 @@ public class CanvasEditor : Canvas
public void SetBackground(ImageSource? source)
{
SetZoom();
_backgroundImage.Source = source;
BackgroundImage.Source = source;
}
private void SetZoom(Matrix? matrix = null)
@@ -142,8 +143,8 @@ public class CanvasEditor : Canvas
_matrixTransform.Matrix = matrix.Value;
_isZoomedIn = true;
}
foreach (var detection in CurrentDetections)
detection.UpdateAdornerScale(scale: _matrixTransform.Matrix.M11);
// foreach (var detection in CurrentDetections)
// detection.UpdateAdornerScale(scale: _matrixTransform.Matrix.M11);
}
private void CanvasWheel(object sender, MouseWheelEventArgs e)
@@ -175,6 +176,8 @@ public class CanvasEditor : Canvas
private void CanvasMouseDown(object sender, MouseButtonEventArgs e)
{
ClearSelections();
if (e.LeftButton != MouseButtonState.Pressed)
return;
if (Keyboard.Modifiers == ModifierKeys.Control && _isZoomedIn)
{
_panStartPoint = e.GetPosition(this);
@@ -182,11 +185,13 @@ public class CanvasEditor : Canvas
}
else
NewAnnotationStart(sender, e);
(sender as UIElement)?.CaptureMouse();
}
private void CanvasMouseMove(object sender, MouseEventArgs e)
{
var pos = e.GetPosition(this);
Mediator.Publish(new SetStatusTextEvent($"Mouse Coordinates: {pos.X}, {pos.Y}"));
_horizontalLine.Y1 = _horizontalLine.Y2 = pos.Y;
_verticalLine.X1 = _verticalLine.X2 = pos.X;
SetLeft(_classNameHint, pos.X + 10);
@@ -216,11 +221,14 @@ public class CanvasEditor : Canvas
var matrix = _matrixTransform.Matrix;
matrix.Translate(delta.X, delta.Y);
_matrixTransform.Matrix = matrix;
Mediator.Publish(new SetStatusTextEvent(_matrixTransform.Matrix.ToString()));
}
private void CanvasMouseUp(object sender, MouseButtonEventArgs e)
{
(sender as UIElement)?.ReleaseMouseCapture();
if (SelectionState == SelectionState.NewAnnCreating)
{
var endPos = e.GetPosition(this);
@@ -279,8 +287,8 @@ public class CanvasEditor : Canvas
{
_horizontalLine.X2 = e.NewSize.Width;
_verticalLine.Y2 = e.NewSize.Height;
_backgroundImage.Width = e.NewSize.Width;
_backgroundImage.Height = e.NewSize.Height;
BackgroundImage.Width = e.NewSize.Width;
BackgroundImage.Height = e.NewSize.Height;
}
#region Annotation Resizing & Moving
@@ -383,7 +391,6 @@ public class CanvasEditor : Canvas
private void NewAnnotationStart(object sender, MouseButtonEventArgs e)
{
_newAnnotationStartPos = e.GetPosition(this);
SetLeft(_newAnnotationRect, _newAnnotationStartPos.X);
SetTop(_newAnnotationRect, _newAnnotationStartPos.Y);
_newAnnotationRect.MouseMove += NewAnnotationCreatingMove;
+19 -23
View File
@@ -12,15 +12,15 @@ namespace Azaion.Common.Controls;
public class DetectionControl : Border
{
private readonly Action<object, MouseButtonEventArgs> _resizeStart;
private const double RESIZE_RECT_SIZE = 12;
private const double RESIZE_RECT_SIZE = 10;
private readonly Grid _grid;
private readonly Label _detectionLabel;
private readonly DetectionLabelPanel _detectionLabelPanel;
//private readonly Label _detectionLabel;
public readonly Canvas DetectionLabelContainer;
public TimeSpan Time { get; set; }
private readonly double _confidence;
private List<Rectangle> _resizedRectangles = new();
private readonly List<Rectangle> _resizedRectangles = new();
private DetectionClass _detectionClass = null!;
public DetectionClass DetectionClass
@@ -33,9 +33,8 @@ public class DetectionControl : Border
BorderThickness = new Thickness(3);
foreach (var rect in _resizedRectangles)
rect.Stroke = brush;
_detectionLabel.Background = new SolidColorBrush(value.Color.ToConfidenceColor(_confidence));
_detectionLabel.Content = _detectionLabelText(value.UIName);
_detectionLabelPanel.DetectionClass = value;
_detectionClass = value;
}
}
@@ -78,10 +77,7 @@ public class DetectionControl : Border
DetectionLabelContainer.VerticalAlignment = value.Vertical;
}
}
private string _detectionLabelText(string detectionClassName) =>
_confidence >= 0.995 ? detectionClassName : $"{detectionClassName}: {_confidence * 100:F0}%"; //double
public DetectionControl(DetectionClass detectionClass, TimeSpan time, Action<object,
MouseButtonEventArgs> resizeStart, CanvasLabel canvasLabel)
{
@@ -89,7 +85,6 @@ public class DetectionControl : Border
Height = canvasLabel.Height;
Time = time;
_resizeStart = resizeStart;
_confidence = canvasLabel.Confidence;
DetectionLabelContainer = new Canvas
{
@@ -97,16 +92,16 @@ public class DetectionControl : Border
VerticalAlignment = VerticalAlignment.Top,
ClipToBounds = false,
};
_detectionLabel = new Label
_detectionLabelPanel = new DetectionLabelPanel
{
Content = _detectionLabelText(detectionClass.Name),
FontSize = 16,
Visibility = Visibility.Visible
Confidence = canvasLabel.Confidence
};
DetectionLabelContainer.Children.Add(_detectionLabel);
DetectionLabelContainer.Children.Add(_detectionLabelPanel);
_selectionFrame = new Rectangle
{
Margin = new Thickness(-3),
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
Stroke = new SolidColorBrush(Colors.Black),
@@ -146,12 +141,13 @@ public class DetectionControl : Border
var rect = new Rectangle() // small rectangles at the corners and sides
{
ClipToBounds = false,
Margin = new Thickness(-RESIZE_RECT_SIZE * 0.7),
Margin = new Thickness(-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,
@@ -160,9 +156,9 @@ public class DetectionControl : Border
return rect;
}
public YoloLabel GetLabel(Size canvasSize, Size? videoSize = null)
{
var label = new CanvasLabel(DetectionClass.YoloId, Canvas.GetLeft(this), Canvas.GetTop(this), Width, Height);
return new YoloLabel(label, canvasSize, videoSize);
}
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);
}
@@ -0,0 +1,59 @@
<UserControl x:Class="Azaion.Common.Controls.DetectionLabelPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
mc:Ignorable="d">
<UserControl.Resources>
<!-- Friendly (Light Blue Square) -->
<DrawingImage x:Key="Friendly">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V320 H320 V0 H0 Z">
<GeometryDrawing Brush="LightBlue" Geometry="M25,50 l150,0 0,100 -150,0 z">
<GeometryDrawing.Pen>
<Pen Brush="Black" Thickness="8"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<!-- Hostile (Red Diamond) -->
<DrawingImage x:Key="Hostile">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V320 H320 V0 H0 Z">
<GeometryDrawing Brush="Red" Geometry="M 100,28 L172,100 100,172 28,100 100,28 Z">
<GeometryDrawing.Pen>
<Pen Brush="Black" Thickness="8"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<!-- Unknown (Yellow Quatrefoil) -->
<DrawingImage x:Key="Unknown">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V320 H320 V0 H0 Z">
<GeometryDrawing Brush="Yellow" Geometry="M63,63 C63,20 137,20 137,63 C180,63 180,137 137,137 C137,180
63,180 63,137 C20,137 20,63 63,63 Z">
<GeometryDrawing.Pen>
<Pen Brush="Black" Thickness="8"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="28"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" x:Name="AffiliationImage">
</Image>
<Label Grid.Column="1" FontSize="16"></Label>
</Grid>
</UserControl>
@@ -0,0 +1,55 @@
using System.Windows.Media;
using Azaion.Common.DTO;
namespace Azaion.Common.Controls
{
public partial class DetectionLabelPanel
{
private AffiliationEnum _affiliation = AffiliationEnum.None;
private double _confidence;
public AffiliationEnum Affiliation
{
get => _affiliation;
set
{
_affiliation = value;
UpdateAffiliationImage();
}
}
public DetectionClass DetectionClass { get; set; }
public double Confidence
{
get => _confidence;
set
{
_confidence = value;
}
}
public DetectionLabelPanel()
{
InitializeComponent();
}
private string _detectionLabelText(string detectionClassName) =>
_confidence >= 0.98 ? detectionClassName : $"{detectionClassName}: {_confidence * 100:F0}%";
private void UpdateAffiliationImage()
{
if (_affiliation == AffiliationEnum.None)
{
AffiliationImage.Source = null;
return;
}
if (TryFindResource(_affiliation.ToString()) is DrawingImage drawingImage)
AffiliationImage.Source = drawingImage;
else
AffiliationImage.Source = null;
}
}
}