mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 10:56:31 +00:00
clamp detections to media borders - create, move, resize
fix inference start fix config fix resize rectangles show
This commit is contained in:
@@ -7,7 +7,6 @@ using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using Azaion.Common.Database;
|
||||
using Azaion.Common.DTO;
|
||||
using Azaion.Common.Events;
|
||||
using MediatR;
|
||||
using Color = System.Windows.Media.Color;
|
||||
using Image = System.Windows.Controls.Image;
|
||||
@@ -40,7 +39,8 @@ public class CanvasEditor : Canvas
|
||||
private readonly TimeSpan _viewThreshold = TimeSpan.FromMilliseconds(400);
|
||||
|
||||
public Image BackgroundImage { get; set; } = new() { Stretch = Stretch.Uniform };
|
||||
|
||||
private RectangleF? _clampedRect;
|
||||
|
||||
public static readonly DependencyProperty GetTimeFuncProp =
|
||||
DependencyProperty.Register(
|
||||
nameof(GetTimeFunc),
|
||||
@@ -129,6 +129,7 @@ public class CanvasEditor : Canvas
|
||||
{
|
||||
SetZoom();
|
||||
BackgroundImage.Source = source;
|
||||
UpdateClampedRect();
|
||||
}
|
||||
|
||||
private void SetZoom(Matrix? matrix = null)
|
||||
@@ -190,7 +191,7 @@ public class CanvasEditor : Canvas
|
||||
|
||||
private void CanvasMouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
var pos = e.GetPosition(this);
|
||||
var pos = GetClampedPosition(e);
|
||||
_horizontalLine.Y1 = _horizontalLine.Y2 = pos.Y;
|
||||
_verticalLine.X1 = _verticalLine.X2 = pos.X;
|
||||
SetLeft(_classNameHint, pos.X + 10);
|
||||
@@ -199,24 +200,36 @@ public class CanvasEditor : Canvas
|
||||
switch (SelectionState)
|
||||
{
|
||||
case SelectionState.NewAnnCreating:
|
||||
NewAnnotationCreatingMove(sender, e);
|
||||
NewAnnotationCreatingMove(pos);
|
||||
break;
|
||||
case SelectionState.AnnResizing:
|
||||
AnnotationResizeMove(sender, e);
|
||||
AnnotationResizeMove(pos);
|
||||
break;
|
||||
case SelectionState.AnnMoving:
|
||||
AnnotationPositionMove(sender, e);
|
||||
AnnotationPositionMove(pos);
|
||||
e.Handled = true;
|
||||
break;
|
||||
case SelectionState.PanZoomMoving:
|
||||
PanZoomMove(sender, e);
|
||||
PanZoomMove(pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void PanZoomMove(object sender, MouseEventArgs e)
|
||||
private Point GetClampedPosition(MouseEventArgs e)
|
||||
{
|
||||
var currentPoint = e.GetPosition(this);
|
||||
var delta = currentPoint - _panStartPoint;
|
||||
var pos = e.GetPosition(this);
|
||||
return !_clampedRect.HasValue
|
||||
? pos
|
||||
: new Point
|
||||
(
|
||||
Math.Clamp(pos.X, _clampedRect.Value.X, _clampedRect.Value.Right),
|
||||
Math.Clamp(pos.Y, _clampedRect.Value.Y, _clampedRect.Value.Bottom)
|
||||
);
|
||||
}
|
||||
|
||||
private void PanZoomMove(Point point)
|
||||
{
|
||||
var delta = point - _panStartPoint;
|
||||
|
||||
var matrix = _matrixTransform.Matrix;
|
||||
matrix.Translate(delta.X, delta.Y);
|
||||
@@ -229,7 +242,7 @@ public class CanvasEditor : Canvas
|
||||
(sender as UIElement)?.ReleaseMouseCapture();
|
||||
if (SelectionState == SelectionState.NewAnnCreating)
|
||||
{
|
||||
var endPos = e.GetPosition(this);
|
||||
var endPos = GetClampedPosition(e);
|
||||
_newAnnotationRect.Width = 0;
|
||||
_newAnnotationRect.Height = 0;
|
||||
var width = Math.Abs(endPos.X - _newAnnotationStartPos.X);
|
||||
@@ -262,14 +275,14 @@ public class CanvasEditor : Canvas
|
||||
var origin = lb.TranslatePoint(new Point(0, 0), this);
|
||||
lb.Children[0].Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
|
||||
var size = lb.Children[0].DesiredSize;
|
||||
var lbRect = new RectangleF((float)origin.X, (float)origin.Y, (float)size.Width, (float)size.Height);
|
||||
var controlLabel = new RectangleF((float)origin.X, (float)origin.Y, (float)size.Width, (float)size.Height);
|
||||
|
||||
foreach (var c in CurrentDetections)
|
||||
{
|
||||
if (c == detectionControl)
|
||||
continue;
|
||||
var detRect = new RectangleF((float)GetLeft(c), (float)GetTop(c), (float)c.Width, (float)c.Height);
|
||||
detRect.Intersect(lbRect);
|
||||
detRect.Intersect(controlLabel);
|
||||
|
||||
|
||||
// var intersect = detections[i].ToRectangle();
|
||||
@@ -287,8 +300,44 @@ public class CanvasEditor : Canvas
|
||||
_verticalLine.Y2 = e.NewSize.Height;
|
||||
BackgroundImage.Width = e.NewSize.Width;
|
||||
BackgroundImage.Height = e.NewSize.Height;
|
||||
UpdateClampedRect();
|
||||
}
|
||||
|
||||
|
||||
private void UpdateClampedRect()
|
||||
{
|
||||
if (BackgroundImage.Source is not BitmapSource imageSource)
|
||||
{
|
||||
_clampedRect = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var imgWidth = imageSource.PixelWidth;
|
||||
var imgHeight = imageSource.PixelHeight;
|
||||
var canvasWidth = ActualWidth;
|
||||
var canvasHeight = ActualHeight;
|
||||
|
||||
var imgRatio = imgWidth / (double)imgHeight;
|
||||
var canvasRatio = canvasWidth / canvasHeight;
|
||||
|
||||
double renderedWidth;
|
||||
double renderedHeight;
|
||||
|
||||
if (imgRatio > canvasRatio)
|
||||
{
|
||||
renderedWidth = canvasWidth;
|
||||
renderedHeight = canvasWidth / imgRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
renderedHeight = canvasHeight;
|
||||
renderedWidth = canvasHeight * imgRatio;
|
||||
}
|
||||
var xOffset = (canvasWidth - renderedWidth) / 2;
|
||||
var yOffset = (canvasHeight - renderedHeight) / 2;
|
||||
|
||||
_clampedRect = new RectangleF((float)xOffset, (float)yOffset, (float)renderedWidth, (float)renderedHeight);
|
||||
}
|
||||
|
||||
#region Annotation Resizing & Moving
|
||||
|
||||
private void AnnotationResizeStart(object sender, MouseEventArgs e)
|
||||
@@ -300,17 +349,15 @@ public class CanvasEditor : Canvas
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void AnnotationResizeMove(object sender, MouseEventArgs e)
|
||||
private void AnnotationResizeMove(Point point)
|
||||
{
|
||||
if (SelectionState != SelectionState.AnnResizing)
|
||||
return;
|
||||
|
||||
var currentPos = e.GetPosition(this);
|
||||
|
||||
var x = GetLeft(_curAnn);
|
||||
var y = GetTop(_curAnn);
|
||||
var offsetX = currentPos.X - _lastPos.X;
|
||||
var offsetY = currentPos.Y - _lastPos.Y;
|
||||
var offsetX = point.X - _lastPos.X;
|
||||
var offsetY = point.Y - _lastPos.Y;
|
||||
switch (_curRec.HorizontalAlignment, _curRec.VerticalAlignment)
|
||||
{
|
||||
case (HorizontalAlignment.Left, VerticalAlignment.Top):
|
||||
@@ -350,7 +397,7 @@ public class CanvasEditor : Canvas
|
||||
_curAnn.Height = Math.Max(MIN_SIZE, _curAnn.Height + offsetY);
|
||||
break;
|
||||
}
|
||||
_lastPos = currentPos;
|
||||
_lastPos = point;
|
||||
}
|
||||
|
||||
private void AnnotationPositionStart(object sender, MouseEventArgs e)
|
||||
@@ -367,19 +414,26 @@ public class CanvasEditor : Canvas
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void AnnotationPositionMove(object sender, MouseEventArgs e)
|
||||
private void AnnotationPositionMove(Point point)
|
||||
{
|
||||
if (SelectionState != SelectionState.AnnMoving)
|
||||
return;
|
||||
|
||||
var currentPos = e.GetPosition(this);
|
||||
var offsetX = currentPos.X - _lastPos.X;
|
||||
var offsetY = currentPos.Y - _lastPos.Y;
|
||||
|
||||
SetLeft(_curAnn, GetLeft(_curAnn) + offsetX);
|
||||
SetTop(_curAnn, GetTop(_curAnn) + offsetY);
|
||||
_lastPos = currentPos;
|
||||
e.Handled = true;
|
||||
var offsetX = point.X - _lastPos.X;
|
||||
var offsetY = point.Y - _lastPos.Y;
|
||||
|
||||
var nextLeft = GetLeft(_curAnn) + offsetX;
|
||||
var nextTop = GetTop(_curAnn) + offsetY;
|
||||
|
||||
if (_clampedRect.HasValue)
|
||||
{
|
||||
nextLeft = Math.Clamp(nextLeft, _clampedRect.Value.X, _clampedRect.Value.Right - _curAnn.Width);
|
||||
nextTop = Math.Clamp(nextTop, _clampedRect.Value.Y, _clampedRect.Value.Bottom - _curAnn.Height);
|
||||
}
|
||||
|
||||
SetLeft(_curAnn, nextLeft);
|
||||
SetTop(_curAnn, nextTop);
|
||||
_lastPos = point;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -391,26 +445,29 @@ public class CanvasEditor : Canvas
|
||||
_newAnnotationStartPos = e.GetPosition(this);
|
||||
SetLeft(_newAnnotationRect, _newAnnotationStartPos.X);
|
||||
SetTop(_newAnnotationRect, _newAnnotationStartPos.Y);
|
||||
_newAnnotationRect.MouseMove += NewAnnotationCreatingMove;
|
||||
_newAnnotationRect.MouseMove += (sender, e) =>
|
||||
{
|
||||
var currentPos = e.GetPosition(this);
|
||||
NewAnnotationCreatingMove(currentPos);
|
||||
};
|
||||
|
||||
SelectionState = SelectionState.NewAnnCreating;
|
||||
}
|
||||
|
||||
private void NewAnnotationCreatingMove(object sender, MouseEventArgs e)
|
||||
private void NewAnnotationCreatingMove(Point point)
|
||||
{
|
||||
if (SelectionState != SelectionState.NewAnnCreating)
|
||||
return;
|
||||
|
||||
var currentPos = e.GetPosition(this);
|
||||
var diff = currentPos - _newAnnotationStartPos;
|
||||
var diff = point - _newAnnotationStartPos;
|
||||
|
||||
_newAnnotationRect.Height = Math.Abs(diff.Y);
|
||||
_newAnnotationRect.Width = Math.Abs(diff.X);
|
||||
|
||||
if (diff.X < 0)
|
||||
SetLeft(_newAnnotationRect, currentPos.X);
|
||||
SetLeft(_newAnnotationRect, point.X);
|
||||
if (diff.Y < 0)
|
||||
SetTop(_newAnnotationRect, currentPos.Y);
|
||||
SetTop(_newAnnotationRect, point.Y);
|
||||
}
|
||||
|
||||
public void CreateDetections(Annotation annotation, List<DetectionClass> detectionClasses, Size mediaSize)
|
||||
@@ -432,7 +489,9 @@ public class CanvasEditor : Canvas
|
||||
canvasLabel = new CanvasLabel(yoloLabel, RenderSize, mediaSize, canvasLabel.Confidence);
|
||||
}
|
||||
|
||||
CreateDetectionControl(detectionClass, annotation.Time, canvasLabel);
|
||||
var control = CreateDetectionControl(detectionClass, annotation.Time, canvasLabel);
|
||||
control.UpdateLayout();
|
||||
CheckLabelBoundaries(control);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,9 +540,7 @@ public class CanvasEditor : Canvas
|
||||
.ToList();
|
||||
RemoveAnnotations(expiredAnns);
|
||||
}
|
||||
|
||||
public void ResetBackground() => Background = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0));
|
||||
|
||||
|
||||
public void ZoomTo(Point point)
|
||||
{
|
||||
SetZoom();
|
||||
|
||||
@@ -127,9 +127,9 @@ public class DetectionControl : Border
|
||||
VerticalAlignment = VerticalAlignment.Stretch,
|
||||
Children = { _selectionFrame }
|
||||
};
|
||||
_grid.Children.Add(DetectionLabelContainer);
|
||||
foreach (var rect in _resizedRectangles)
|
||||
_grid.Children.Add(rect);
|
||||
_grid.Children.Add(DetectionLabelContainer);
|
||||
|
||||
Child = _grid;
|
||||
Cursor = Cursors.SizeAll;
|
||||
|
||||
Reference in New Issue
Block a user