eho69 commited on
Commit
e8ca12e
Β·
verified Β·
1 Parent(s): 7aadeb6
Files changed (1) hide show
  1. app.py +5 -43
app.py CHANGED
@@ -1,16 +1,3 @@
1
- """
2
- Engine Part CV System β€” v5
3
- ══════════════════════════
4
- Key upgrades over v4:
5
- 1. PCA projection β€” compresses 1536-D CNN space to N most discriminative
6
- dimensions, so cosine gaps widen from 0.007 β†’ 0.1+
7
- 2. Anomaly scoring β€” primary signal is "distance from Perfect centroid"
8
- rather than multi-class cosine race
9
- 3. Per-dim variance weighting (whitening) β€” equalises feature scales
10
- 4. Mahalanobis-style distance β€” accounts for within-class spread per axis
11
- 5. Gradio 6.0 fix β€” theme/css moved to launch()
12
- """
13
-
14
  import gradio as gr
15
  import cv2
16
  import numpy as np
@@ -35,8 +22,8 @@ CLUSTER_VERSION = "v5"
35
  TEXTURE_WEIGHT = 1.6
36
  MIN_SAMPLES_WARN = 5
37
  MIN_MATCH_SAMPLES= 3
38
- PCA_COMPONENTS = 64 # reduce 1536-D β†’ 64-D (tune: 32–128)
39
- ANOMALY_THRESHOLD= 2.5 # mahalanobis z-score above this β†’ FAIL
40
  PERFECT_CLASS = "Perfect"
41
 
42
 
@@ -192,20 +179,7 @@ class FeatureExtractor:
192
  # ───────────────────────────────────────────────────────────────────────────────
193
 
194
  class PCAProjector:
195
- """
196
- Fits a PCA on ALL stored feature vectors across ALL classes, then
197
- projects every query into the lower-dimensional discriminative subspace.
198
-
199
- Why this fixes the 0.9944 / 0.9865 cosine collapse
200
- ───────────────────────────────────────────────────
201
- In 1536-D space virtually every unit vector has cosine similarity β‰₯ 0.98
202
- to every other β€” this is the "curse of dimensionality". PCA finds the
203
- axes of maximum variance in the training data. These axes correspond
204
- to the visual differences BETWEEN classes (colour, texture, defect edges).
205
- After projecting to 64-D the cosine gap between Perfect and Defected
206
- typically widens from 0.007 β†’ 0.10–0.30, making classification reliable.
207
- """
208
-
209
  def __init__(self, n_components: int = PCA_COMPONENTS):
210
  self.n_components = n_components
211
  self.pca = None
@@ -393,11 +367,7 @@ class EnginePartDetector:
393
  return float(np.dot(a,b)/(na*nb)) if na>1e-8 and nb>1e-8 else 0.
394
 
395
  def _mahalanobis(self, query: np.ndarray, name: str) -> float:
396
- """
397
- Diagonal Mahalanobis distance from query to class centroid.
398
- Accounts for per-axis spread β€” features with high variance within
399
- a class contribute less to the distance score.
400
- """
401
  centroid = self.centroids[name]
402
  cov_inv = self.class_cov_inv.get(name)
403
  diff = query - centroid
@@ -407,11 +377,7 @@ class EnginePartDetector:
407
  return float(np.linalg.norm(diff))
408
 
409
  def _anomaly_score(self, query_proj: np.ndarray) -> dict:
410
- """
411
- Primary decision signal: z-score distance from the Perfect centroid.
412
- Lower = more like a Perfect part.
413
- Returns dict with anomaly_z, perfect_dist, verdict.
414
- """
415
  if PERFECT_CLASS not in self.centroids:
416
  return {"anomaly_z": None, "verdict": "no_perfect_class"}
417
 
@@ -815,10 +781,6 @@ with gr.Blocks(title="Engine Part CV System v5") as demo:
815
  rst_btn.click(reset_all_ui, [], [rst_st, lib_txt, lib_roi])
816
  demo.load(update_library_preview, [], [lib_txt, lib_roi])
817
 
818
- gr.Markdown("""<div class="footer">
819
- Engine Part CV System v5 β€’ PCA + Anomaly Scoring + Centroid Cosine
820
- </div>""")
821
-
822
 
823
  if __name__ == "__main__":
824
  demo.launch(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
  import cv2
3
  import numpy as np
 
22
  TEXTURE_WEIGHT = 1.6
23
  MIN_SAMPLES_WARN = 5
24
  MIN_MATCH_SAMPLES= 3
25
+ PCA_COMPONENTS = 64
26
+ ANOMALY_THRESHOLD= 2.5
27
  PERFECT_CLASS = "Perfect"
28
 
29
 
 
179
  # ───────────────────────────────────────────────────────────────────────────────
180
 
181
  class PCAProjector:
182
+
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  def __init__(self, n_components: int = PCA_COMPONENTS):
184
  self.n_components = n_components
185
  self.pca = None
 
367
  return float(np.dot(a,b)/(na*nb)) if na>1e-8 and nb>1e-8 else 0.
368
 
369
  def _mahalanobis(self, query: np.ndarray, name: str) -> float:
370
+
 
 
 
 
371
  centroid = self.centroids[name]
372
  cov_inv = self.class_cov_inv.get(name)
373
  diff = query - centroid
 
377
  return float(np.linalg.norm(diff))
378
 
379
  def _anomaly_score(self, query_proj: np.ndarray) -> dict:
380
+
 
 
 
 
381
  if PERFECT_CLASS not in self.centroids:
382
  return {"anomaly_z": None, "verdict": "no_perfect_class"}
383
 
 
781
  rst_btn.click(reset_all_ui, [], [rst_st, lib_txt, lib_roi])
782
  demo.load(update_library_preview, [], [lib_txt, lib_roi])
783
 
 
 
 
 
784
 
785
  if __name__ == "__main__":
786
  demo.launch(