mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 22:16:30 +00:00
263 lines
9.1 KiB
C#
263 lines
9.1 KiB
C#
using System.Windows;
|
|
using Azaion.Common;
|
|
using Azaion.Common.DTO;
|
|
using Azaion.Common.Services;
|
|
using Xunit;
|
|
|
|
namespace Azaion.Annotator.Test;
|
|
|
|
public class TileProcessorTest
|
|
{
|
|
private const int IMAGE_SIZE = 5000;
|
|
|
|
[Fact]
|
|
public void Split_DetectionsNearImageCorners_ShouldCreateFourTiles()
|
|
{
|
|
// Arrange
|
|
var originalSize = new Size(IMAGE_SIZE, IMAGE_SIZE);
|
|
var detections = new List<CanvasLabel>
|
|
{
|
|
new(10, 60, 10, 60), // Top-left corner
|
|
new(IMAGE_SIZE - 60, IMAGE_SIZE - 10, 10, 60), // Top-right corner
|
|
new(10, 60, IMAGE_SIZE - 60, IMAGE_SIZE - 10), // Bottom-left corner
|
|
new(IMAGE_SIZE - 60, IMAGE_SIZE - 10, IMAGE_SIZE - 60, IMAGE_SIZE - 10) // Bottom-right corner
|
|
};
|
|
|
|
// Act
|
|
var results = TileProcessor.Split(originalSize, detections, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Equal(4, results.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void Split_DetectionsFarApartButFitInOneTile_ShouldCreateOneTile()
|
|
{
|
|
// Arrange
|
|
var originalSize = new Size(IMAGE_SIZE, IMAGE_SIZE);
|
|
var detections = new List<CanvasLabel>
|
|
{
|
|
new(100, 150, 100, 150),
|
|
new(1200, 1250, 1200, 1250)
|
|
};
|
|
|
|
// Act
|
|
var results = TileProcessor.Split(originalSize, detections, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Single(results);
|
|
Assert.Equal(2, results[0].Detections.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void Split_DetectionsTooFarApart_ShouldCreateMultipleTiles()
|
|
{
|
|
// Arrange
|
|
var originalSize = new Size(IMAGE_SIZE, IMAGE_SIZE);
|
|
var detections = new List<CanvasLabel>
|
|
{
|
|
new(100, 150, 100, 150),
|
|
new(2000, 2050, 2000, 2050) // More than Constants.AI_TILE_SIZE away
|
|
};
|
|
|
|
// Act
|
|
var results = TileProcessor.Split(originalSize, detections, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Equal(2, results.Count);
|
|
Assert.Contains(results, r => r.Detections.Count == 1 && r.Detections.Contains(detections[0]));
|
|
Assert.Contains(results, r => r.Detections.Count == 1 && r.Detections.Contains(detections[1]));
|
|
}
|
|
|
|
[Fact]
|
|
public void Split_ComplexScenario_ShouldCreateCorrectNumberOfTiles()
|
|
{
|
|
// Arrange
|
|
var originalSize = new Size(IMAGE_SIZE, IMAGE_SIZE);
|
|
var detections = new List<CanvasLabel>
|
|
{
|
|
// Group 1 (should be tiled together)
|
|
new(100, 150, 100, 150),
|
|
new(200, 250, 200, 250),
|
|
new(500, 550, 500, 550),
|
|
// Group 2 (far from group 1, should be in a separate tile)
|
|
new(3000, 3050, 3000, 3050),
|
|
new(3100, 3150, 3100, 3150),
|
|
};
|
|
|
|
// Act
|
|
var results = TileProcessor.Split(originalSize, detections, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Equal(2, results.Count);
|
|
var group1Tile = results.FirstOrDefault(r => r.Detections.Count == 3);
|
|
var group2Tile = results.FirstOrDefault(r => r.Detections.Count == 2);
|
|
|
|
Assert.NotNull(group1Tile);
|
|
Assert.NotNull(group2Tile);
|
|
|
|
Assert.Contains(detections[0], group1Tile.Detections);
|
|
Assert.Contains(detections[1], group1Tile.Detections);
|
|
Assert.Contains(detections[2], group1Tile.Detections);
|
|
|
|
Assert.Contains(detections[3], group2Tile.Detections);
|
|
Assert.Contains(detections[4], group2Tile.Detections);
|
|
}
|
|
|
|
[Fact]
|
|
public void Split_NoDetections_ShouldReturnEmptyList()
|
|
{
|
|
// Arrange
|
|
var originalSize = new Size(IMAGE_SIZE, IMAGE_SIZE);
|
|
var detections = new List<CanvasLabel>();
|
|
|
|
// Act
|
|
var results = TileProcessor.Split(originalSize, detections, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Empty(results);
|
|
}
|
|
|
|
[Fact]
|
|
public void Split_OneDetection_ShouldCreateOneTile()
|
|
{
|
|
// Arrange
|
|
var originalSize = new Size(IMAGE_SIZE, IMAGE_SIZE);
|
|
var detections = new List<CanvasLabel> { new(100, 150, 100, 150) };
|
|
|
|
// Act
|
|
var results = TileProcessor.Split(originalSize, detections, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Single(results);
|
|
Assert.Single(results[0].Detections);
|
|
Assert.Equal(detections[0], results[0].Detections[0]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Split_DetectionsOnTileBoundary_ShouldFitInOneTile()
|
|
{
|
|
// Arrange
|
|
var originalSize = new Size(IMAGE_SIZE, IMAGE_SIZE);
|
|
// Combined width is 1270. 1270 + BORDER (10) is not > Constants.AI_TILE_SIZE (1280), so they fit.
|
|
var detections = new List<CanvasLabel>
|
|
{
|
|
new(0, 50, 0, 50),
|
|
new(Constants.AI_TILE_SIZE - TileProcessor.BORDER - 50, Constants.AI_TILE_SIZE - TileProcessor.BORDER, 0, 50)
|
|
};
|
|
|
|
// Act
|
|
var results = TileProcessor.Split(originalSize, detections, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Single(results);
|
|
Assert.Equal(2, results[0].Detections.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void Split_DetectionsJustOverTileBoundary_ShouldCreateTwoTiles()
|
|
{
|
|
// Arrange
|
|
var originalSize = new Size(IMAGE_SIZE, IMAGE_SIZE);
|
|
// Combined width is 1271. 1271 + BORDER (10) is > Constants.AI_TILE_SIZE (1280), so they don't fit.
|
|
var detections = new List<CanvasLabel>
|
|
{
|
|
new(0, 50, 1000, 1050), // Top-most
|
|
new(Constants.AI_TILE_SIZE - TileProcessor.BORDER - 49, Constants.AI_TILE_SIZE - TileProcessor.BORDER + 1, 0, 50)
|
|
};
|
|
|
|
// Act
|
|
var results = TileProcessor.Split(originalSize, detections, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Equal(2, results.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void Split_ResultingTiles_ShouldBeWithinImageBoundaries()
|
|
{
|
|
// Arrange
|
|
var originalSize = new Size(IMAGE_SIZE, IMAGE_SIZE);
|
|
var detections = new List<CanvasLabel>
|
|
{
|
|
new(10, 60, 10, 60), // Top-left corner
|
|
new(IMAGE_SIZE - 60, IMAGE_SIZE - 10, IMAGE_SIZE - 60, IMAGE_SIZE - 10) // Bottom-right corner
|
|
};
|
|
|
|
// Act
|
|
var results = TileProcessor.Split(originalSize, detections, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Equal(2, results.Count);
|
|
foreach (var result in results)
|
|
{
|
|
var tile = result.Tile;
|
|
Assert.True(tile.Left >= 0, $"Tile Left boundary {tile.Left} is out of bounds.");
|
|
Assert.True(tile.Top >= 0, $"Tile Top boundary {tile.Top} is out of bounds.");
|
|
Assert.True(tile.Right <= originalSize.Width, $"Tile Right boundary {tile.Right} is out of bounds.");
|
|
Assert.True(tile.Bottom <= originalSize.Height, $"Tile Bottom boundary {tile.Bottom} is out of bounds.");
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Split_ChainedDetections_ShouldCreateOneTile()
|
|
{
|
|
// Arrange
|
|
var originalSize = new Size(IMAGE_SIZE, IMAGE_SIZE);
|
|
var detections = new List<CanvasLabel>
|
|
{
|
|
new(100, 200, 100, 200), // Detection A
|
|
new(600, 700, 600, 700), // Detection B (close to A)
|
|
new(1100, 1200, 1100, 1200) // Detection C (close to B, but far from A)
|
|
};
|
|
|
|
// Act
|
|
var results = TileProcessor.Split(originalSize, detections, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Single(results);
|
|
Assert.Equal(3, results[0].Detections.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void Split_SingleDetectionLargerThanTileSize_ShouldCreateOneTile()
|
|
{
|
|
// Arrange
|
|
var originalSize = new Size(IMAGE_SIZE, IMAGE_SIZE);
|
|
var largeDetection = new CanvasLabel(100, 100 + Constants.AI_TILE_SIZE + 100, 100, 200);
|
|
var detections = new List<CanvasLabel> { largeDetection };
|
|
|
|
// Act
|
|
var results = TileProcessor.Split(originalSize, detections, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Single(results);
|
|
var resultTile = results[0];
|
|
Assert.Single(resultTile.Detections);
|
|
Assert.Equal(largeDetection, resultTile.Detections[0]);
|
|
// The tile should be at least as large as the detection it contains.
|
|
Assert.True(resultTile.Tile.Width >= largeDetection.Width);
|
|
Assert.True(resultTile.Tile.Height >= largeDetection.Height);
|
|
}
|
|
|
|
[Fact]
|
|
public void Split_LargeDetectionWithNearbySmallDetection_ShouldCreateOneTile()
|
|
{
|
|
// Arrange
|
|
var originalSize = new Size(IMAGE_SIZE, IMAGE_SIZE);
|
|
var largeTallDetection = new CanvasLabel(100, 150, 100, 100 + Constants.AI_TILE_SIZE + 200);
|
|
var smallDetectionNearby = new CanvasLabel(largeTallDetection.Right + 15, largeTallDetection.Right + 35, 700, 720);
|
|
|
|
var detections = new List<CanvasLabel> { largeTallDetection, smallDetectionNearby };
|
|
|
|
// Act
|
|
var results = TileProcessor.Split(originalSize, detections, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Single(results);
|
|
Assert.Equal(2, results[0].Detections.Count);
|
|
Assert.Contains(largeTallDetection, results[0].Detections);
|
|
Assert.Contains(smallDetectionNearby, results[0].Detections);
|
|
}
|
|
|
|
} |