-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_clip_search.py
More file actions
172 lines (140 loc) Β· 5.77 KB
/
test_clip_search.py
File metadata and controls
172 lines (140 loc) Β· 5.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/usr/bin/env python3
"""
Test script for CLIP-only search functionality
"""
import sys
import os
sys.path.insert(0, os.path.abspath('.'))
import json
import numpy as np
from pathlib import Path
from app.embeddings import load_models, compute_clip_text_embedding
from PIL import Image
import time
def test_clip_search():
print("π Testing CLIP-Only Search Functionality")
print("=" * 50)
# 1. Check if demo images exist
demo_dir = Path("demo_images")
if not demo_dir.exists():
print("β No demo_images directory found!")
return False
demo_images = list(demo_dir.glob("*.png"))
if not demo_images:
print("β No demo images found!")
return False
print(f"π Found {len(demo_images)} demo images")
# 2. Load CLIP models
print("π€ Loading CLIP models...")
try:
vit_model, clip_model, preprocess_vit, preprocess_clip, vit_dim, clip_dim = load_models()
if clip_model is None:
print("β CLIP model not available!")
return False
print("β
CLIP models loaded successfully")
except Exception as e:
print(f"β Failed to load models: {e}")
return False
# 3. Create a simple test case with CLIP embeddings
print("\nπ Creating test case with CLIP embeddings...")
test_case_dir = Path("output_index/test_clip_case")
test_case_dir.mkdir(parents=True, exist_ok=True)
# Process a few demo images to create embeddings
test_images = demo_images[:10] # Use first 10 images
manifest = []
for img_path in test_images:
try:
# Load and preprocess image
img = Image.open(img_path).convert("RGB")
img_tensor = preprocess_clip(img).unsqueeze(0)
# Compute CLIP embedding
with torch.no_grad():
clip_emb = clip_model.encode_image(img_tensor).detach().cpu().numpy()[0]
# Normalize
clip_emb = clip_emb / (np.linalg.norm(clip_emb) + 1e-10)
# Add to manifest
manifest.append({
"path": str(img_path),
"hashes": {},
"clip_embedding": clip_emb.tolist()
})
except Exception as e:
print(f"β οΈ Failed to process {img_path.name}: {e}")
continue
if not manifest:
print("β No images could be processed!")
return False
print(f"β
Created manifest with {len(manifest)} images")
# 4. Save manifest
manifest_path = test_case_dir / "manifest.json"
with open(manifest_path, 'w') as f:
json.dump(manifest, f, indent=2)
print(f"πΎ Saved manifest to {manifest_path}")
# 5. Test text-to-image search
print("\nπ Test 1: Text-to-Image Search")
try:
# Test query
query_text = "synthetic image"
query_emb = compute_clip_text_embedding(query_text, clip_model)
# Search through manifest
similarities = []
for item in manifest:
if 'clip_embedding' in item:
img_emb = np.array(item['clip_embedding'])
# Compute cosine similarity
similarity = np.dot(query_emb, img_emb) / (np.linalg.norm(query_emb) * np.linalg.norm(img_emb))
similarities.append((item['path'], similarity))
# Sort by similarity
similarities.sort(key=lambda x: x[1], reverse=True)
print(f"β
Text search successful!")
print(f" Query: '{query_text}'")
print(f" Top 3 results:")
for i, (path, sim) in enumerate(similarities[:3]):
filename = Path(path).name
print(f" {i+1}. {filename} (similarity: {sim:.4f})")
except Exception as e:
print(f"β Text search failed: {e}")
return False
# 6. Test image-to-image search
print("\nπΌοΈ Test 2: Image-to-Image Search")
try:
# Use first image as query
query_img_path = test_images[0]
query_img = Image.open(query_img_path).convert("RGB")
query_tensor = preprocess_clip(query_img).unsqueeze(0)
with torch.no_grad():
query_emb = clip_model.encode_image(query_tensor).detach().cpu().numpy()[0]
# Normalize
query_emb = query_emb / (np.linalg.norm(query_emb) + 1e-10)
# Search through manifest
similarities = []
for item in manifest:
if 'clip_embedding' in item:
img_emb = np.array(item['clip_embedding'])
# Compute cosine similarity
similarity = np.dot(query_emb, img_emb) / (np.linalg.norm(query_emb) * np.linalg.norm(img_emb))
similarities.append((item['path'], similarity))
# Sort by similarity
similarities.sort(key=lambda x: x[1], reverse=True)
print(f"β
Image search successful!")
print(f" Query image: {query_img_path.name}")
print(f" Top 3 results:")
for i, (path, sim) in enumerate(similarities[:3]):
filename = Path(path).name
print(f" {i+1}. {filename} (similarity: {sim:.4f})")
except Exception as e:
print(f"β Image search failed: {e}")
return False
print("\n" + "=" * 50)
print("β
CLIP-only search is working correctly!")
print(f"π Test case created at: {test_case_dir}")
print("π You can now load this case in the Streamlit app")
print("π― The search should return results instead of 0")
return True
if __name__ == "__main__":
# Add torch import
import torch
success = test_clip_search()
if not success:
print("\nβ CLIP search test failed - check logs above")
sys.exit(1)