feat(trip-cluster): coverage detection — completeness flags + outliers
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
from photoflow.core.models import ClusterMember
|
||||
from app.clustering import _epoch, _median
|
||||
|
||||
|
||||
def coverage_members(candidate, assets_by_id, *, outlier_factor: float = 8.0) -> list:
|
||||
member_ids = [i for i in candidate.member_ids if i in assets_by_id]
|
||||
members = sorted((assets_by_id[i] for i in member_ids), key=lambda a: a.taken_at)
|
||||
epochs = [_epoch(a.taken_at) for a in members]
|
||||
gaps = [b - a for a, b in zip(epochs, epochs[1:])]
|
||||
base = _median(gaps) if gaps else 0.0
|
||||
|
||||
out = []
|
||||
for idx, a in enumerate(members):
|
||||
is_outlier = False
|
||||
if candidate.seed_tag and base > 0:
|
||||
left = epochs[idx] - epochs[idx - 1] if idx > 0 else 0
|
||||
right = epochs[idx + 1] - epochs[idx] if idx < len(members) - 1 else 0
|
||||
nearest = min([g for g in (left, right) if g > 0], default=0)
|
||||
if nearest > outlier_factor * base:
|
||||
is_outlier = True
|
||||
out.append(ClusterMember(
|
||||
cluster_id=0, immich_id=a.immich_id,
|
||||
member_confidence=candidate.confidence, is_outlier=is_outlier,
|
||||
included=True, flagged_coverage=False))
|
||||
|
||||
if candidate.seed_tag and candidate.start_at and candidate.end_at:
|
||||
mset = set(member_ids)
|
||||
for a in sorted(assets_by_id.values(), key=lambda x: x.taken_at):
|
||||
if a.immich_id in mset:
|
||||
continue
|
||||
if candidate.start_at <= a.taken_at <= candidate.end_at:
|
||||
out.append(ClusterMember(
|
||||
cluster_id=0, immich_id=a.immich_id, member_confidence=0.0,
|
||||
is_outlier=False, included=False, flagged_coverage=True))
|
||||
return out
|
||||
Reference in New Issue
Block a user