pred_depth shape: [B, V, 1, H, W] target_depth shape: [B, V, 1, H, W] impl according to MiDaS paper Eq.6 and Splatter-a-Video paper Eq.4 Args: pred_depth: predicted depth target_depth: ground truth depth mask: validity mask ignore_large_loss: threshol
(pred_depth, target_depth, mask=None, ignore_large_loss=0.0, smooth_transition=True, range_utilization=0.0, eps=1e-8, inverse_depth=True)
| 2 | from einops import rearrange |
| 3 | |
| 4 | def ssitrim_loss(pred_depth, target_depth, mask=None, ignore_large_loss=0.0, smooth_transition=True, range_utilization=0.0, eps=1e-8, inverse_depth=True): |
| 5 | """ |
| 6 | pred_depth shape: [B, V, 1, H, W] |
| 7 | target_depth shape: [B, V, 1, H, W] |
| 8 | impl according to MiDaS paper Eq.6 and Splatter-a-Video paper Eq.4 |
| 9 | Args: |
| 10 | pred_depth: predicted depth |
| 11 | target_depth: ground truth depth |
| 12 | mask: validity mask |
| 13 | ignore_large_loss: threshold for filtering large losses |
| 14 | smooth_transition: whether to use smooth transition between small and large losses |
| 15 | range_utilization: weight for encouraging better utilization of depth range |
| 16 | eps: small constant for numerical stability |
| 17 | """ |
| 18 | # (B, H * W) |
| 19 | if mask is None: |
| 20 | mask = torch.ones_like(target_depth) |
| 21 | |
| 22 | if pred_depth.dim() == 5: |
| 23 | # seperate depth |
| 24 | # pred_depth = rearrange(pred_depth, 'B V C H W -> (B V) C H W') |
| 25 | # target_depth = rearrange(target_depth, 'B V C H W -> (B V) C H W') |
| 26 | # mask = rearrange(mask, 'B V C H W -> (B V) C H W') |
| 27 | # unify depth across all views |
| 28 | pred_depth = rearrange(pred_depth, 'B V C H W -> B (V C) H W') |
| 29 | target_depth = rearrange(target_depth, 'B V C H W -> B (V C) H W') |
| 30 | mask = rearrange(mask, 'B V C H W -> B (V C) H W') |
| 31 | |
| 32 | # Add range utilization encouragement |
| 33 | if range_utilization > 0: |
| 34 | # Calculate min and max depth values |
| 35 | min_depth = pred_depth.min(dim=1, keepdim=True)[0] |
| 36 | max_depth = pred_depth.max(dim=1, keepdim=True)[0] |
| 37 | |
| 38 | # Encourage min to be close to 0 and max to be close to 1 |
| 39 | min_penalty = torch.relu(min_depth) # Penalize if min > 0 |
| 40 | max_penalty = torch.relu(1 - max_depth) # Penalize if max < 1 |
| 41 | |
| 42 | # Encourage spread by penalizing small ranges |
| 43 | range_size = max_depth - min_depth |
| 44 | range_penalty = torch.relu(0.5 - range_size) # Penalize if range < 0.5 |
| 45 | |
| 46 | # Combine penalties |
| 47 | utilization_loss = (min_penalty + max_penalty + range_penalty).mean() * range_utilization |
| 48 | else: |
| 49 | utilization_loss = 0.0 |
| 50 | |
| 51 | if inverse_depth: |
| 52 | # Convert to inverse depth |
| 53 | pred_depth = 1.0 / (pred_depth + eps) |
| 54 | |
| 55 | pred_depth, target_depth = pred_depth * mask.float(), target_depth * mask.float() |
| 56 | |
| 57 | pred_depth, target_depth = pred_depth.flatten(1), target_depth.flatten(1) |
| 58 | |
| 59 | pix_num = pred_depth.shape[1] |
| 60 | |
| 61 | pred_t = torch.median(pred_depth.float(), dim=1).values |
nothing calls this directly
no outgoing calls
no test coverage detected