Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- src/orchestrator.py +2 -1
- src/patchcore.py +7 -8
- src/retriever.py +6 -1
src/orchestrator.py
CHANGED
|
@@ -206,7 +206,8 @@ def run_inspection(pil_img: Image.Image,
|
|
| 206 |
|
| 207 |
# ββ STEP 7: Index 2 retrieval βββββββββββββββββββββββββββββ
|
| 208 |
similar_cases = retriever.retrieve_similar_defects(
|
| 209 |
-
clip_crop, k=5, exclude_hash=image_hash
|
|
|
|
| 210 |
)
|
| 211 |
|
| 212 |
# ββ STEP 8: Knowledge graph traversal ββββββββββββββββββββ
|
|
|
|
| 206 |
|
| 207 |
# ββ STEP 7: Index 2 retrieval βββββββββββββββββββββββββββββ
|
| 208 |
similar_cases = retriever.retrieve_similar_defects(
|
| 209 |
+
clip_crop, k=5, exclude_hash=image_hash,
|
| 210 |
+
category_filter=category
|
| 211 |
)
|
| 212 |
|
| 213 |
# ββ STEP 8: Knowledge graph traversal ββββββββββββββββββββ
|
src/patchcore.py
CHANGED
|
@@ -160,17 +160,16 @@ class PatchCoreExtractor:
|
|
| 160 |
|
| 161 |
def get_anomaly_centroid(self, heatmap: np.ndarray) -> tuple:
|
| 162 |
"""
|
| 163 |
-
Find
|
| 164 |
Used to locate defect crop for Index 2 retrieval.
|
| 165 |
-
Returns: (cx, cy) pixel coordinates
|
| 166 |
"""
|
| 167 |
-
|
| 168 |
-
mask = heatmap > threshold
|
| 169 |
-
if mask.sum() == 0:
|
| 170 |
return (112, 112) # centre fallback
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
|
|
|
| 174 |
|
| 175 |
def calibrate_score(self,
|
| 176 |
raw_score: float,
|
|
|
|
| 160 |
|
| 161 |
def get_anomaly_centroid(self, heatmap: np.ndarray) -> tuple:
|
| 162 |
"""
|
| 163 |
+
Find the peak (highest activation) location of the anomaly.
|
| 164 |
Used to locate defect crop for Index 2 retrieval.
|
| 165 |
+
Returns: (cx, cy) pixel coordinates of maximum activation
|
| 166 |
"""
|
| 167 |
+
if heatmap.size == 0:
|
|
|
|
|
|
|
| 168 |
return (112, 112) # centre fallback
|
| 169 |
+
|
| 170 |
+
# Use peak location, not mean of thresholded region
|
| 171 |
+
max_idx = np.unravel_index(np.argmax(heatmap), heatmap.shape)
|
| 172 |
+
return (int(max_idx[1]), int(max_idx[0])) # cx, cy
|
| 173 |
|
| 174 |
def calibrate_score(self,
|
| 175 |
raw_score: float,
|
src/retriever.py
CHANGED
|
@@ -99,11 +99,13 @@ class FAISSRetriever:
|
|
| 99 |
def retrieve_similar_defects(self,
|
| 100 |
clip_crop_embedding: np.ndarray,
|
| 101 |
k: int = 5,
|
| 102 |
-
exclude_hash: str = None
|
|
|
|
| 103 |
"""
|
| 104 |
Given a defect-crop CLIP embedding, return k most similar
|
| 105 |
historical defect cases.
|
| 106 |
exclude_hash: skip self-match (same image submitted again)
|
|
|
|
| 107 |
Returns: list of metadata dicts with similarity scores
|
| 108 |
"""
|
| 109 |
query = clip_crop_embedding.reshape(1, -1).astype(np.float32)
|
|
@@ -118,6 +120,9 @@ class FAISSRetriever:
|
|
| 118 |
continue
|
| 119 |
meta = self.index2_metadata[idx].copy()
|
| 120 |
meta["similarity_score"] = float(dist)
|
|
|
|
|
|
|
|
|
|
| 121 |
# Skip self-match
|
| 122 |
if exclude_hash and meta.get("image_hash") == exclude_hash:
|
| 123 |
continue
|
|
|
|
| 99 |
def retrieve_similar_defects(self,
|
| 100 |
clip_crop_embedding: np.ndarray,
|
| 101 |
k: int = 5,
|
| 102 |
+
exclude_hash: str = None,
|
| 103 |
+
category_filter: str = None) -> list:
|
| 104 |
"""
|
| 105 |
Given a defect-crop CLIP embedding, return k most similar
|
| 106 |
historical defect cases.
|
| 107 |
exclude_hash: skip self-match (same image submitted again)
|
| 108 |
+
category_filter: only return cases from specified category
|
| 109 |
Returns: list of metadata dicts with similarity scores
|
| 110 |
"""
|
| 111 |
query = clip_crop_embedding.reshape(1, -1).astype(np.float32)
|
|
|
|
| 120 |
continue
|
| 121 |
meta = self.index2_metadata[idx].copy()
|
| 122 |
meta["similarity_score"] = float(dist)
|
| 123 |
+
# Filter by category if provided
|
| 124 |
+
if category_filter and meta.get("category") != category_filter:
|
| 125 |
+
continue
|
| 126 |
# Skip self-match
|
| 127 |
if exclude_hash and meta.get("image_hash") == exclude_hash:
|
| 128 |
continue
|