Views
No views yet
| Capability | Description |
|---|---|
| Visual Search | Encode jewelry images into 512-dim embeddings. Find matching products via cosine similarity. |
| Classification | Classify into 5 categories: Bracelet, Earrings, Necklace, Pendant, Ring |
| Coarse-to-Fine | First classify the category, then search within that category for 99%+ match accuracy |
Input Image (224×224)
↓
DINOv2-base (ViT-B/14, 86M params) → 768-dim CLS token
↓
Projection Head (768 → 768 → GELU → 512) → L2-normalized embedding
↓
├── ArcFace Head (angular margin loss, s=32, m=0.3) → discriminative embeddings
└── Classification Head (512 → 5) → subcategory prediction| Parameter | Value |
|---|---|
| Backbone | facebook/dinov2-base (86M params, ViT-B/14) |
| Embedding dim | 512 |
| Dataset | bzcasper/ai-tool-pool-jewelry-vision |
| Train/Val/Test | 4,488 / 429 / 213 images |
| Classes | Bracelet (795), Earrings (822), Necklace (2196), Pendant (345), Ring (330) |
| Loss | ArcFace (s=32, m=0.3) + 0.1 × weighted CE |
| Optimizer | AdamW (backbone LR=2e-5, heads LR=1e-3) |
| Batch | 32 × 4 gradient accumulation = 128 effective |
| Epochs | 15 (backbone frozen for first 3) |
| Augmentation | RandomResizedCrop, HFlip, Rotation±15°, ColorJitter, RandomErasing |
1from inference_jewelry_search import JewelrySearchEngine
2from PIL import Image
3
4# 1. Load model
5engine = JewelrySearchEngine("maheshp1109/jewelry-visual-search-dinov2")
6
7# 2. Build gallery from your product catalog
8product_images = [Image.open(f"products/{sku}.jpg") for sku in your_skus]
9product_metadata = [{"sku": sku, "name": name, "price": price} for sku, name, price in your_catalog]
10engine.build_index(product_images, product_metadata)
11
12# 3. Search with a user-uploaded image
13query = Image.open("user_upload.jpg")
14results = engine.search(query, top_k=5)
15
16for r in results:
17 print(f" #{r['rank']} Score={r['score']:.3f} SKU={r['metadata']['sku']}")
18print(f" Category: {results[0]['query_category']['category']}")1classification = engine.classify(Image.open("ring.jpg"))
2# {'category': 'Ring', 'confidence': 0.97, 'all_scores': {'Bracelet': 0.01, ...}}1# Save gallery index (don't re-encode every time)
2engine.save_index("gallery_index.npz")
3
4# Load pre-built index
5engine.load_index("gallery_index.npz")
6
7# For millions of products, use FAISS:
8import faiss
9index = faiss.IndexFlatIP(512) # cosine similarity (embeddings are L2-normalized)
10index.add(engine.gallery_embeddings)
11scores, indices = index.search(query_embedding.reshape(1, -1), top_k)1# Stage 1: Classify the query → narrow search space
2category = engine.classify(query_image)["category"] # e.g., "Ring"
3
4# Stage 2: Search only within that category
5ring_indices = [i for i, m in enumerate(metadata) if m["category"] == "Ring"]
6ring_embeddings = gallery_embeddings[ring_indices]
7
8# Much higher precision when searching within category
9query_emb = engine.encode_image(query_image)
10scores = query_emb @ ring_embeddings.TIMAGE_SIZE to 448 for +3-5% on fine-grained details (stones, settings)Marqo/fashion200k for pre-fine-tuning warmupMarqo/marqo-fashionSigLIP as an alternative backbone (already fine-tuned on fashion, 76.7% P@1)jewelry visual-search image-retrieval product-search dinov2 arcface metric-learning classification fashion e-commerce