fix editing tiled images

This commit is contained in:
Oleksandr Bezdieniezhnykh
2025-08-14 12:54:32 +03:00
parent eb9e2a6f47
commit d1ce9d9365
6 changed files with 31 additions and 25 deletions
+3 -15
View File
@@ -307,15 +307,8 @@ public class AnnotatorEventHandler(
if (!File.Exists(imgPath)) if (!File.Exists(imgPath))
{ {
var source = (mainWindow.Editor.BackgroundImage.Source as BitmapSource)!; var source = (mainWindow.Editor.BackgroundImage.Source as BitmapSource)!;
if (source.PixelWidth <= Constants.AI_TILE_SIZE * 2 && source.PixelHeight <= Constants.AI_TILE_SIZE * 2) // Allow to be up to 2560*2560 to save to 1280*1280 if (new Size(source.PixelWidth, source.PixelHeight).FitSizeForAI())
{ await source.SaveImage(imgPath, cancellationToken);
//Save image
await using var stream = new FileStream(imgPath, FileMode.Create);
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(source));
encoder.Save(stream);
await stream.FlushAsync(cancellationToken);
}
else else
{ {
//Tiling //Tiling
@@ -335,13 +328,8 @@ public class AnnotatorEventHandler(
var annotationName = $"{formState.MediaName}{Constants.SPLIT_SUFFIX}{res.Tile.Left:0000}_{res.Tile.Top:0000}!".ToTimeName(time); var annotationName = $"{formState.MediaName}{Constants.SPLIT_SUFFIX}{res.Tile.Left:0000}_{res.Tile.Top:0000}!".ToTimeName(time);
var tileImgPath = Path.Combine(dirConfig.Value.ImagesDirectory, $"{annotationName}{Constants.JPG_EXT}"); var tileImgPath = Path.Combine(dirConfig.Value.ImagesDirectory, $"{annotationName}{Constants.JPG_EXT}");
await using var tileStream = new FileStream(tileImgPath, FileMode.Create);
var bitmap = new CroppedBitmap(source, new Int32Rect((int)res.Tile.Left, (int)res.Tile.Top, (int)res.Tile.Width, (int)res.Tile.Height)); var bitmap = new CroppedBitmap(source, new Int32Rect((int)res.Tile.Left, (int)res.Tile.Top, (int)res.Tile.Width, (int)res.Tile.Height));
await bitmap.SaveImage(tileImgPath, cancellationToken);
var tileEncoder = new JpegBitmapEncoder { Frames = [BitmapFrame.Create(bitmap)] };
tileEncoder.Save(tileStream);
await tileStream.FlushAsync(cancellationToken);
tileStream.Close();
var frameSize = new Size(res.Tile.Width, res.Tile.Height); var frameSize = new Size(res.Tile.Width, res.Tile.Height);
var detections = res.Detections var detections = res.Detections
+3 -3
View File
@@ -7,6 +7,7 @@ using System.Windows.Media.Imaging;
using System.Windows.Shapes; using System.Windows.Shapes;
using Azaion.Common.Database; using Azaion.Common.Database;
using Azaion.Common.DTO; using Azaion.Common.DTO;
using Azaion.Common.Extensions;
using MediatR; using MediatR;
using Color = System.Windows.Media.Color; using Color = System.Windows.Media.Color;
using Image = System.Windows.Controls.Image; using Image = System.Windows.Controls.Image;
@@ -473,17 +474,16 @@ public class CanvasEditor : Canvas
public void CreateDetections(Annotation annotation, List<DetectionClass> detectionClasses, Size mediaSize) public void CreateDetections(Annotation annotation, List<DetectionClass> detectionClasses, Size mediaSize)
{ {
var splitTile = annotation.SplitTile;
foreach (var detection in annotation.Detections) foreach (var detection in annotation.Detections)
{ {
var detectionClass = DetectionClass.FromYoloId(detection.ClassNumber, detectionClasses); var detectionClass = DetectionClass.FromYoloId(detection.ClassNumber, detectionClasses);
CanvasLabel canvasLabel; CanvasLabel canvasLabel;
if (splitTile == null) if (!annotation.IsSplit || mediaSize.FitSizeForAI())
canvasLabel = new CanvasLabel(detection, RenderSize, mediaSize, detection.Confidence); canvasLabel = new CanvasLabel(detection, RenderSize, mediaSize, detection.Confidence);
else else
{ {
canvasLabel = new CanvasLabel(detection, new Size(Constants.AI_TILE_SIZE, Constants.AI_TILE_SIZE), null, detection.Confidence) canvasLabel = new CanvasLabel(detection, new Size(Constants.AI_TILE_SIZE, Constants.AI_TILE_SIZE), null, detection.Confidence)
.ReframeFromSmall(splitTile); .ReframeFromSmall(annotation.SplitTile!);
//From CurrentMediaSize to Render Size //From CurrentMediaSize to Render Size
var yoloLabel = new YoloLabel(canvasLabel, mediaSize); var yoloLabel = new YoloLabel(canvasLabel, mediaSize);
@@ -26,4 +26,14 @@ public static class BitmapExtensions
public static Color CreateTransparent(this Color color, byte transparency) => public static Color CreateTransparent(this Color color, byte transparency) =>
Color.FromArgb(transparency, color.R, color.G, color.B); Color.FromArgb(transparency, color.R, color.G, color.B);
public static async Task SaveImage(this BitmapSource bitmap, string path, CancellationToken ct = default)
{
await using var stream = new FileStream(path, FileMode.Create);
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(stream);
await stream.FlushAsync(ct);
}
} }
@@ -0,0 +1,10 @@
using System.Windows;
namespace Azaion.Common.Extensions;
public static class SizeExtensions
{
public static bool FitSizeForAI(this Size size) =>
// Allow to be up to FullHD to save as 1280*1280
size.Width <= Constants.AI_TILE_SIZE * 1.5 && size.Height <= Constants.AI_TILE_SIZE * 1.5;
}
+1
View File
@@ -138,6 +138,7 @@
Header="Редактор" Header="Редактор"
Visibility="Collapsed"> Visibility="Collapsed">
<controls:CanvasEditor x:Name="ExplorerEditor" <controls:CanvasEditor x:Name="ExplorerEditor"
Background="#01000000"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" > HorizontalAlignment="Stretch" >
</controls:CanvasEditor> </controls:CanvasEditor>
+1 -4
View File
@@ -195,10 +195,7 @@ public partial class DatasetExplorer
ThumbnailsView.SelectedIndex = index; ThumbnailsView.SelectedIndex = index;
var ann = CurrentAnnotation.Annotation; var ann = CurrentAnnotation.Annotation;
ExplorerEditor.Background = new ImageBrush ExplorerEditor.SetBackground(await ann.ImagePath.OpenImage());
{
ImageSource = await ann.ImagePath.OpenImage()
};
SwitchTab(toEditor: true); SwitchTab(toEditor: true);
ExplorerEditor.RemoveAllAnns(); ExplorerEditor.RemoveAllAnns();