Skip to content

Commit

Permalink
Ready for people-merge UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Webreaper committed Mar 6, 2024
1 parent 50cd613 commit 639a12b
Show file tree
Hide file tree
Showing 8 changed files with 1,279 additions and 38 deletions.
Binary file modified .DS_Store
Binary file not shown.
26 changes: 14 additions & 12 deletions Damselfly.Core/Services/ImageRecognitionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,21 +254,22 @@ private async Task LoadPersonCache(bool force = false)
using var db = scope.ServiceProvider.GetService<ImageContext>();

var identifiedPeople = await db.People.Where(x => !string.IsNullOrEmpty(x.PersonGuid))
.Include(x => x.FaceData)
.Where( x => x.FaceData.Count > 0)
.AsNoTracking()
.ToListAsync();

if( identifiedPeople.Any() )
{
// Merge the items into the people cache. Note that we use
// the indexer to avoid dupe key issues. TODO: Should the table be unique?
foreach( var pair in identifiedPeople.ToDictionary( x => x.PersonGuid!, x => x) )
_peopleCache[pair.Key] = pair.Value;

// Now create the dictionary of embeddings. Parse the floats out from the comma-separated string,
// and load them into the ONNX embeddings collection.
var embeddings = identifiedPeople.ToDictionary(x => x.PersonGuid,
x => x.FaceData.Select( x => x.Embeddings) );

// Populate the people cache
foreach( var person in identifiedPeople )
_peopleCache[person.PersonGuid] = person;

// Now populate the embeddings lookup
var embeddings = identifiedPeople.ToDictionary(
x => x.PersonGuid,
x => x.FaceData.Select( e => e.Embeddings));

_faceOnnxService.LoadFaceEmbeddings(embeddings);

Logging.LogTrace("Pre-loaded cach with {0} people.", _peopleCache.Count());
Expand Down Expand Up @@ -310,12 +311,13 @@ public async Task CreateMissingPeople(IEnumerable<ImageDetectResult> detectedFac
State = Person.PersonState.Unknown,
LastUpdated = DateTime.UtcNow,
PersonGuid = x.PersonGuid,
FaceData = new List<PersonFaceData> { new PersonFaceData { Embeddings = string.Join( ",", x.Embeddings) } },
FaceData = new List<PersonFaceData> { new() { Embeddings = string.Join( ",", x.Embeddings) } },
}).ToList();

if ( newPeople.Any() )
{
await db.BulkInsert(db.People, newPeople);
await db.People.AddRangeAsync( newPeople );
await db.SaveChangesAsync();

// Add or replace the new people in the cache (this should always add)
newPeople.ForEach(x => _peopleCache[x.PersonGuid] = x);
Expand Down
22 changes: 17 additions & 5 deletions Damselfly.ML.FaceONNX/Embeddings.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UMapx.Core;

namespace FaceEmbeddingsClassification;
Expand All @@ -9,7 +10,7 @@ namespace FaceEmbeddingsClassification;
/// </summary>
public class Embeddings
{
private Dictionary<string, List<float[]>> VectorLookup = new();
private readonly Dictionary<string, List<float[]>> VectorLookup = new();

public Embeddings()
{
Expand All @@ -23,24 +24,35 @@ public Embeddings()
/// <param name="labels">Labels</param>
public Embeddings(Dictionary<string, List<float[]>> vectorLookups)
{
VectorLookup = vectorLookups;
Clear();

foreach( var pair in vectorLookups )
VectorLookup[pair.Key] = pair.Value;
}

private float[] GetVectorFromString( string s )
{
return s.Split(",", StringSplitOptions.TrimEntries)
.Select( fl => (float)Convert.ToDouble(fl)).ToArray();
}

/// <summary>
/// Adds embedding to embeddings database.
/// </summary>
/// <param name="label">Label</param>
/// <param name="vector">Vector</param>
public void Add(string label, float[] vectors)
public void Add(string label, IEnumerable<string> embeddings)
{
var vectors = embeddings.Select( x => GetVectorFromString(x)).ToList();

if( VectorLookup.TryGetValue(label, out var existingList) )
{
existingList.Add( vectors);
existingList.AddRange( vectors );
return;
}
else
{
existingList = new List<float[]> { vectors };
existingList = new List<float[]>(vectors);
VectorLookup[label] = existingList;
}
}
Expand Down
17 changes: 5 additions & 12 deletions Damselfly.ML.FaceONNX/FaceONNXService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class FaceONNXService : IDisposable
private FaceDetector _faceDetector;
private FaceLandmarksExtractor _faceLandmarksExtractor;
private FaceEmbedder _faceEmbedder;
private Embeddings _embeddings;
private readonly Embeddings _embeddings = new();

public FaceONNXService(IServiceScopeFactory scopeFactory, ILogger<FaceONNXService> logger )
{
Expand All @@ -50,7 +50,6 @@ public void StartService()
_faceDetector = new FaceDetector();
_faceLandmarksExtractor = new FaceLandmarksExtractor();
_faceEmbedder = new FaceEmbedder();
_embeddings = new Embeddings();
}
catch ( Exception ex )
{
Expand All @@ -59,11 +58,6 @@ public void StartService()
Logging.LogError($"Inner exception: {ex.InnerException}");
}
}

private List<float[]> GetEmbeddingsFromString( IEnumerable<string> strings )
{
return strings.Select( x => x.Split(",").Select( fl => (float)Convert.ToDouble(fl)).ToArray() ).ToList();
}

/// <summary>
/// Takes a list of person GUIDs, each with a list of one or more sets of embeddings
Expand All @@ -73,10 +67,8 @@ private List<float[]> GetEmbeddingsFromString( IEnumerable<string> strings )
/// <param name="personIDAndEmbeddings"></param>
public void LoadFaceEmbeddings(Dictionary<string,IEnumerable<string>> personIDAndEmbeddings)
{
var convertedDict = personIDAndEmbeddings.ToDictionary( x => x.Key,
x => GetEmbeddingsFromString(x.Value));

_embeddings = new Embeddings(convertedDict);
foreach( var pair in personIDAndEmbeddings )
_embeddings.Add( pair.Key, pair.Value);
}

private class FaceONNXFace
Expand Down Expand Up @@ -170,8 +162,9 @@ public async Task<List<ImageDetectResult>> DetectFaces(Image<Rgb24> image)
{
// No match, so create a new person GUID
face.PersonGuid = Guid.NewGuid().ToString();
var vectorStr = string.Join(",", face.Embeddings);
// Add it to the embeddings DB
_embeddings.Add(face.PersonGuid, face.Embeddings);
_embeddings.Add(face.PersonGuid, new[] {vectorStr});
}
else
{
Expand Down
Loading

0 comments on commit 639a12b

Please sign in to comment.