James Ketrenos 1767e807ea Its working pretty well now
Signed-off-by: James Ketrenos <james_git@ketrenos.com>
2023-01-10 16:29:11 -08:00

74 lines
2.2 KiB
Python

from ketrface.util import *
MIN_PTS = 5
MAX_DISTANCE = 0.25
Undefined = 0
Edge = -1
Noise = -2
# Union of two lists of dicts
def Union(A, B):
C = []
for key in A + B:
if key not in C:
C.append(key)
return C
# https://en.wikipedia.org/wiki/DBSCAN
def DBSCAN(points, eps = MAX_DISTANCE, minPts = MIN_PTS, verbose = True):
clusters = [] # Cluster list
perc = -1
total = len(points)
for i, P in enumerate(points):
if verbose == True:
new_perc = int(100 * (i+1) / total)
if new_perc != perc:
perc = new_perc
print(f'Clustering points {perc}% ({i}/{total} processed) complete with {len(clusters)} identities.')
if P['cluster'] != Undefined: # Previously processed in inner loop
continue
N = RangeQuery(points, P, eps) # Find neighbors
if len(N) < minPts: # Density check
P['cluster'] = Noise # Label as Noise
continue
C = { # Define new cluster
'id': len(clusters),
'faces': [ P ],
'cluster': Undefined
}
clusters.append(C)
P['cluster'] = C # Label initial point
S = N # Neighbors to expand (exclude P)
S.remove(P)
for Q in S: # Process every seed point
if Q['cluster'] == Noise: # Change Noise to border point
Q['cluster'] = C
C['faces'].append(Q)
if Q['cluster'] != Undefined: # Previously processed (border point)
continue
Q['cluster'] = C # Label neighbor
C['faces'].append(Q)
N = RangeQuery(points, Q, eps) # Find neighbors
if len(N) >= minPts: # Density check (if Q is a core point)
S = Union(S, N) # Add new neighbors to seed set
return clusters
def RangeQuery(points, Q, eps):
neighbors = []
for P in points: # Scan all points in the database
if P in neighbors:
continue
distance = findCosineDistance( # Compute distance and check epsilon
Q['descriptors'],
P['descriptors'])
if distance <= eps:
neighbors += [ P ] # Add to result
return neighbors