SAM and ERGAS for images with zero-value pixels #1127
|
Hi, I am using SAM and ERGAS from TorchMetrics with images that happen to be padded with zero values (which is quite common in remote sensing). The pixels with value zero cause the metrics to (maybe?) break. SAM becomes However, this is rather inconvenient. Would you consider letting the behavior of these functions change so they can handle pixels with zero value? I think it can be fixed with changing Example of this problem in Python REPL: This can be easily mitigated on the user side for SAM ( |
Replies: 2 comments
|
Also, adding EPS to the divider may be a solution too. |
|
@maciejzj — your analysis is spot on. Zero-value pixels cause division by zero in both SAM and ERGAS. Workaround 1 — Mask out zero regions: import torch
from torchmetrics.functional.image import spectral_angle_mapper
# Create mask of valid pixels
valid_mask = (target.sum(dim=1, keepdim=True) != 0) # (N, 1, H, W)
preds_masked = preds * valid_mask
target_masked = target * valid_mask
# Use reduction="none" and average over valid pixels only
sam_map = spectral_angle_mapper(preds_masked, target_masked, reduction="none")
valid_pixels = valid_mask.squeeze(1)
sam_score = sam_map[valid_pixels].mean()Workaround 2 — Add epsilon (simpler but slightly changes values): eps = 1e-8
sam_score = spectral_angle_mapper(preds + eps, target + eps)Workaround 3 — Crop zero padding (if zeros are at borders, common in remote sensing): nonzero = target.sum(dim=(0, 1)).nonzero()
y_min, x_min = nonzero.min(dim=0).values
y_max, x_max = nonzero.max(dim=0).values
preds_crop = preds[:, :, y_min:y_max+1, x_min:x_max+1]
target_crop = target[:, :, y_min:y_max+1, x_min:x_max+1]
sam_score = spectral_angle_mapper(preds_crop, target_crop)This is a real gap in the library — the metrics should handle zero pixels gracefully. Worth opening a PR if you're up for it. |
@maciejzj — your analysis is spot on. Zero-value pixels cause division by zero in both SAM and ERGAS.
Workaround 1 — Mask out zero regions:
Workaround 2 — Add epsilon (simpler but slightly changes values):