Fix NMS cross-orientation suppression — correctly detects R9
Browse filesA horizontal-orientation candidate (angle~0°, 88x47px, ncc=0.501) was
suppressing the correct vertical R9 detection (angle=90°, 35x66px,
ncc=0.497) during NMS because their IoU (0.323) exceeded the 0.30
threshold. These represent fundamentally different shape hypotheses and
should not compete: horizontal matches should never eliminate vertical ones.
Fix: NMS now skips suppression when the two candidates belong to different
orientation groups (horizontal vs vertical). The structural filters
(chamfer, wire_leads, etc.) already correctly eliminate wrong-orientation
false positives from the surviving candidate pool.
Result: Drawing 1 now detects all 10 resistors (9 circuit + 1 legend),
including R9 at (969,642,35x66) with chamfer=2.43 and conf=0.500.
All 10 unit tests pass.
- src/ncc_matcher.py +8 -0
|
@@ -134,6 +134,14 @@ class NCCMatcher:
|
|
| 134 |
for j in range(i + 1, len(candidates)):
|
| 135 |
if suppressed[j]:
|
| 136 |
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
if self._iou(cand, candidates[j]) > self.nms_iou_threshold:
|
| 138 |
suppressed[j] = True
|
| 139 |
|
|
|
|
| 134 |
for j in range(i + 1, len(candidates)):
|
| 135 |
if suppressed[j]:
|
| 136 |
continue
|
| 137 |
+
# Never suppress across orientation groups: a horizontal match
|
| 138 |
+
# (angle near 0°) should not eliminate a vertical match (angle
|
| 139 |
+
# near 90°) at the same location — they represent different
|
| 140 |
+
# shape hypotheses and the structural filters decide later.
|
| 141 |
+
a_vert = 70 <= abs(cand.get("angle", 0)) <= 110
|
| 142 |
+
b_vert = 70 <= abs(candidates[j].get("angle", 0)) <= 110
|
| 143 |
+
if a_vert != b_vert:
|
| 144 |
+
continue
|
| 145 |
if self._iou(cand, candidates[j]) > self.nms_iou_threshold:
|
| 146 |
suppressed[j] = True
|
| 147 |
|