crabbly commited on
Commit
e1e390a
·
verified ·
1 Parent(s): 4106a5d

Delete cv_helpers.py

Browse files
Files changed (1) hide show
  1. cv_helpers.py +0 -78
cv_helpers.py DELETED
@@ -1,78 +0,0 @@
1
- """Shared CV helpers: mask visualization and stem-tip heuristic."""
2
-
3
- import numpy as np
4
-
5
-
6
- def blend_mask_overlays(bgr, rind_mask, flesh_mask, alpha=0.42):
7
- """
8
- Semi-transparent rind (green tint) and flesh (orange tint) on top of the BGR image.
9
- Flesh is drawn after rind so overlap reads clearly.
10
- """
11
- out = bgr.astype(np.float32)
12
- rind_m = (rind_mask > 0).astype(np.float32)
13
- flesh_m = (flesh_mask > 0).astype(np.float32)
14
- rind_color = np.array([0.0, 170.0, 0.0], dtype=np.float32)
15
- flesh_color = np.array([60.0, 120.0, 255.0], dtype=np.float32)
16
- for c in range(3):
17
- ch = out[..., c]
18
- ch[:] = ch * (1.0 - alpha * rind_m) + rind_color[c] * (alpha * rind_m)
19
- for c in range(3):
20
- ch = out[..., c]
21
- ch[:] = ch * (1.0 - alpha * flesh_m) + flesh_color[c] * (alpha * flesh_m)
22
- return np.clip(out, 0, 255).astype(np.uint8)
23
-
24
-
25
- def stem_tip_tangent_deg(contour, centroid_xy):
26
- """
27
- Heuristic "stem / neck" pole on the rind contour: take PCA major-axis extremes,
28
- then pick the end with sharper local turning (inward-curving neck). Tie-break:
29
- smaller image y (overhead shots often have stem toward top of frame).
30
-
31
- Returns (tip_x, tip_y, tangent_deg) where tangent_deg is atan2(dy, dx) in degrees,
32
- or None if not enough contour points.
33
- """
34
- cnt = contour.reshape(-1, 2).astype(np.float64)
35
- n = len(cnt)
36
- if n < 9:
37
- return None
38
-
39
- cx, cy = float(centroid_xy[0]), float(centroid_xy[1])
40
- X = cnt - np.array([cx, cy])
41
- cov = np.cov(X.T)
42
- eigvals, eigvecs = np.linalg.eigh(cov)
43
- u = eigvecs[:, int(np.argmax(eigvals))]
44
- un = np.linalg.norm(u)
45
- if un < 1e-9:
46
- return None
47
- u /= un
48
-
49
- s = X @ u
50
- idx_a = int(np.argmax(s))
51
- idx_b = int(np.argmin(s))
52
- span = max(3, min(25, n // 30))
53
-
54
- def curvature_score(i):
55
- p = cnt[i % n]
56
- prev = cnt[(i - span) % n]
57
- nxt = cnt[(i + span) % n]
58
- v1 = p - prev
59
- v2 = nxt - p
60
- nv1 = np.linalg.norm(v1)
61
- nv2 = np.linalg.norm(v2)
62
- if nv1 < 1e-6 or nv2 < 1e-6:
63
- return 0.0
64
- v1u = v1 / nv1
65
- v2u = v2 / nv2
66
- return abs(v1u[0] * v2u[1] - v1u[1] * v2u[0])
67
-
68
- ka, kb = curvature_score(idx_a), curvature_score(idx_b)
69
- if abs(ka - kb) < 0.05:
70
- stem_idx = idx_a if cnt[idx_a, 1] < cnt[idx_b, 1] else idx_b
71
- else:
72
- stem_idx = idx_a if ka > kb else idx_b
73
-
74
- span_t = max(2, span // 2)
75
- d = cnt[(stem_idx + span_t) % n] - cnt[(stem_idx - span_t) % n]
76
- tang_deg = float(np.degrees(np.arctan2(d[1], d[0])))
77
- tip = cnt[stem_idx]
78
- return float(tip[0]), float(tip[1]), tang_deg