mirror of
https://github.com/unclshura/splitter.git
synced 2026-06-21 16:12:01 +00:00
Detection preview added.
This commit is contained in:
parent
42408bba38
commit
18928a23f9
@ -1,6 +1,7 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Splitter_UI;
|
||||
|
||||
@ -31,12 +32,28 @@ internal sealed class Program
|
||||
services.AddTransient<StatusBarViewModel>();
|
||||
services.AddTransient<LogPaneViewModel>();
|
||||
|
||||
// splitter services
|
||||
services.AddSingleton<UltraFaceDetector>();
|
||||
services.AddSingleton<YoloOnnxObjectDetector>();
|
||||
services.AddSingleton( x => new SingleThreadedDetector<UltraFaceDetector>(x.GetRequiredService<UltraFaceDetector>()) );
|
||||
services.AddSingleton( x => new SingleThreadedDetector<YoloOnnxObjectDetector>(x.GetRequiredService<YoloOnnxObjectDetector>()));
|
||||
services.AddSingleton<Func<string, IObjectDetector>>( x => detectorName =>
|
||||
{
|
||||
return detectorName switch
|
||||
{
|
||||
"face" => x.GetRequiredService<SingleThreadedDetector<UltraFaceDetector>>(),
|
||||
"body" => x.GetRequiredService<SingleThreadedDetector<YoloOnnxObjectDetector>>(),
|
||||
_ => new DummyDetector()
|
||||
};
|
||||
});
|
||||
services.AddSingleton<splitter.ILogger, GlobalLogger>();
|
||||
|
||||
// Domain services (your pipeline)
|
||||
services.AddTransient<IFileProbeService, FileProbeService>();
|
||||
services.AddTransient<IThumbnailService, ThumbnailService>();
|
||||
services.AddTransient<IFileProbeService, FileProbeService>();
|
||||
services.AddTransient<IThumbnailService, ThumbnailService>();
|
||||
services.AddSingleton<IAutoDecisionService, AutoDecisionService>();
|
||||
services.AddSingleton<IProcessingService, ProcessingService>();
|
||||
services.AddSingleton<ILogService, LogService>();
|
||||
services.AddSingleton<IProcessingService, ProcessingService>();
|
||||
services.AddSingleton<ILogService, LogService>();
|
||||
|
||||
services.AddSingleton<IFileJobFactory, FileJobFactory>();
|
||||
|
||||
|
||||
43
Splitter-UI/Services/AvaloniaBitmapExtensions.cs
Normal file
43
Splitter-UI/Services/AvaloniaBitmapExtensions.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Avalonia;
|
||||
using Avalonia.Media.Imaging;
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace Splitter_UI.Services;
|
||||
|
||||
public static class AvaloniaBitmapExtensions
|
||||
{
|
||||
public static Mat ToMatContinuous(this Bitmap bmp)
|
||||
{
|
||||
var w = bmp.PixelSize.Width;
|
||||
var h = bmp.PixelSize.Height;
|
||||
var stride = w * 4;
|
||||
var size = h * stride;
|
||||
|
||||
var buffer = new byte[size];
|
||||
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
||||
|
||||
try
|
||||
{
|
||||
bmp.CopyPixels(
|
||||
new PixelRect(0, 0, w, h),
|
||||
handle.AddrOfPinnedObject(),
|
||||
size,
|
||||
stride);
|
||||
|
||||
return Mat.FromPixelData(h, w, MatType.CV_8UC4, buffer);
|
||||
}
|
||||
finally
|
||||
{
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
public static Mat ToMatBgrContinuous(this Bitmap bmp)
|
||||
{
|
||||
using var bgra = bmp.ToMatContinuous();
|
||||
var bgr = new Mat();
|
||||
Cv2.CvtColor(bgra, bgr, ColorConversionCodes.BGRA2BGR);
|
||||
return bgr;
|
||||
}
|
||||
}
|
||||
12
Splitter-UI/Services/DummyDetector.cs
Normal file
12
Splitter-UI/Services/DummyDetector.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace Splitter_UI.Services;
|
||||
|
||||
internal class DummyDetector : IObjectDetector
|
||||
{
|
||||
public List<(Rect box, splitter.Point2f center)> DetectAll(Mat frameCont) => [];
|
||||
public void Dispose() {}
|
||||
}
|
||||
15
Splitter-UI/Services/GlobalLogger.cs
Normal file
15
Splitter-UI/Services/GlobalLogger.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Splitter_UI.Services;
|
||||
|
||||
internal class GlobalLogger(ILogService _logService) : ILogger
|
||||
{
|
||||
public void ClearProgress(int progressLevel) { }
|
||||
public void DrawProgress(string name, int progressLine, double progress, TimeSpan eta, double speed) { }
|
||||
public void Log(string prefix, ConsoleColor color, string msg)
|
||||
{
|
||||
_logService.Write($"[{prefix}] {msg}");
|
||||
}
|
||||
}
|
||||
23
Splitter-UI/Services/SingleThreadedDetector.cs
Normal file
23
Splitter-UI/Services/SingleThreadedDetector.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace Splitter_UI.Services;
|
||||
|
||||
public class SingleThreadedDetector<T>(IObjectDetector _detector) : IObjectDetector
|
||||
where T : IObjectDetector
|
||||
{
|
||||
private Lock _lock = new();
|
||||
|
||||
public List<(Rect box, splitter.Point2f center)> DetectAll(Mat frameCont)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _detector.DetectAll(frameCont);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if ( _detector is IDisposable d )
|
||||
d.Dispose();
|
||||
}
|
||||
}
|
||||
@ -35,9 +35,11 @@ public partial class JobViewModel : ObservableObject
|
||||
public IRelayCommand StepForwardCommand { get; }
|
||||
public IRelayCommand StepBackwardCommand { get; }
|
||||
|
||||
private readonly IThumbnailService _thumbnails;
|
||||
private readonly IFileProbeService _fileProbe;
|
||||
private readonly DispatcherTimer _debounceTimer;
|
||||
private readonly IThumbnailService _thumbnails;
|
||||
private readonly IFileProbeService _fileProbe;
|
||||
private readonly DispatcherTimer _debounceTimer;
|
||||
private readonly Func<string, IObjectDetector> _detectorFactory;
|
||||
private readonly ILogger _log;
|
||||
|
||||
public string FileName => Path.GetFileName(Job.InputFile);
|
||||
|
||||
@ -115,11 +117,13 @@ public partial class JobViewModel : ObservableObject
|
||||
}
|
||||
}
|
||||
|
||||
public JobViewModel(SingleJob job, IThumbnailService thumbnails, IFileProbeService fileProbe)
|
||||
public JobViewModel(SingleJob job, IThumbnailService thumbnails, IFileProbeService fileProbe, Func<string, IObjectDetector> detectorFactory, ILogger log)
|
||||
{
|
||||
Job = job;
|
||||
_thumbnails = thumbnails;
|
||||
_fileProbe = fileProbe;
|
||||
Job = job;
|
||||
_thumbnails = thumbnails;
|
||||
_fileProbe = fileProbe;
|
||||
_detectorFactory = detectorFactory;
|
||||
_log = log;
|
||||
|
||||
ParametersList.Add(new ParameterEntry("DropoutToleranceFrames", ""));
|
||||
ParametersList.Add(new ParameterEntry("EmaFactor", ""));
|
||||
@ -164,11 +168,21 @@ public partial class JobViewModel : ObservableObject
|
||||
return;
|
||||
try
|
||||
{
|
||||
var frame = await _thumbnails.CreateThumbnailAsync(Job.InputFile, Probe, TimeSpan.FromSeconds(PositionSeconds), Probe.Width, Probe.Height, Job.Rotate);
|
||||
Preview = new PreviewData(frame, [], null);
|
||||
var frame = await _thumbnails.CreateThumbnailAsync(Job.InputFile, Probe, TimeSpan.FromSeconds(PositionSeconds), Probe.Width, Probe.Height, Job.Rotate);
|
||||
if ( frame == null )
|
||||
return;
|
||||
|
||||
Preview = new PreviewData(frame, [], null);
|
||||
|
||||
var detector = _detectorFactory(Job.Detect ?? "");
|
||||
var detections = detector.DetectAll(frame.ToMatContinuous());
|
||||
|
||||
var boxes = detections.Select(x => new Avalonia.Rect(x.box.X, x.box.Y, x.box.Width, x.box.Height)).ToList();
|
||||
Preview = new PreviewData(frame, boxes, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.LogError($"Error creating preview for {FileName}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user