V1 로직(CLIP 활용) - 100-hours-a-week/5-yeosa-wiki GitHub Wiki

1. 로직 요약

a. 입력

  • req.images: 이미지 파일명 리스트
  • 사전 생성된 CLIP 임베딩을 캐시에서 불러옴 (get_cached_embeddings_parallel 사용)

b. 임베딩 처리

image_features = torch.stack(image_features)
  • 모든 이미지의 [N, D] 차원 CLIP 임베딩을 하나의 텐서로 결합

c. 유사도 계산 → 거리 행렬 변환

normed = image_features / image_features.norm(dim=1, keepdim=True)
similarity_matrix = normed @ normed.T
distance_matrix = 1 - similarity_matrix
  • Cosine similarity 계산
  • 유사도를 1에서 빼서 Cosine distance matrix 생성

d. DBSCAN 클러스터링 (유사한 이미지 묶기)

DBSCAN(eps=0.1, min_samples=2, metric="precomputed")
  • eps: 두 이미지가 중복으로 간주되기 위한 최대 거리 (기본값: 0.1)
  • min_samples: 동일 그룹으로 판단할 최소 이미지 수 (기본값: 2)
  • 거리 행렬 기반 클러스터링 수행 → label 할당 (-1은 noise)

e. 중복 그룹 구성

groups[label].append(image_names[idx])
  • 같은 클러스터(label)를 가진 이미지들을 하나의 그룹으로 묶음
  • noise(label == -1)는 제외됨

f. 최종 결과

{
  "message": "success",
  "data": [
    ["img1.jpg", "img2.jpg"],
    ["img5.jpg", "img8.jpg", "img9.jpg"]
  ]
}
  • 각 중복 그룹을 하나의 리스트로 반환
  • 전체 결과는 List[List[str]] 형식

2. 특징 및 장점

항목 설명
모델 OpenAI CLIP 기반 임베딩 사용
비교 방식 Cosine similarity → distance 변환 후 DBSCAN 적용
중복 판단 기준 거리 기반 클러스터링 (eps, min_samples 조정 가능)
성능 모든 쌍 간 유사도를 계산하지만, N이 적당하면 실시간 응답 가능