|
|
|
|
namespace ZeroLevel.NN.Clusterization
|
|
|
|
|
{
|
|
|
|
|
public class FeatureClusterBulder
|
|
|
|
|
{
|
|
|
|
|
public FeatureClusterCollection<T> Build<T>(IEnumerable<T> faces, Func<T, float[]> vectorExtractor, Func<float[], float[], double> similarityFunction, float threshold, float clusterThreshold = 0.5f)
|
|
|
|
|
{
|
|
|
|
|
var collection = new FeatureClusterCollection<T>();
|
|
|
|
|
foreach (var face in faces)
|
|
|
|
|
{
|
|
|
|
|
bool isAdded = false;
|
|
|
|
|
foreach (var cluster in collection.Clusters)
|
|
|
|
|
{
|
|
|
|
|
if (cluster.Value.IsNeighbor(face, similarityFunction, threshold, clusterThreshold))
|
|
|
|
|
{
|
|
|
|
|
cluster.Value.Append(face);
|
|
|
|
|
isAdded = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (false == isAdded)
|
|
|
|
|
{
|
|
|
|
|
var cluster = new FeatureCluster<T>(vectorExtractor);
|
|
|
|
|
cluster.Append(face);
|
|
|
|
|
collection.Add(cluster);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
MergeClusters(collection, similarityFunction, threshold, clusterThreshold);
|
|
|
|
|
return collection;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void MergeClusters<T>(FeatureClusterCollection<T> collection, Func<float[], float[], double> similarityFunction, float threshold, float clusterThreshold = 0.5f)
|
|
|
|
|
{
|
|
|
|
|
int lastCount = collection.Clusters.Count;
|
|
|
|
|
var removed = new Queue<int>();
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
var ids = collection.Clusters.Keys.ToList();
|
|
|
|
|
for (var i = 0; i < ids.Count - 1; i++)
|
|
|
|
|
{
|
|
|
|
|
for (var j = i + 1; j < ids.Count; j++)
|
|
|
|
|
{
|
|
|
|
|
var c1 = collection.Clusters[ids[i]];
|
|
|
|
|
var c2 = collection.Clusters[ids[j]];
|
|
|
|
|
if (c1.IsNeighborCluster(c2, similarityFunction, threshold, clusterThreshold))
|
|
|
|
|
{
|
|
|
|
|
c1.Merge(c2);
|
|
|
|
|
removed.Enqueue(ids[j]);
|
|
|
|
|
ids.RemoveAt(j);
|
|
|
|
|
j--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while (removed.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
collection.Clusters.Remove(removed.Dequeue());
|
|
|
|
|
}
|
|
|
|
|
if (lastCount == collection.Clusters.Count)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
lastCount = collection.Clusters.Count;
|
|
|
|
|
} while (true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|