mirror of
https://github.com/unclshura/splitter.git
synced 2026-06-22 00:22:01 +00:00
Detection preview added.
This commit is contained in:
parent
42408bba38
commit
18928a23f9
@ -1,6 +1,7 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Splitter_UI;
|
namespace Splitter_UI;
|
||||||
|
|
||||||
@ -31,6 +32,22 @@ internal sealed class Program
|
|||||||
services.AddTransient<StatusBarViewModel>();
|
services.AddTransient<StatusBarViewModel>();
|
||||||
services.AddTransient<LogPaneViewModel>();
|
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)
|
// Domain services (your pipeline)
|
||||||
services.AddTransient<IFileProbeService, FileProbeService>();
|
services.AddTransient<IFileProbeService, FileProbeService>();
|
||||||
services.AddTransient<IThumbnailService, ThumbnailService>();
|
services.AddTransient<IThumbnailService, ThumbnailService>();
|
||||||
|
|||||||
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -38,6 +38,8 @@ public partial class JobViewModel : ObservableObject
|
|||||||
private readonly IThumbnailService _thumbnails;
|
private readonly IThumbnailService _thumbnails;
|
||||||
private readonly IFileProbeService _fileProbe;
|
private readonly IFileProbeService _fileProbe;
|
||||||
private readonly DispatcherTimer _debounceTimer;
|
private readonly DispatcherTimer _debounceTimer;
|
||||||
|
private readonly Func<string, IObjectDetector> _detectorFactory;
|
||||||
|
private readonly ILogger _log;
|
||||||
|
|
||||||
public string FileName => Path.GetFileName(Job.InputFile);
|
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;
|
Job = job;
|
||||||
_thumbnails = thumbnails;
|
_thumbnails = thumbnails;
|
||||||
_fileProbe = fileProbe;
|
_fileProbe = fileProbe;
|
||||||
|
_detectorFactory = detectorFactory;
|
||||||
|
_log = log;
|
||||||
|
|
||||||
ParametersList.Add(new ParameterEntry("DropoutToleranceFrames", ""));
|
ParametersList.Add(new ParameterEntry("DropoutToleranceFrames", ""));
|
||||||
ParametersList.Add(new ParameterEntry("EmaFactor", ""));
|
ParametersList.Add(new ParameterEntry("EmaFactor", ""));
|
||||||
@ -165,10 +169,20 @@ public partial class JobViewModel : ObservableObject
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var frame = await _thumbnails.CreateThumbnailAsync(Job.InputFile, Probe, TimeSpan.FromSeconds(PositionSeconds), Probe.Width, Probe.Height, Job.Rotate);
|
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);
|
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)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
_log.LogError($"Error creating preview for {FileName}: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user