using System.Windows; using System.Windows.Media.Imaging; using Azaion.Common.DTO; namespace Azaion.Common.Services; public class TileResult { public CanvasLabel Tile { get; set; } public List Detections { get; set; } public TileResult(CanvasLabel tile, List detections) { Tile = tile; Detections = detections; } } public static class TileProcessor { private const int MaxTileWidth = 1280; private const int MaxTileHeight = 1280; private const int Border = 10; public static List Split(Size originalSize, List detections, CancellationToken cancellationToken) { var results = new List(); var processingDetectionList = new List(detections); while (processingDetectionList.Count > 0 && !cancellationToken.IsCancellationRequested) { var topMostDetection = processingDetectionList .OrderBy(d => d.Y) .First(); var result = GetDetectionsInTile(originalSize, topMostDetection, processingDetectionList); processingDetectionList.RemoveAll(x => result.Detections.Contains(x)); results.Add(result); } return results; } private static TileResult GetDetectionsInTile(Size originalSize, CanvasLabel startDet, List allDetections) { var tile = new CanvasLabel( left: Math.Max(startDet.X - Border, 0), right: Math.Min(startDet.Right + Border, originalSize.Width), top: Math.Max(startDet.Y - Border, 0), bottom: Math.Min(startDet.Bottom + Border, originalSize.Height)); var selectedDetections = new List{startDet}; foreach (var det in allDetections) { if (det == startDet) continue; var commonTile = new CanvasLabel( left: Math.Max(Math.Min(tile.X, det.X) - Border, 0), right: Math.Min(Math.Max(tile.Right, det.Right) + Border, originalSize.Width), top: Math.Max(Math.Min(tile.Y, det.Y) - Border, 0), bottom: Math.Min(Math.Max(tile.Bottom, det.Bottom) + Border, originalSize.Height) ); if (commonTile.Width > MaxTileWidth || commonTile.Height > MaxTileHeight) continue; tile = commonTile; selectedDetections.Add(det); } //normalization, width and height should be at least half of 1280px tile.Width = Math.Max(tile.Width, MaxTileWidth / 2.0); tile.Height = Math.Max(tile.Height, MaxTileHeight / 2.0); //boundaries check after normalization tile.Right = Math.Min(tile.Right, originalSize.Width); tile.Bottom = Math.Min(tile.Bottom, originalSize.Height); return new TileResult(tile, selectedDetections); } }