2023-10-20 19:37:19 -07:00

169 lines
6.1 KiB
C#

using DlibDotNet;
using View_by_Distance.Shared.Models.Stateless;
namespace View_by_Distance.FaceRecognitionDotNet.Dlib.Python;
internal sealed class SimpleObjectDetector
{
#region Methods
public static IEnumerable<Rectangle> RunDetectorWithUpscale1(FrontalFaceDetector detector,
Image img,
uint upsamplingAmount,
double adjustThreshold,
List<double> detectionConfidences,
List<ulong> weightIndices)
{
List<Rectangle>? rectangles = [];
if (img.Mode == Mode.Greyscale)
{
Matrix<byte>? greyscaleMatrix = img.Matrix as Matrix<byte>;
if (upsamplingAmount == 0)
{
detector.Operator(greyscaleMatrix, out IEnumerable<RectDetection>? rectDetections, adjustThreshold);
RectDetection[]? dets = rectDetections.ToArray();
SplitRectDetections(dets, rectangles, detectionConfidences, weightIndices);
foreach (RectDetection? rectDetection in dets)
rectDetection.Dispose();
}
else
{
using PyramidDown? pyr = new(2);
Matrix<byte>? temp = null;
try
{
DlibDotNet.Dlib.PyramidUp(greyscaleMatrix, pyr, out temp);
uint levels = upsamplingAmount - 1;
while (levels > 0)
{
levels--;
DlibDotNet.Dlib.PyramidUp(temp);
}
detector.Operator(temp, out IEnumerable<RectDetection>? rectDetections, adjustThreshold);
RectDetection[]? dets = rectDetections.ToArray();
foreach (RectDetection? t in dets)
t.Rect = pyr.RectDown(t.Rect, upsamplingAmount);
SplitRectDetections(dets, rectangles, detectionConfidences, weightIndices);
foreach (RectDetection? rectDetection in dets)
rectDetection.Dispose();
}
finally
{
temp?.Dispose();
}
}
return rectangles;
}
else
{
Matrix<RgbPixel>? rgbMatrix = img.Matrix as Matrix<RgbPixel>;
if (upsamplingAmount == 0)
{
detector.Operator(rgbMatrix, out IEnumerable<RectDetection>? rectDetections, adjustThreshold);
RectDetection[]? dets = rectDetections.ToArray();
SplitRectDetections(dets, rectangles, detectionConfidences, weightIndices);
foreach (RectDetection? rectDetection in dets)
rectDetection.Dispose();
}
else
{
using PyramidDown? pyr = new(2);
Matrix<RgbPixel>? temp = null;
try
{
DlibDotNet.Dlib.PyramidUp(rgbMatrix, pyr, out temp);
uint levels = upsamplingAmount - 1;
while (levels > 0)
{
levels--;
DlibDotNet.Dlib.PyramidUp(temp);
}
detector.Operator(temp, out IEnumerable<RectDetection>? rectDetections, adjustThreshold);
RectDetection[]? dets = rectDetections.ToArray();
foreach (RectDetection? t in dets)
t.Rect = pyr.RectDown(t.Rect, upsamplingAmount);
SplitRectDetections(dets, rectangles, detectionConfidences, weightIndices);
foreach (RectDetection? rectDetection in dets)
rectDetection.Dispose();
}
finally
{
temp?.Dispose();
}
}
return rectangles;
}
}
public static IEnumerable<Tuple<Rectangle, double>> RunDetectorWithUpscale2(FrontalFaceDetector detector,
Image image,
uint upsamplingAmount)
{
if (detector == null)
throw new NullReferenceException(nameof(detector));
if (image == null)
throw new NullReferenceException(nameof(image));
detector.ThrowIfDisposed();
image.ThrowIfDisposed();
List<double>? detectionConfidences = [];
List<ulong>? weightIndices = [];
const double adjustThreshold = 0.0;
Rectangle[]? rects = RunDetectorWithUpscale1(detector,
image,
upsamplingAmount,
adjustThreshold,
detectionConfidences,
weightIndices).ToArray();
int index = 0;
foreach (Rectangle rect in rects)
yield return new Tuple<Rectangle, double>(rect, detectionConfidences[index++]);
}
#region Helpers
private static void SplitRectDetections(RectDetection[] rectDetections,
List<Rectangle> rectangles,
List<double> detectionConfidences,
List<ulong> weightIndices)
{
rectangles.Clear();
detectionConfidences.Clear();
weightIndices.Clear();
foreach (RectDetection? rectDetection in rectDetections)
{
rectangles.Add(rectDetection.Rect);
detectionConfidences.Add(rectDetection.DetectionConfidence);
weightIndices.Add(rectDetection.WeightIndex);
}
}
#endregion
#endregion
}