messed around with it some more

This commit is contained in:
Yuri Staal 2025-03-03 09:13:18 +01:00
parent 1f7b9770c9
commit ff7fdd8e45
6 changed files with 115 additions and 16 deletions

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

Binary file not shown.

View file

@ -1,7 +1,11 @@
using Crestron.SimplSharp;
using FaceAiSharp;
using FaceAiSharp.Extensions;
using PhotoBooth;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Processing;
namespace CrestronOpenCvSharp.Capture;
@ -16,15 +20,22 @@ public class FacialRecognition
private readonly Dictionary<string, string> _faceImagesDict;
private string? FaceImagePath { get; set; }
private Contract _contract;
public FacialRecognition(string? baseDirectory)
private const string BaseUrl = "https://ise2025.local.staal.one/VirtualControl/MA/Rooms/MYFIRSTAI/Html/";
public FacialRecognition(string? baseDirectory, Contract contract)
{
_baseDirectory = baseDirectory;
_contract = contract;
_detector = FaceAiSharpBundleFactory.CreateFaceDetectorWithLandmarks();
_recognizer = FaceAiSharpBundleFactory.CreateFaceEmbeddingsGenerator();
if (_baseDirectory != null)
if (_baseDirectory != null)
{
FaceImagePath = Path.Combine(_baseDirectory, "aligned.png");
}
// Let's load the default stuff in this dictionary
_faceImagesDict = new Dictionary<string, string>
@ -49,7 +60,19 @@ public class FacialRecognition
if (faces.Count != 0)
{
foreach (var face in faces)
{
var box = face.Box;
_image.Mutate(ctx => ctx.DrawPolygon(Color.Red, 2, new PointF(box.Left, box.Top), new PointF(box.Right, box.Top), new PointF(box.Right, box.Bottom), new PointF(box.Left, box.Bottom)));
}
var fileName = GenerateUniqueFilename();
_image.Save(Path.Combine(_baseDirectory!, fileName!));
_contract.Main.ImagePreview_Url(string.Format($"{BaseUrl}{fileName!}"));
Console.WriteLine($"Sending URL {string.Format($"{BaseUrl}{fileName!}")}");
_recognizer.AlignFaceUsingLandmarks(_image, faces.First().Landmarks!);
_referenceEmbeddings = _recognizer.GenerateEmbedding(_image);
_image.Save(FaceImagePath!);
Console.WriteLine("Aligned faces!");
@ -113,4 +136,26 @@ public class FacialRecognition
var imageBytes = await hc.GetByteArrayAsync(path);
return Image.Load<Rgb24>(imageBytes);
}
/// <summary>
/// Generate a unique filename for the floor plan
/// </summary>
/// <returns>A dynamic string with a randomized number appended to "image"</returns>
private string? GenerateUniqueFilename()
{
try
{
// We are generating random numbers to append to the filename
// We do this to force an update of the image in the browser
var rnd = new Random();
var num = rnd.Next();
var fileName = $"image{num}.jpg";
return fileName;
}
catch (Exception exception)
{
ErrorLog.Exception($"Exception in GenerateUniqueFilename()", exception);
return null;
}
}
}

View file

@ -1,4 +1,7 @@
using Crestron.SimplSharp;
using PhotoBooth;
using RandomNameGeneratorLibrary;
using Timeout = System.Threading.Timeout;
namespace CrestronOpenCvSharp.Capture;
@ -10,15 +13,19 @@ public class MjpegCapture
private readonly FacialRecognition? _facialRecognition;
private Timer? _timer;
private readonly PersonNameGenerator _personNameGenerator;
private Contract _contract;
public bool CaptureRunning { get; private set; }
public MjpegCapture(string? url, string? directory, FacialRecognition? facialRecognition)
private const string BaseUrl = "https://ise2025.local.staal.one/VirtualControl/MA/Rooms/MYFIRSTAI/Html/";
public MjpegCapture(string? url, string? directory, FacialRecognition? facialRecognition, Contract contract)
{
_mjpegUrl = url;
_directory = Path.Combine(directory!, "captures");
_facialRecognition = facialRecognition;
_contract = contract;
_personNameGenerator = new PersonNameGenerator();
}
@ -72,7 +79,8 @@ public class MjpegCapture
try
{
CaptureRunning = true;
var fileName = Path.Combine(_directory!, $"frame_{DateTime.Now:yyyyMMdd_HHmmss}.jpg");
var uniqueName = $"frame_{DateTime.Now:yyyyMMdd_HHmmss}.jpg";
var fileName = Path.Combine(_directory!, uniqueName);
try
{
HttpResponseMessage response = await _client.GetAsync(_mjpegUrl, HttpCompletionOption.ResponseHeadersRead);
@ -85,35 +93,36 @@ public class MjpegCapture
}
Console.WriteLine($"Saved frame to {fileName}");
// TODO Send to image preview window on touchpanel
_contract.Main.ImagePreview_Url(string.Format($"{BaseUrl}/captures/{uniqueName}"));
Console.WriteLine($"Sending URL {string.Format($"{BaseUrl}/captures/{uniqueName}")}");
if (_facialRecognition!.CheckForFace(fileName))
{
StopCapture();
_contract.Main.ImagePreview_Url(string.Empty);
Thread.Sleep(1000);
Console.WriteLine("Face detected, stopping capture");
// TODO Send image to preview window on touchpanel
//Path.Combine(_baseDirectory, "aligned.png"));
Console.WriteLine("Comparing captured face against database");
var result = await _facialRecognition.CompareFaces();
if (result is not null)
{
Console.WriteLine($"We have found a match! The person in front of the camera is: {result}");
_contract.Main.txtFeedback_Indirect($"{result} detected!");
}
else
{
Console.WriteLine("No match was found in our database, let's add this person!");
var randomFullName = _personNameGenerator.GenerateRandomFirstAndLastName();
_facialRecognition.AddPersonToDatabase(randomFullName);
Thread.Sleep(2000);
Console.WriteLine("Person added to database, restarting capture");
StartCapture(2000);
Console.WriteLine("Person added to database");
_contract.Main.txtFeedback_Indirect($"{randomFullName} added to database");
}
}
else
{
Console.WriteLine("No face detected, carrying on!");
_contract.Main.txtFeedback_Indirect($"No face detected!");
}
}
catch (Exception ex)

View file

@ -1,6 +1,8 @@
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.UI;
using CrestronOpenCvSharp.Capture;
using PhotoBooth;
using Directory = Crestron.SimplSharp.CrestronIO.Directory;
using Path = Crestron.SimplSharp.CrestronIO.Path;
@ -11,6 +13,9 @@ public class ControlSystem : CrestronControlSystem
private FacialRecognition? _facialRecognition;
private MjpegCapture? _capture;
private UiHandler? _uiHandler;
private XpanelForHtml5 _xpanel;
private Contract _contract;
// Default snapshot URL of a Bosch camera
private const string Url = "http://192.168.1.221/snap.jpg";
@ -34,15 +39,31 @@ public class ControlSystem : CrestronControlSystem
{
try
{
_facialRecognition = new FacialRecognition(_directory);
_capture = new MjpegCapture(Url, _directory, _facialRecognition);
_xpanel = new XpanelForHtml5(0x03, this);
_xpanel.Register();
_contract = new Contract(_xpanel);
_facialRecognition = new FacialRecognition(_directory, _contract);
_capture = new MjpegCapture(Url, _directory, _facialRecognition, _contract);
_uiHandler = new UiHandler(_capture);
_capture.StartCapture(5000);
_contract.Main.btnStartCapture_PressEvent += MainOnbtnStartCapture_PressEvent;
_contract.Main.btnStopCapture_PressEvent += MainOnbtnStopCapture_PressEvent;
//_capture.StartCapture(5000);
}
catch (Exception e)
{
ErrorLog.Error("Error in InitializeSystem: {0}", e.Message);
}
}
private void MainOnbtnStopCapture_PressEvent(object? sender, UIEventArgs uiEventArgs)
{
_capture?.StopCapture();
}
private void MainOnbtnStartCapture_PressEvent(object? sender, UIEventArgs uiEventArgs)
{
_capture?.StartCapture(2000);
}
}

View file

@ -34,4 +34,22 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\Documents\Crestron\Crestron Construct\Solutions\PhotoBooth\PhotoBooth\output\contract\programming\SIMPLSharp\ContractSupport\ComponentMediator.g.cs">
<Link>UI\ComponentMediator.g.cs</Link>
</Compile>
<Compile Include="..\..\..\Documents\Crestron\Crestron Construct\Solutions\PhotoBooth\PhotoBooth\output\contract\programming\SIMPLSharp\ContractSupport\Contract.g.cs">
<Link>UI\Contract.g.cs</Link>
</Compile>
<Compile Include="..\..\..\Documents\Crestron\Crestron Construct\Solutions\PhotoBooth\PhotoBooth\output\contract\programming\SIMPLSharp\ContractSupport\IndexedEventArgs.g.cs">
<Link>UI\IndexedEventArgs.g.cs</Link>
</Compile>
<Compile Include="..\..\..\Documents\Crestron\Crestron Construct\Solutions\PhotoBooth\PhotoBooth\output\contract\programming\SIMPLSharp\ContractSupport\Main.g.cs">
<Link>UI\Main.g.cs</Link>
</Compile>
<Compile Include="..\..\..\Documents\Crestron\Crestron Construct\Solutions\PhotoBooth\PhotoBooth\output\contract\programming\SIMPLSharp\ContractSupport\UIEventArgs.g.cs">
<Link>UI\UIEventArgs.g.cs</Link>
</Compile>
</ItemGroup>
</Project>