Mirko Trasciatti commited on
Commit
dfe5b17
·
1 Parent(s): 6ae1c1a

Broaden solid core in ball falloff

Browse files
Files changed (1) hide show
  1. app.py +8 -6
app.py CHANGED
@@ -930,7 +930,7 @@ def compose_frame(state: AppState, frame_idx: int, remove_bg: bool = False) -> I
930
  if ball_mask is not None:
931
  combined_mask = np.maximum(
932
  combined_mask,
933
- _apply_radial_falloff(np.clip(ball_mask.astype(np.float32), 0.0, 1.0)),
934
  )
935
  result_np = _apply_cutout_fx(state, frame_np, combined_mask)
936
  out_img = Image.fromarray(result_np)
@@ -944,7 +944,7 @@ def compose_frame(state: AppState, frame_idx: int, remove_bg: bool = False) -> I
944
  if BALL_OBJECT_ID in masks:
945
  ball_mask = masks[BALL_OBJECT_ID]
946
  if ball_mask is not None:
947
- ball_alpha = _apply_radial_falloff(ball_mask)
948
  if ball_alpha is not None and ball_alpha.max() > FX_EPS:
949
  base_np = np.array(out_img).astype(np.float32) / 255.0
950
  color = np.array(state.color_by_obj.get(BALL_OBJECT_ID, (255, 255, 0)), dtype=np.float32) / 255.0
@@ -1137,7 +1137,7 @@ def _build_ball_trail_mask(state: AppState, frame_idx: int) -> np.ndarray | None
1137
  if mask_np.ndim == 3:
1138
  mask_np = mask_np.squeeze()
1139
  mask_np = np.clip(mask_np, 0.0, 1.0)
1140
- mask_np = _apply_radial_falloff(mask_np)
1141
  if trail_mask is None:
1142
  trail_mask = np.zeros_like(mask_np, dtype=np.float32)
1143
  if trail_mask.shape != mask_np.shape:
@@ -1169,7 +1169,7 @@ def _compute_mask_centroid(mask: np.ndarray) -> tuple[int, int] | None:
1169
  return cx, cy
1170
 
1171
 
1172
- def _apply_radial_falloff(mask: np.ndarray, strength: float = 1.5) -> np.ndarray:
1173
  if mask is None:
1174
  return None
1175
  mask_np = np.clip(mask.astype(np.float32), 0.0, 1.0)
@@ -1189,8 +1189,10 @@ def _apply_radial_falloff(mask: np.ndarray, strength: float = 1.5) -> np.ndarray
1189
  max_dist = dist[mask_np > FX_EPS].max() if np.any(mask_np > FX_EPS) else 0.0
1190
  if max_dist <= FX_EPS:
1191
  return mask_np
1192
- falloff = 1.0 - np.clip(dist / max_dist, 0.0, 1.0)
1193
- falloff = np.power(falloff, strength)
 
 
1194
  return np.clip(mask_np * falloff, 0.0, 1.0)
1195
 
1196
 
 
930
  if ball_mask is not None:
931
  combined_mask = np.maximum(
932
  combined_mask,
933
+ _apply_radial_falloff(np.clip(ball_mask.astype(np.float32), 0.0, 1.0), strength=1.0, solid_ratio=0.8),
934
  )
935
  result_np = _apply_cutout_fx(state, frame_np, combined_mask)
936
  out_img = Image.fromarray(result_np)
 
944
  if BALL_OBJECT_ID in masks:
945
  ball_mask = masks[BALL_OBJECT_ID]
946
  if ball_mask is not None:
947
+ ball_alpha = _apply_radial_falloff(ball_mask, strength=1.0, solid_ratio=0.8)
948
  if ball_alpha is not None and ball_alpha.max() > FX_EPS:
949
  base_np = np.array(out_img).astype(np.float32) / 255.0
950
  color = np.array(state.color_by_obj.get(BALL_OBJECT_ID, (255, 255, 0)), dtype=np.float32) / 255.0
 
1137
  if mask_np.ndim == 3:
1138
  mask_np = mask_np.squeeze()
1139
  mask_np = np.clip(mask_np, 0.0, 1.0)
1140
+ mask_np = _apply_radial_falloff(mask_np, strength=1.0, solid_ratio=0.8)
1141
  if trail_mask is None:
1142
  trail_mask = np.zeros_like(mask_np, dtype=np.float32)
1143
  if trail_mask.shape != mask_np.shape:
 
1169
  return cx, cy
1170
 
1171
 
1172
+ def _apply_radial_falloff(mask: np.ndarray, strength: float = 1.0, solid_ratio: float = 0.8) -> np.ndarray:
1173
  if mask is None:
1174
  return None
1175
  mask_np = np.clip(mask.astype(np.float32), 0.0, 1.0)
 
1189
  max_dist = dist[mask_np > FX_EPS].max() if np.any(mask_np > FX_EPS) else 0.0
1190
  if max_dist <= FX_EPS:
1191
  return mask_np
1192
+ if solid_ratio >= 1.0:
1193
+ return mask_np
1194
+ clipped_dist = np.clip((dist / max_dist - solid_ratio) / (1.0 - solid_ratio), 0.0, 1.0)
1195
+ falloff = 1.0 - np.power(clipped_dist, strength)
1196
  return np.clip(mask_np * falloff, 0.0, 1.0)
1197
 
1198