IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 19140


Ignore:
Timestamp:
Aug 20, 2008, 3:12:44 PM (18 years ago)
Author:
Paul Price
Message:

Adding option of allowing 'exact' shifts when doing interpolation. This cuts down on a bit of the work in the event that the shift is integral. This can be turned off via a new boolean in psImageInterpolateOptions, so that a real interpolation kernel (not just with 0 and 1, but a real sinc kernel, for example) is returned. Hopefully this allows the use of psImageInterpolate to interpolate over bad pixels.

Location:
trunk/psLib/src/imageops
Files:
2 edited

Legend:

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

    r19129 r19140  
    77 *  @author Paul Price, IfA
    88 *
    9  *  @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
    10  *  @date $Date: 2008-08-20 04:06:31 $
     9 *  @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
     10 *  @date $Date: 2008-08-21 01:12:44 $
    1111 *
    1212 *  Copyright 2004-2007 Institute for Astronomy, University of Hawaii
     
    6060    options->poorMask = poorMask;
    6161    options->poorFrac = poorFrac;
     62    options->shifting = true;
    6263
    6364    return options;
     
    166167static inline void interpolateKernelGenerate(int xNum, int yNum, // Size of interpolation kernel
    167168                                             double kernel[xNum][yNum], // Kernel, to be set
     169                                             bool *xExact, bool *yExact, // Exact shift?
    168170                                             int xCentral, int yCentral, // Central pixel of convolution
    169171                                             float x, float y, // Coordinates of interest
    170                                              psImageInterpolateMode mode // Mode for interpolation
     172                                             psImageInterpolateMode mode, // Mode for interpolation
     173                                             bool allowExact // Allow exact shifts?
    171174                                             )
    172175{
     176    double xFrac = x - 0.5 - xCentral; // Fraction of pixel in x
     177    double yFrac = y - 0.5 - yCentral; // Fraction of pixel in y
     178    *xExact = (allowExact && fabs(xFrac) < DBL_EPSILON);
     179    *yExact = (allowExact && fabs(yFrac) < DBL_EPSILON);
     180
    173181    switch (mode) {
    174182      case PS_INTERPOLATE_BILINEAR: {
    175           double xFrac = x - 0.5 - xCentral; // Fraction of pixel in x
    176           double yFrac = y - 0.5 - yCentral; // Fraction of pixel in y
    177183          kernel[0][0] = (1.0 - xFrac) * (1.0 - yFrac);
    178184          kernel[0][1] = xFrac * (1.0 - yFrac);
     
    220226        psAbort("Invalid interpolation mode.");
    221227    }
    222 }
     228    return;
     229}
     230
     231// Can't interpolate: kernel is off the image
     232#define INTERPOLATE_OFF() { \
     233        *imageValue = options->badImage; \
     234        if (varianceValue) { \
     235            *varianceValue = options->badVariance; \
     236        } \
     237        if (maskValue) { \
     238            *maskValue = options->badMask; \
     239        } \
     240        return PS_INTERPOLATE_STATUS_OFF; \
     241    }
    223242
    224243// Set up and check interpolation bounds
     
    231250    if (xStart > xLast || xStop < 0 || yStart > yLast || yStop < 0) { \
    232251        /* Interpolation kernel is entirely off the image */ \
    233         *imageValue = options->badImage; \
    234         if (varianceValue) { \
    235             *varianceValue = options->badVariance; \
    236         } \
    237         if (maskValue) { \
    238             *maskValue = options->badMask; \
    239         } \
    240         return PS_INTERPOLATE_STATUS_OFF; \
     252        INTERPOLATE_OFF(); \
    241253    } \
    242254    int xMin, xMax, yMin, yMax; /* Minimum and maximum valid pixels on image */ \
     
    276288    }
    277289
     290// Refine limits if the interpolation is exact
     291#define INTERPOLATE_EXACT() { \
     292    if (xExact) { \
     293        if (iMin > 0 || iMax < 1) { \
     294            INTERPOLATE_OFF(); /* Returns */ \
     295        } \
     296        iMin = (xNum - 1) / 2; \
     297        iMax = iMin + 1; \
     298    } \
     299    if (yExact) { \
     300        if (jMin > 0 || jMax < 1) { \
     301            INTERPOLATE_OFF(); /* Returns */ \
     302        } \
     303        jMin = (yNum - 1) / 2; \
     304        jMax = jMin + 1; \
     305    } \
     306    if (xExact && yExact) { \
     307        return interpolateFlat(imageValue, varianceValue, maskValue, x, y, options); \
     308    } \
     309}
     310
    278311// Interpolation engine using interpolation kernel
    279312static psImageInterpolateStatus interpolateKernel(double *imageValue, double *varianceValue,
     
    294327
    295328    double kernel[yNum][xNum];          // Interpolation kernel for straight interpolation
    296     interpolateKernelGenerate(xNum, yNum, kernel, xCentral, yCentral, x, y, options->mode);
     329    bool xExact, yExact;                // Exact shifts?
     330    interpolateKernelGenerate(xNum, yNum, kernel, &xExact, &yExact, xCentral, yCentral,
     331                              x, y, options->mode, options->shifting);
    297332
    298333    float sumKernel = 0.0;              // Sum of the kernel
     
    306341    bool haveMask = mask && maskVal; // Does the user want the variance value?
    307342
     343    INTERPOLATE_EXACT();
     344
    308345    // Add contributions in an area outside the image
    309346#define INTERPOLATE_KERNEL_ADD_OFFIMAGE() { \
     
    316353    // Measure kernel contribution from outside image
    317354    if (offImage) {
    318         // Bottom rows
    319         for (int j = 0; j < jMin; j++) {
    320             for (int i = 0; i < xNum; i++) {
    321                 INTERPOLATE_KERNEL_ADD_OFFIMAGE();
     355        if (!yExact) {
     356            // Bottom rows
     357            for (int j = 0; j < jMin; j++) {
     358                for (int i = 0; i < xNum; i++) {
     359                    INTERPOLATE_KERNEL_ADD_OFFIMAGE();
     360                }
    322361            }
    323362        }
    324         // Two sides
    325         for (int j = jMin; j < jMax; j++) {
    326             for (int i = 0; i < iMin; i++) {
    327                 INTERPOLATE_KERNEL_ADD_OFFIMAGE();
     363        if (!xExact) {
     364            // Two sides
     365            for (int j = jMin; j < jMax; j++) {
     366                for (int i = 0; i < iMin; i++) {
     367                    INTERPOLATE_KERNEL_ADD_OFFIMAGE();
     368                }
     369                for (int i = iMax + 1; i < xNum; i++) {
     370                    INTERPOLATE_KERNEL_ADD_OFFIMAGE();
     371                }
    328372            }
    329             for (int i = iMax + 1; i < xNum; i++) {
    330                 INTERPOLATE_KERNEL_ADD_OFFIMAGE();
    331             }
    332         }
    333         // Top rows
    334         for (int j = jMax + 1; j < yNum; j++) {
    335             for (int i = 0; i < xNum; i++) {
    336                 INTERPOLATE_KERNEL_ADD_OFFIMAGE();
     373        }
     374        if (!yExact) {
     375            // Top rows
     376            for (int j = jMax + 1; j < yNum; j++) {
     377                for (int i = 0; i < xNum; i++) {
     378                    INTERPOLATE_KERNEL_ADD_OFFIMAGE();
     379                }
    337380            }
    338381        }
     
    445488// Generate Lanczos interpolation kernels
    446489static void lanczos(double values[],    // Interpolation kernel to generate
     490                    bool *exact,        // Exact shift?
    447491                    int num,            // Number of values in the kernel
    448                     float frac          // Sub-pixel position
     492                    float frac,         // Sub-pixel position
     493                    bool allowExact     // Allow exact shift?
    449494    )
    450495{
    451     // XXX: Instead of generating a convolution kernel that does no shifting, need to set a boolean that says
    452     // we can do an exact shift.
    453     if (fabs(frac) < DBL_EPSILON) {
     496    if (allowExact && fabs(frac) < DBL_EPSILON) {
     497        *exact = true;
    454498        // No real shift
    455499        for (int i = 0; i < (num - 1) / 2; i++) {
     
    461505        }
    462506    } else {
    463         double norm4 = 0.0;             // Normalisation
     507        *exact = false;
    464508        double norm1 = 2.0 / PS_SQR(M_PI); // Normalisation for laczos
    465509        double norm2 = M_PI * 4.0 / (float)num; // Normalisation for sinc function 1
     
    467511        double pos = - (num - 1)/2 - frac;  // Position of interest
    468512        for (int i = 0; i < num; i++, pos += 1.0) {
    469             norm4 += values[i] = norm1 * sin(pos * norm2) * sin(pos * norm3) / PS_SQR(pos);
    470         }
    471         norm4 = 1.0 / norm4;
    472         for (int i = 0; i < num; i++) {
    473             values[i] *= norm4;
     513            if (fabs(pos) < DBL_EPSILON) {
     514                values[i] = 1.0;
     515            } else {
     516                values[i] = norm1 * sin(pos * norm2) * sin(pos * norm3) / PS_SQR(pos);
     517            }
    474518        }
    475519    }
     
    510554static inline void interpolateSeparateGenerate(int xNum, int yNum, // Size of interpolation kernel
    511555                                               double xKernel[xNum], double yKernel[yNum], // Kernels
     556                                               bool *xExact, bool *yExact, // Exact shifts?
    512557                                               int xCentral, int yCentral, // Central pixel of convolution
    513558                                               float x, float y, // Coordinates of interest
    514                                                psImageInterpolateMode mode // Mode for interpolation
     559                                               psImageInterpolateMode mode, // Mode for interpolation
     560                                               bool allowExact // Allow an exact shift?
    515561                                               )
    516562{
     
    521567      case PS_INTERPOLATE_LANCZOS4: {
    522568          double xFrac = x - xCentral - 0.5; // Fraction of pixel in x
    523           lanczos(xKernel, xNum, xFrac);
     569          lanczos(xKernel, xExact, xNum, xFrac, allowExact);
    524570          double yFrac = y - yCentral - 0.5; // Fraction of pixel in y
    525           lanczos(yKernel, yNum, yFrac);
     571          lanczos(yKernel, yExact, yNum, yFrac, allowExact);
    526572          break;
    527573      }
     
    553599
    554600    double xKernel[xNum], yKernel[yNum]; // Interpolation kernels
    555     interpolateSeparateGenerate(xNum, yNum, xKernel, yKernel, xCentral, yCentral, x, y, options->mode);
     601    bool xExact, yExact;                // Exact shift?
     602    interpolateSeparateGenerate(xNum, yNum, xKernel, yKernel, &xExact, &yExact,
     603                                xCentral, yCentral, x, y, options->mode, options->shifting);
    556604
    557605    float sumKernel = 0.0;              // Sum of the kernel
     
    564612    bool wantVariance = variance && varianceValue; // Does the user want the variance value?
    565613    bool haveMask = mask && maskVal; // Does the user want the variance value?
     614
     615    INTERPOLATE_EXACT();
    566616
    567617    // Add contributions in an area outside the image
     
    585635    if (offImage) {
    586636        // Bottom rows
    587         for (int j = 0; j < jMin; j++) {
    588             INTERPOLATE_SEPARATE_SETUP_OFFIMAGE_COL();
    589             for (int i = 0; i < xNum; i++) {
    590                 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL();
     637        if (!yExact) {
     638            for (int j = 0; j < jMin; j++) {
     639                INTERPOLATE_SEPARATE_SETUP_OFFIMAGE_COL();
     640                for (int i = 0; i < xNum; i++) {
     641                    INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL();
     642                }
     643                INTERPOLATE_SEPARATE_ADD_OFFIMAGE_ROW();
    591644            }
    592             INTERPOLATE_SEPARATE_ADD_OFFIMAGE_ROW();
    593645        }
    594646        // Two sides
    595         for (int j = jMin; j < jMax; j++) {
    596             INTERPOLATE_SEPARATE_SETUP_OFFIMAGE_COL();
    597             for (int i = 0; i < iMin; i++) {
    598                 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL();
     647        if (!xExact) {
     648            for (int j = jMin; j < jMax; j++) {
     649                INTERPOLATE_SEPARATE_SETUP_OFFIMAGE_COL();
     650                for (int i = 0; i < iMin; i++) {
     651                    INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL();
     652                }
     653                for (int i = iMax + 1; i < xNum; i++) {
     654                    INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL();
     655                }
     656                INTERPOLATE_SEPARATE_ADD_OFFIMAGE_ROW();
    599657            }
    600             for (int i = iMax + 1; i < xNum; i++) {
    601                 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL();
     658        }
     659        // Top rows
     660        if (!yExact) {
     661            for (int j = jMax + 1; j < yNum; j++) {
     662                if (!xExact) {
     663                    INTERPOLATE_SEPARATE_SETUP_OFFIMAGE_COL();
     664                    for (int i = 0; i < xNum; i++) {
     665                        INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL();
     666                    }
     667                    INTERPOLATE_SEPARATE_ADD_OFFIMAGE_ROW();
     668                }
    602669            }
    603             INTERPOLATE_SEPARATE_ADD_OFFIMAGE_ROW();
    604         }
    605         // Top rows
    606         for (int j = jMax + 1; j < yNum; j++) {
    607             INTERPOLATE_SEPARATE_SETUP_OFFIMAGE_COL();
    608             for (int i = 0; i < xNum; i++) {
    609                 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL();
    610             }
    611             INTERPOLATE_SEPARATE_ADD_OFFIMAGE_ROW();
    612670        }
    613671    }
     
    826884
    827885    double kernel[yNum][xNum];          // Interpolation kernel for straight interpolation
    828     interpolateKernelGenerate(xNum, yNum, kernel, xCentral, yCentral, x, y, options->mode);
     886    bool xExact, yExact;                // Exact shift?
     887    // Pretend we're not shifting pixels (i.e., we don't care about any exact shifting) because on the off
     888    // chance that a shift is integral, we don't want to get a trivial kernel back, but something that sort of
     889    // reflects what's going on.
     890    interpolateKernelGenerate(xNum, yNum, kernel, &xExact, &yExact, xCentral, yCentral,
     891                              x, y, options->mode, false);
    829892
    830893    double sumKernel2 = 0.0;            // Sum of kernel squares
     
    855918
    856919    double xKernel[xNum], yKernel[yNum]; // Interpolation kernels for separable interpolation
    857     interpolateSeparateGenerate(xNum, yNum, xKernel, yKernel, xCentral, yCentral, x, y, options->mode);
     920    bool xExact, yExact;                // Exact shift?
     921    // Pretend we're not shifting pixels (i.e., we don't care about any exact shifting) because on the off
     922    // chance that a shift is integral, we don't want to get a trivial kernel back, but something that sort of
     923    // reflects what's going on.
     924    interpolateSeparateGenerate(xNum, yNum, xKernel, yKernel, &xExact, &yExact,
     925                                xCentral, yCentral, x, y, options->mode, false);
    858926
    859927    double ySumKernel2 = 0.0;           // Sum of kernel squared in y
  • trunk/psLib/src/imageops/psImageInterpolate.h

    r18162 r19140  
    77 * @author Paul Price, Institute for Astronomy
    88 *
    9  * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
    10  * @date $Date: 2008-06-17 21:24:58 $
     9 * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
     10 * @date $Date: 2008-08-21 01:12:44 $
    1111 * Copyright 2004-2007 Institute for Astronomy, University of Hawaii
    1212 */
     
    5353    psMaskType poorMask;                ///< Mask value to give poor pixels
    5454    float poorFrac;                     ///< Fraction of flux in bad pixels before output is marked bad
     55    bool shifting;                      ///< Shifting images? Don't interpolate if the shift is exact.
    5556} psImageInterpolateOptions;
    5657
Note: See TracChangeset for help on using the changeset viewer.