mirror of
https://github.com/unclshura/splitter.git
synced 2026-06-21 16:12:01 +00:00
82 lines
2.3 KiB
C#
82 lines
2.3 KiB
C#
using System.Runtime.InteropServices;
|
|
using UltraFaceDotNet;
|
|
|
|
namespace splitter.algo;
|
|
|
|
public sealed class UltraFaceDetector: LoggingBase, IDisposable, IObjectDetector
|
|
{
|
|
private readonly UltraFace _ultraFace;
|
|
|
|
public UltraFaceDetector(ILogger logger) : base(logger, -1)
|
|
{
|
|
var basePath = AppDomain.CurrentDomain.BaseDirectory;
|
|
var param = new UltraFaceParameter
|
|
{
|
|
BinFilePath = Path.Combine(basePath, "models", "slim_320.bin"),
|
|
ParamFilePath = Path.Combine(basePath, "models", "slim_320.param"),
|
|
InputWidth = 320,
|
|
InputLength = 240,
|
|
NumThread = 1,
|
|
ScoreThreshold = 0.7f
|
|
};
|
|
|
|
_ultraFace = UltraFace.Create(param);
|
|
}
|
|
|
|
public List<(Rect box, Point2f center)> DetectAll(Mat frameCont)
|
|
{
|
|
// Convert to byte[] for UltraFace
|
|
var bytesFull = frameCont.Rows * frameCont.Cols * frameCont.ElemSize();
|
|
var bgr = new byte[bytesFull];
|
|
Marshal.Copy(frameCont.Data, bgr, 0, bytesFull);
|
|
|
|
var results = new List<(Rect box, Point2f center)>();
|
|
|
|
if (bgr == null || bgr.Length == 0)
|
|
return results;
|
|
|
|
unsafe
|
|
{
|
|
fixed (byte* p = bgr)
|
|
{
|
|
using var mat = NcnnDotNet.Mat.FromPixels(
|
|
(IntPtr)p,
|
|
NcnnDotNet.PixelType.Bgr, // BGR24 input
|
|
frameCont.Width,
|
|
frameCont.Height);
|
|
|
|
var faces = _ultraFace.Detect(mat);
|
|
if (faces == null)
|
|
return results;
|
|
|
|
foreach (var f in faces)
|
|
{
|
|
var x1 = (int)f.X1;
|
|
var y1 = (int)f.Y1;
|
|
var x2 = (int)f.X2;
|
|
var y2 = (int)f.Y2;
|
|
|
|
var rect = new Rect(
|
|
x1,
|
|
y1,
|
|
x2 - x1,
|
|
y2 - y1);
|
|
|
|
if (rect.Width <= 0 || rect.Height <= 0)
|
|
continue;
|
|
|
|
var center = new Point2f(
|
|
rect.X + rect.Width / 2f,
|
|
rect.Y + rect.Height / 2f);
|
|
|
|
results.Add((rect, center));
|
|
}
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
public void Dispose() => _ultraFace?.Dispose();
|
|
}
|