kerojohan Claude Sonnet 4.6 commited on
Commit ·
05fdfa4
1
Parent(s): be814bf
Port v5 scoring fixes: border penalty, valid-region clip
Browse files- score_candidate: border contact penalty (×0.60 for 1 edge, ×0.35 for 2+)
prevents dark vegetation at image borders from outscoring contained cave voids
- process_image: hard-clip final mask to actual illumination columns after
refine_mask, removing IR vignette/penumbra reintroduced by GrabCut or smoothing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- detect_cave.py +30 -1
detect_cave.py
CHANGED
|
@@ -458,8 +458,25 @@ def score_candidate(mask, gray_f32, weight_map, left_col, right_col,
|
|
| 458 |
if valid_score < 0.5:
|
| 459 |
lateral_pen = 0.4
|
| 460 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 461 |
total = (additive * area_mult * solidity_mult
|
| 462 |
-
* texture_mult * vert_gate * lateral_pen)
|
| 463 |
|
| 464 |
return {
|
| 465 |
"total": round(float(total), 4),
|
|
@@ -480,6 +497,8 @@ def score_candidate(mask, gray_f32, weight_map, left_col, right_col,
|
|
| 480 |
"valid_score": round(float(valid_score), 3),
|
| 481 |
"mean_inside": round(float(mean_inside), 3),
|
| 482 |
"mean_outside": round(float(mean_outside), 3),
|
|
|
|
|
|
|
| 483 |
}
|
| 484 |
|
| 485 |
|
|
@@ -819,6 +838,7 @@ def process_image(input_path, output_dir):
|
|
| 819 |
f"depth={scores['depth']:.2f} "
|
| 820 |
f"area_m={scores['area_mult']:.2f} "
|
| 821 |
f"sol={scores['solidity']:.2f}(×{scores['sol_mult']:.2f}) "
|
|
|
|
| 822 |
f"in={scores['mean_inside']:.2f}±{scores['texture']:.2f} "
|
| 823 |
f"out={scores['mean_outside']:.2f}")
|
| 824 |
|
|
@@ -921,6 +941,15 @@ def process_image(input_path, output_dir):
|
|
| 921 |
best_mask = gc_result
|
| 922 |
|
| 923 |
refined = refine_mask(best_mask, gray_f32)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 924 |
draw_result(gray_u8, refined, scores,
|
| 925 |
out_r, out_m, out_dv,
|
| 926 |
wmap, pn,
|
|
|
|
| 458 |
if valid_score < 0.5:
|
| 459 |
lateral_pen = 0.4
|
| 460 |
|
| 461 |
+
# Border contact penalty: true cave entrances are contained within the frame.
|
| 462 |
+
# Dark patches that bleed to an image edge are likely cast shadows or vegetation
|
| 463 |
+
# extending beyond the visible area, not a cave void.
|
| 464 |
+
bp = 3 # border margin in pixels
|
| 465 |
+
border_touches = int(
|
| 466 |
+
(mask[:bp, :] > 0).any() # top
|
| 467 |
+
+ (mask[-bp:, :] > 0).any() # bottom
|
| 468 |
+
+ (mask[:, :bp] > 0).any() # left
|
| 469 |
+
+ (mask[:, -bp:] > 0).any() # right
|
| 470 |
+
)
|
| 471 |
+
if border_touches == 0:
|
| 472 |
+
border_mult = 1.0
|
| 473 |
+
elif border_touches == 1:
|
| 474 |
+
border_mult = 0.60
|
| 475 |
+
else:
|
| 476 |
+
border_mult = 0.35
|
| 477 |
+
|
| 478 |
total = (additive * area_mult * solidity_mult
|
| 479 |
+
* texture_mult * vert_gate * lateral_pen * border_mult)
|
| 480 |
|
| 481 |
return {
|
| 482 |
"total": round(float(total), 4),
|
|
|
|
| 497 |
"valid_score": round(float(valid_score), 3),
|
| 498 |
"mean_inside": round(float(mean_inside), 3),
|
| 499 |
"mean_outside": round(float(mean_outside), 3),
|
| 500 |
+
"border_touches": border_touches,
|
| 501 |
+
"border_mult": round(float(border_mult), 3),
|
| 502 |
}
|
| 503 |
|
| 504 |
|
|
|
|
| 838 |
f"depth={scores['depth']:.2f} "
|
| 839 |
f"area_m={scores['area_mult']:.2f} "
|
| 840 |
f"sol={scores['solidity']:.2f}(×{scores['sol_mult']:.2f}) "
|
| 841 |
+
f"border={scores['border_touches']}(×{scores['border_mult']:.2f}) "
|
| 842 |
f"in={scores['mean_inside']:.2f}±{scores['texture']:.2f} "
|
| 843 |
f"out={scores['mean_outside']:.2f}")
|
| 844 |
|
|
|
|
| 941 |
best_mask = gc_result
|
| 942 |
|
| 943 |
refined = refine_mask(best_mask, gray_f32)
|
| 944 |
+
|
| 945 |
+
# Hard-clip final mask to the actual illumination columns (not the capped
|
| 946 |
+
# lc/rc) to exclude IR vignette/penumbra that GrabCut or contour smoothing
|
| 947 |
+
# may have reintroduced after the expansion clip.
|
| 948 |
+
if actual_lc > int(w * 0.05):
|
| 949 |
+
refined[:, :actual_lc] = 0
|
| 950 |
+
if actual_rc < int(w * 0.95):
|
| 951 |
+
refined[:, actual_rc + 1:] = 0
|
| 952 |
+
|
| 953 |
draw_result(gray_u8, refined, scores,
|
| 954 |
out_r, out_m, out_dv,
|
| 955 |
wmap, pn,
|