splitting python complete

This commit is contained in:
Oleksandr Bezdieniezhnykh
2025-08-12 14:48:56 +03:00
parent fc6e5db795
commit ad782bcbaa
31 changed files with 834 additions and 369 deletions
+36 -27
View File
@@ -23,7 +23,7 @@ using MediaPlayer = LibVLCSharp.Shared.MediaPlayer;
namespace Azaion.Annotator;
public class AnnotatorEventHandler(
LibVLC libVLC,
LibVLC libVlc,
MediaPlayer mediaPlayer,
Annotator mainWindow,
FormState formState,
@@ -47,8 +47,7 @@ public class AnnotatorEventHandler(
{
private const int STEP = 20;
private const int LARGE_STEP = 5000;
private const int RESULT_WIDTH = 1280;
private readonly string tempImgPath = Path.Combine(dirConfig.Value.ImagesDirectory, "___temp___.jpg");
private readonly string _tempImgPath = Path.Combine(dirConfig.Value.ImagesDirectory, "___temp___.jpg");
private readonly Dictionary<Key, PlaybackControlEnum> _keysControlEnumDict = new()
{
@@ -144,8 +143,8 @@ public class AnnotatorEventHandler(
if (mediaPlayer.IsPlaying)
{
mediaPlayer.Pause();
mediaPlayer.TakeSnapshot(0, tempImgPath, 0, 0);
mainWindow.Editor.SetBackground(await tempImgPath.OpenImage());
mediaPlayer.TakeSnapshot(0, _tempImgPath, 0, 0);
mainWindow.Editor.SetBackground(await _tempImgPath.OpenImage());
formState.BackgroundTime = TimeSpan.FromMilliseconds(mediaPlayer.Time);
}
else
@@ -238,16 +237,21 @@ public class AnnotatorEventHandler(
return;
var mediaInfo = (MediaFileInfo)mainWindow.LvFiles.SelectedItem;
if (formState.CurrentMedia == mediaInfo)
return; //already loaded
formState.CurrentMedia = mediaInfo;
mainWindow.Title = $"{mainWindow.MainTitle} - {mediaInfo.Name}";
await mainWindow.ReloadAnnotations();
if (mediaInfo.MediaType == MediaTypes.Video)
{
mainWindow.Editor.SetBackground(null);
//need to wait a bit for correct VLC playback event handling
await Task.Delay(100, ct);
mediaPlayer.Stop();
mediaPlayer.Play(new Media(libVLC, mediaInfo.Path));
mediaPlayer.Play(new Media(libVlc, mediaInfo.Path));
}
else
{
@@ -256,6 +260,7 @@ public class AnnotatorEventHandler(
formState.CurrentMediaSize = new Size(image.PixelWidth, image.PixelHeight);
mainWindow.Editor.SetBackground(image);
mediaPlayer.Stop();
mainWindow.ShowTimeAnnotations(TimeSpan.Zero, showImage: true);
}
}
@@ -282,13 +287,14 @@ public class AnnotatorEventHandler(
// var annGrid = mainWindow.DgAnnotations;
// annGrid.SelectedIndex = Math.Min(annGrid.Items.Count, annGrid.SelectedIndex + 1);
// mainWindow.OpenAnnotationResult((AnnotationResult)annGrid.SelectedItem);
mainWindow.Editor.SetBackground(null);
formState.BackgroundTime = null;
}
else
{
await NextMedia(ct: cancellationToken);
}
mainWindow.Editor.SetBackground(null);
formState.BackgroundTime = null;
mainWindow.LvFiles.Items.Refresh();
mainWindow.Editor.RemoveAllAnns();
@@ -301,7 +307,7 @@ public class AnnotatorEventHandler(
if (!File.Exists(imgPath))
{
var source = (mainWindow.Editor.BackgroundImage.Source as BitmapSource)!;
if (source.PixelWidth <= RESULT_WIDTH * 2 && source.PixelHeight <= RESULT_WIDTH * 2) // Allow to be up to 2560*2560 to save to 1280*1280
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
{
//Save image
await using var stream = new FileStream(imgPath, FileMode.Create);
@@ -314,28 +320,28 @@ public class AnnotatorEventHandler(
{
//Tiling
//1. Restore original picture coordinates
var pictureCoordinatesDetections = canvasDetections.Select(x => new CanvasLabel(
//1. Convert from RenderSize to CurrentMediaSize
var detectionCoords = canvasDetections.Select(x => new CanvasLabel(
new YoloLabel(x, mainWindow.Editor.RenderSize, formState.CurrentMediaSize), formState.CurrentMediaSize, null, x.Confidence))
.ToList();
//2. Split to 1280*1280 frames
var results = TileProcessor.Split(formState.CurrentMediaSize, pictureCoordinatesDetections, cancellationToken);
//2. Split to frames
var results = TileProcessor.Split(formState.CurrentMediaSize, detectionCoords, cancellationToken);
//3. Save each frame as a separate annotation
BitmapEncoder tileEncoder = new JpegBitmapEncoder();
foreach (var res in results)
{
var mediaName = $"{formState.MediaName}!split!{res.Tile.X}_{res.Tile.Y}!";
var time = TimeSpan.Zero;
var annotationName = mediaName.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}");
await using var tileStream = new FileStream(tileImgPath, FileMode.Create);
var bitmap = new CroppedBitmap(source, new Int32Rect((int)res.Tile.X, (int)res.Tile.Y, (int)res.Tile.Width, (int)res.Tile.Height));
tileEncoder.Frames.Add(BitmapFrame.Create(bitmap));
var bitmap = new CroppedBitmap(source, new Int32Rect((int)res.Tile.Left, (int)res.Tile.Top, (int)res.Tile.Width, (int)res.Tile.Height));
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 detections = res.Detections
@@ -343,18 +349,18 @@ public class AnnotatorEventHandler(
.Select(x => new Detection(annotationName, new YoloLabel(x, frameSize)))
.ToList();
annotationsResult.Add(await annotationService.SaveAnnotation(mediaName, time, detections, token: cancellationToken));
annotationsResult.Add(await annotationService.SaveAnnotation(formState.MediaName, annotationName, time, detections, token: cancellationToken));
}
return annotationsResult;
}
}
var timeImg = formState.BackgroundTime ?? TimeSpan.FromMilliseconds(mediaPlayer.Time);
var timeName = formState.MediaName.ToTimeName(timeImg);
var annName = formState.MediaName.ToTimeName(timeImg);
var currentDetections = canvasDetections.Select(x =>
new Detection(timeName, new YoloLabel(x, mainWindow.Editor.RenderSize)))
new Detection(annName, new YoloLabel(x, mainWindow.Editor.RenderSize)))
.ToList();
var annotation = await annotationService.SaveAnnotation(formState.MediaName, timeImg, currentDetections, token: cancellationToken);
var annotation = await annotationService.SaveAnnotation(formState.MediaName, annName, timeImg, currentDetections, token: cancellationToken);
return [annotation];
}
@@ -367,15 +373,15 @@ public class AnnotatorEventHandler(
var namesSet = notification.AnnotationNames.ToHashSet();
var remainAnnotations = formState.AnnotationResults
.Where(x => !namesSet.Contains(x.Annotation?.Name ?? "")).ToList();
.Where(x => !namesSet.Contains(x.Name)).ToList();
formState.AnnotationResults.Clear();
foreach (var ann in remainAnnotations)
formState.AnnotationResults.Add(ann);
var timedAnnsToRemove = mainWindow.TimedAnnotations
var timedAnnotationsToRemove = mainWindow.TimedAnnotations
.Where(x => namesSet.Contains(x.Value.Name))
.Select(x => x.Value).ToList();
mainWindow.TimedAnnotations.Remove(timedAnnsToRemove);
mainWindow.TimedAnnotations.Remove(timedAnnotationsToRemove);
if (formState.AnnotationResults.Count == 0)
{
@@ -420,7 +426,10 @@ public class AnnotatorEventHandler(
{
mainWindow.Dispatcher.Invoke(() =>
{
mainWindow.AddAnnotation(e.Annotation);
var mediaInfo = (MediaFileInfo)mainWindow.LvFiles.SelectedItem;
if ((mediaInfo?.FName ?? "") == e.Annotation.OriginalMediaName)
mainWindow.AddAnnotation(e.Annotation);
var log = string.Join(Environment.NewLine, e.Annotation.Detections.Select(det =>
$"Розпізнавання {e.Annotation.OriginalMediaName}: {annotationConfig.Value.DetectionClassesDict[det.ClassNumber].ShortName}: " +