IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jul 13, 2010, 2:34:04 PM (16 years ago)
Author:
Paul Price
Message:

It's bothered me for a while that the noise model that we have been using is only kind of spatially variable. The variance map is intended to track the change in the noise properties as a function of position, and while it does keep track of different noise levels due to, e.g., different detectors, vignetting, etc., it has not tracked the different noise that comes from convolution kernels changing over an image. This had been an intentional oversight --- the prescription we were using for calculating the variance and covariance removed the spatial variation (by prescribing that the variance level under a convolution remain unchanged) and we were sweeping it under the carpet so we could calculate the covariance pseudo-matrix and use that for setting the absolute level of the noise.

I've now figured out how to have our cake and eat it too. By changing where the scalings are applied, the variance map can track the changing noise introduced by a varying convolution kernel, while the covariance pseudo-matrix tracks an absolute change. This fix is purely algorithmic --- it does not affect any of the variances/covariances stored on disk, nor is it affected by them. I hope that this means that any Magic recertification required is either minimal or completely unnecessary.

Again, all that has changed is where the scalings are applied.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/imageops/psImageInterpolate.c

    r26892 r28667  
    427427
    428428// Determine the result of the interpolation after all the math has been done
    429 #define INTERPOLATE_RESULT() \
    430     psImageInterpolateStatus status = PS_INTERPOLATE_STATUS_ERROR; /* Status of interpolation */ \
    431     *imageValue = sumKernel > 0 ? sumImage / sumKernel : interp->badImage; \
    432     if (wantVariance) { \
    433         *varianceValue = sumVariance / (sumKernel2 - sumBad); \
    434     } \
    435     if (sumKernel == 0.0) { \
    436         /* No kernel contributions */ \
    437         if (haveMask && maskValue) { \
    438             *maskValue |= interp->badMask; \
    439         } \
    440         status = PS_INTERPOLATE_STATUS_BAD; \
    441     } else if (sumBad == 0) { \
    442         /* Completely good pixel */ \
    443         status = PS_INTERPOLATE_STATUS_GOOD; \
    444     } else if (sumBad < PS_SQR(interp->poorFrac) * sumKernel2) { \
    445         /* Some pixels masked: poor pixel */ \
    446         if (haveMask && maskValue) { \
    447             *maskValue |= interp->poorMask; \
    448         } \
    449         status = PS_INTERPOLATE_STATUS_POOR; \
    450     } else { \
    451         /* Many pixels (or a few important pixels) masked: bad pixel */ \
    452         if (haveMask && maskValue) { \
    453             *maskValue |= interp->badMask; \
    454         } \
    455         status = PS_INTERPOLATE_STATUS_BAD; \
    456     }
     429static psImageInterpolateStatus interpolateResult(const psImageInterpolation *interp,
     430                                                  double *imageValue, double *varianceValue,
     431                                                  psImageMaskType *maskValue,
     432                                                  double sumImage, double sumVariance, double sumBad,
     433                                                  double sumKernel, double sumKernel2,
     434                                                  bool wantVariance, bool haveMask)
     435{
     436    *imageValue = sumKernel > 0 ? sumImage / sumKernel : interp->badImage;
     437    if (wantVariance) {
     438        if (sumBad > 0) {
     439            sumVariance *= sumKernel2 / (sumKernel2 - sumBad);
     440        }
     441        *varianceValue = sumVariance / PS_SQR(sumKernel);
     442    }
     443    if (sumKernel == 0.0) {
     444        // No kernel contributions at all
     445        if (haveMask && maskValue) {
     446            *maskValue |= interp->badMask;
     447        }
     448        return PS_INTERPOLATE_STATUS_BAD;
     449    }
     450    if (sumBad == 0) {
     451        // Completely good pixel
     452        return PS_INTERPOLATE_STATUS_GOOD;
     453    }
     454    if (sumBad < PS_SQR(interp->poorFrac) * sumKernel2) {
     455        // Some pixels masked: poor pixel
     456        if (haveMask && maskValue) {
     457            *maskValue |= interp->poorMask;
     458        }
     459        return PS_INTERPOLATE_STATUS_POOR;
     460    }
     461    // Many pixels (or a few important pixels) masked: bad pixel
     462    if (haveMask && maskValue) {
     463        *maskValue |= interp->badMask;
     464    }
     465    return PS_INTERPOLATE_STATUS_BAD;
     466}
    457467
    458468// Interpolation engine for separable interpolation kernels
     
    703713    }
    704714
    705     INTERPOLATE_RESULT();
    706 
    707715    psFree(xKernelNew);
    708716    psFree(yKernelNew);
     
    710718    psFree(yKernel2New);
    711719
    712     return status;
     720    return interpolateResult(interp, imageValue, varianceValue, maskValue, sumImage, sumVariance, sumBad,
     721                             sumKernel, sumKernel2, wantVariance, haveMask);
    713722}
    714723
     
    861870    }
    862871
    863     INTERPOLATE_RESULT();
    864 
    865     return status;
     872    return interpolateResult(interp, imageValue, varianceValue, maskValue, sumImage, sumVariance, sumBad,
     873                             sumKernel, sumKernel2, wantVariance, haveMask);
    866874}
    867875
Note: See TracChangeset for help on using the changeset viewer.