Depth_wizard / src /evaluation.py
nanii141149's picture
Initial DepthWizard release
a92ee50
Raw History Blame Contribute Delete
1.81 kB
"""Metrics and reports for paired height arrays."""
import numpy as np
from .calibration import ScaleShift, fit_scale_shift
def evaluate(prediction: np.ndarray, ground_truth: np.ndarray, valid: np.ndarray) -> tuple[ScaleShift, np.ndarray, dict]:
if prediction.shape != ground_truth.shape or valid.shape != ground_truth.shape:
raise ValueError("Prediction, ground truth, and validity mask must have matching shapes")
mask = valid & np.isfinite(prediction) & np.isfinite(ground_truth)
calibration = fit_scale_shift(prediction, ground_truth, mask)
aligned = calibration.apply(prediction)
errors = aligned[mask].astype(np.float64) - ground_truth[mask].astype(np.float64)
corr = float(np.corrcoef(aligned[mask], ground_truth[mask])[0, 1])
ss_res = float(np.sum(errors ** 2))
ss_tot = float(np.sum((ground_truth[mask] - ground_truth[mask].mean()) ** 2))
metrics = {
"method": "scale/shift aligned baseline",
"valid_pixels": int(mask.sum()),
"scale_coefficient": calibration.scale,
"shift_coefficient_m": calibration.shift,
"mae_m": float(np.mean(np.abs(errors))),
"rmse_m": float(np.sqrt(np.mean(errors ** 2))),
"pearson_r": corr,
"r_squared": float(1 - ss_res / ss_tot) if ss_tot > 0 else None,
"prediction_raw_min": float(np.min(prediction[mask])),
"prediction_raw_max": float(np.max(prediction[mask])),
"prediction_raw_mean": float(np.mean(prediction[mask])),
"ground_truth_min_m": float(np.min(ground_truth[mask])),
"ground_truth_max_m": float(np.max(ground_truth[mask])),
"ground_truth_mean_m": float(np.mean(ground_truth[mask])),
"ground_truth_median_m": float(np.median(ground_truth[mask])),
}
return calibration, aligned, metrics