mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 08:36:29 +00:00
fix editing tiled images
This commit is contained in:
@@ -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,14 +328,9 @@ 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
|
||||||
.Select(det => det.ReframeToSmall(res.Tile))
|
.Select(det => det.ReframeToSmall(res.Tile))
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -138,8 +138,9 @@
|
|||||||
Header="Редактор"
|
Header="Редактор"
|
||||||
Visibility="Collapsed">
|
Visibility="Collapsed">
|
||||||
<controls:CanvasEditor x:Name="ExplorerEditor"
|
<controls:CanvasEditor x:Name="ExplorerEditor"
|
||||||
VerticalAlignment="Stretch"
|
Background="#01000000"
|
||||||
HorizontalAlignment="Stretch" >
|
VerticalAlignment="Stretch"
|
||||||
|
HorizontalAlignment="Stretch" >
|
||||||
</controls:CanvasEditor>
|
</controls:CanvasEditor>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem Name="ClassDistributionTab" Header="Розподіл класів">
|
<TabItem Name="ClassDistributionTab" Header="Розподіл класів">
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user