IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jul 10, 2007, 1:54:26 PM (19 years ago)
Author:
Paul Price
Message:

Adding additional convolution kernels: SPAM (binned pixels around a central single-pixel core) and FRIES (binning changes as a (Fibonacci-like) function of radius).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psModules/src/imcombine/pmSubtraction.c

    r13736 r14106  
    44 *  @author GLG, MHPCC
    55 *
    6  *  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
    7  *  @date $Date: 2007-06-09 01:06:48 $
     6 *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
     7 *  @date $Date: 2007-07-10 23:54:26 $
    88 *
    99 *  Copyright 2004-2007 Institute for Astronomy, University of Hawaii
     
    2424
    2525#include "pmSubtraction.h"
     26
     27//#define CAN_PASS_STATIC_INLINE          // Can I pass the address of a static inline function?
    2628
    2729//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     
    5355}
    5456
     57#ifndef CAN_PASS_STATIC_INLINE
    5558// Generate an image of the solved kernel
    5659// Meant to replace the following function declaration:
     
    6164//                                      double (*weightFunc)(double value) // Function for weighting
    6265//     );
    63 // because even if the weightFunc can't be "static inline", they still appear in the assembly.
     66// because even though the weightFunc is "static inline", it still appears in the assembly.
    6467// TARGET: Kernel, to return (psKernel*)
    6568// SOLUTION: Solution to the least-squares problem (psVector*)
     
    7578    \
    7679    /* Ensure the subIndex for POIS kernels is what is expected */ \
    77     assert((KERNELS)->type != PM_SUBTRACTION_KERNEL_POIS || \
     80    assert(((KERNELS)->type != PM_SUBTRACTION_KERNEL_POIS && \
     81           (KERNELS)->type != PM_SUBTRACTION_KERNEL_SPAM && \
     82           (KERNELS)->type != PM_SUBTRACTION_KERNEL_FRIES) || \
    7883           ((KERNELS)->u->data.S32[(KERNELS)->subIndex] == 0 && \
    7984            (KERNELS)->v->data.S32[(KERNELS)->subIndex] == 0 && \
     
    103108              break; \
    104109          } \
     110          /* SPAM and FRIES use the same method */ \
     111          case PM_SUBTRACTION_KERNEL_SPAM: \
     112          case PM_SUBTRACTION_KERNEL_FRIES: { \
     113            int uStart = (KERNELS)->u->data.S32[i]; \
     114            int uStop = (KERNELS)->uStop->data.S32[i]; \
     115            int vStart = (KERNELS)->v->data.S32[i]; \
     116            int vStop = (KERNELS)->vStop->data.S32[i]; \
     117            for (int v = vStart; v <= vStop; v++) { \
     118                for (int u = uStart; u <= uStop; u++) { \
     119                    (TARGET)->kernel[v][u] += value; \
     120                } \
     121            } \
     122            if ((KERNELS)->spatialOrder > 0 && i != (KERNELS)->subIndex) { \
     123                /* The (0,0) element is subtracted from most kernels to preserve photometric scaling */ \
     124                (TARGET)->kernel[0][0] += subValue; \
     125            } \
     126            break; \
     127          } \
    105128          case PM_SUBTRACTION_KERNEL_ISIS: { \
    106129              psKernel *preCalc = (KERNELS)->preCalc->data[i]; /* Precalculated values */ \
     
    122145    } \
    123146}
    124 
    125 #if 0
     147#else
    126148// Generate an image of the solved kernel
    127149static inline psKernel *solvedKernel(psKernel *kernel, // Kernel, to return
     
    139161
    140162    // Ensure the subIndex for POIS kernels is what is expected
    141     assert(kernels->type != PM_SUBTRACTION_KERNEL_POIS ||
     163    assert((kernels->type != PM_SUBTRACTION_KERNEL_POIS &&
     164            kernels->type != PM_SUBTRACTION_KERNEL_SPAM &&
     165            kernels->type != PM_SUBTRACTION_KERNEL_FRIES) ||
    142166           (kernels->u->data.S32[kernels->subIndex] == 0 && kernels->v->data.S32[kernels->subIndex] == 0 &&
    143167            kernels->xOrder->data.S32[kernels->subIndex] == 0 &&
     
    167191              break;
    168192          }
     193          /* SPAM and FRIES use the same method */
     194          case PM_SUBTRACTION_KERNEL_SPAM:
     195          case PM_SUBTRACTION_KERNEL_FRIES:
     196            int uStart = kernels->u->data.S32[i];
     197            int uStop = kernels->uStop->data.S32[i];
     198            int vStart = kernels->v->data.S32[i];
     199            int vStop = kernels->vStop->data.S32[i];
     200            for (int v = vStart; v <= vStop; v++) {
     201                for (int u = uStart; u <= uStop; u++) {
     202                    kernel->kernel[v][u] += value;
     203                }
     204            }
     205            if (kernels->spatialOrder > 0 && i != kernels->subIndex) {
     206                /* The (0,0) element is subtracted from most kernels to preserve photometric scaling */
     207                kernel->kernel[0][0] += subValue;
     208            }
     209            break;
    169210          case PM_SUBTRACTION_KERNEL_ISIS: {
    170211              psKernel *preCalc = kernels->preCalc->data[i];// Precalculated values
     
    190231#endif
    191232
     233#ifndef CAN_PASS_STATIC_INLINE
    192234// Generate the convolved pixel value
    193235// Meant to replace the following function declaration:
     
    199241//                                    double (*weightFunc)(double value) // Function for weighting
    200242//     );
    201 // because even if the weightFunc can't be "static inline", they still appear in the assembly.
     243// because even though weightFunc is "static inline", it still appears in the assembly.
    202244//
    203245// TARGET: The value to 'return' (double)
     
    225267          break; \
    226268      } \
    227       case PM_SUBTRACTION_KERNEL_ISIS: { \
     269      /* Method for SPAM and FRIES is the same */ \
     270      case PM_SUBTRACTION_KERNEL_SPAM: \
     271      case PM_SUBTRACTION_KERNEL_FRIES: { \
     272          int uStart = (KERNELS)->u->data.S32[(INDEX)]; \
     273          int uStop = (KERNELS)->uStop->data.S32[(INDEX)]; \
     274          int vStart = (KERNELS)->v->data.S32[(INDEX)]; \
     275          int vStop = (KERNELS)->vStop->data.S32[(INDEX)]; \
     276          for (int v = vStart; v <= vStop; v++) { \
     277              for (int u = uStart; u <= uStop; u++) { \
     278                  (TARGET) += FUNC(polyValue) * (IMAGE)->data.F32[(Y) + v][(X) + u]; \
     279              } \
     280          } \
     281          if ((KERNELS)->spatialOrder > 0 && (INDEX) != (KERNELS)->subIndex) { \
     282              /* The (0,0) element is subtracted from most kernels to preserve photometric scaling */ \
     283              (TARGET) += FUNC(-1.0) * (IMAGE)->data.F32[(Y)][(X)]; \
     284          } \
     285          break; \
     286      } \
     287            case PM_SUBTRACTION_KERNEL_ISIS: { \
    228288          psKernel *kernel = (KERNELS)->preCalc->data[(INDEX)]; /* The convolution kernel */ \
    229289          psKernel *subKernel = (KERNELS)->preCalc->data[(KERNELS)->subIndex]; /* Kernel to subtract */ \
     
    231291          double sum = 0.0;             /* Accumulated sum from convolution */ \
    232292          double sub = 0.0;             /* Accumulated sum to subtract */ \
    233           for (int v = -size; v <= size; v++) { \
    234               for (int u = -size; u <= size; u++) { \
    235                   sum += FUNC(kernel->kernel[v][u]) * (IMAGE)->data.F32[(Y) + v][(X) + u]; \
     293          for (int v = -size, y = (Y) - size; v <= size; v++, y++) { \
     294              for (int u = -size, x = (X) - size; u <= size; u++, x++) { \
     295                  sum += FUNC(kernel->kernel[v][u]) * (IMAGE)->data.F32[y][x]; \
    236296                  /* The (0,0) kernel is subtracted from other kernels to preserve photometric scaling */ \
    237297                  if ((KERNELS)->spatialOrder > 0 && (INDEX) != (KERNELS)->subIndex) { \
    238                       sub += FUNC(subKernel->kernel[v][u]) * (IMAGE)->data.F32[(Y) + v][(X) + u]; \
     298                      sub += FUNC(subKernel->kernel[v][u]) * (IMAGE)->data.F32[y][x]; \
    239299                  } \
    240300              } \
     
    247307    } \
    248308}
    249 
    250 #if 0
     309#else
    251310// Generate the convolved pixel value
    252311static inline double convolvePixel(const pmSubtractionKernels *kernels, // Kernel basis functions
     
    273332          }
    274333          return value;
     334      }
     335      /* Method for SPAM and FRIES is the same */
     336      case PM_SUBTRACTION_KERNEL_SPAM:
     337      case PM_SUBTRACTION_KERNEL_FRIES: {
     338          int uStart = kernels->u->data.S32[index];
     339          int uStop = kernels->uStop->data.S32[index];
     340          int vStart = kernels->v->data.S32[index];
     341          int vStop = kernels->vStop->data.S32[index];
     342          for (int v = vStart; v <= vStop; v++) {
     343              for (int u = uStart; u <= uStop; u++) {
     344                  value += weightFunc(polyValue) * image->data.F32[y + v][x + u];
     345              }
     346          }
     347          if (kernels->spatialOrder > 0 && index != kernels->subIndex) {
     348              /* The (0,0) element is subtracted from most kernels to preserve photometric scaling */
     349              value += weightFunc(-1.0) * image->data.F32[y][x];
     350          }
     351          break;
    275352      }
    276353      case PM_SUBTRACTION_KERNEL_ISIS: {
     
    333410//////////////////////////////////////////////////////////////////////////////////////////////////////////////
    334411
    335 psImage *pmSubtractionMask(const psImage *inMask, const psImage *refMask, psMaskType maskVal,
    336                            int size, int footprint)
    337 {
    338     PS_ASSERT_IMAGE_NON_NULL(inMask, NULL);
    339     PS_ASSERT_IMAGE_TYPE(inMask, PS_TYPE_MASK, NULL);
    340     PS_ASSERT_IMAGE_NON_NULL(refMask, NULL);
    341     PS_ASSERT_IMAGE_TYPE(refMask, PS_TYPE_MASK, NULL);
    342     PS_ASSERT_IMAGES_SIZE_EQUAL(inMask, refMask, NULL);
    343     PS_ASSERT_INT_NONNEGATIVE(size, NULL);
    344     PS_ASSERT_INT_NONNEGATIVE(footprint, NULL);
    345 
    346     // Size of the images
    347     int numCols = inMask->numCols;
    348     int numRows = inMask->numRows;
    349 
    350     // Worried about the masks for bad pixels and bad stamps colliding, so make our own mask
    351     psImage *mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK); // The global mask
    352     psImageInit(mask, 0);
    353 
    354     // Dereference for convenience
    355     psMaskType **maskData = mask->data.PS_TYPE_MASK_DATA;
    356     psMaskType **inData = inMask->data.PS_TYPE_MASK_DATA;
    357     psMaskType **refData = refMask->data.PS_TYPE_MASK_DATA;
    358 
    359     // Block out a border around the edge of the image
    360 
    361     // Bottom stripe
    362     for (int y = 0; y < PS_MIN(size + footprint, numRows); y++) {
    363         for (int x = 0; x < numCols; x++) {
    364             maskData[y][x] |= PM_SUBTRACTION_MASK_BORDER;
    365         }
    366     }
    367     // Either side
    368     for (int y = PS_MIN(size + footprint, numRows); y < numRows - size - footprint; y++) {
    369         for (int x = 0; x < PS_MIN(size + footprint, numCols); x++) {
    370             maskData[y][x] |= PM_SUBTRACTION_MASK_BORDER;
    371         }
    372         for (int x = PS_MAX(numCols - size - footprint, 0); x < numCols; x++) {
    373             maskData[y][x] |= PM_SUBTRACTION_MASK_BORDER;
    374         }
    375     }
    376     // Top stripe
    377     for (int y = PS_MAX(numRows - size - footprint, 0); y < numRows; y++) {
    378         for (int x = 0; x < numCols; x++) {
    379             maskData[y][x] |= PM_SUBTRACTION_MASK_BORDER;
    380         }
    381     }
    382 
    383     // Mask the bad pixels, and around them
    384     for (int y = footprint + size; y < numRows - footprint - size; y++) {
    385         for (int x = 0; x < numCols; x++) {
    386             if (inData[y][x] & maskVal) {
    387                 maskData[y][x] |= PM_SUBTRACTION_MASK_INPUT;
    388                 // Block out the entire stamp footprint around this pixel
    389                 for (int v = y - footprint; v <= y + footprint; v++) {
    390                     for (int u = x - footprint; u <= x + footprint; u++) {
    391                         maskData[v][u] |= PM_SUBTRACTION_MASK_FOOTPRINT;
    392                     }
    393                 }
    394             }
    395             if (refData[y][x] & maskVal) {
    396                 maskData[y][x] |= PM_SUBTRACTION_MASK_REF;
    397 
    398                 // We want to block out with the CONVOLVE mask anything that would be bad if we convolved with
    399                 // this bad pixel (within 'size').  Then we want to block out with the FOOTPRINT mask
    400                 // everything within a footprint's distance of those (within 'footprint').
    401 
    402                 // Bottom stripe
    403                 for (int v = PS_MAX(y - footprint - size, 0); v < y - size; v++) {
    404                     for (int u = PS_MAX(x - footprint - size, 0);
    405                          u <= PS_MIN(x + footprint + size, numCols - 1); u++) {
    406                         maskData[v][u] |= PM_SUBTRACTION_MASK_FOOTPRINT;
    407                     }
    408                 }
    409                 // Middle
    410                 for (int v = PS_MAX(y - size, 0); v <= PS_MIN(y + size, numRows - 1); v++) {
    411                     // Left side
    412                     for (int u = PS_MAX(x - footprint - size, 0); u < x - size; u++) {
    413                         maskData[v][u] |= PM_SUBTRACTION_MASK_FOOTPRINT;
    414                     }
    415                     // Centre
    416                     for (int u = PS_MAX(x - size, 0); u <= PS_MIN(x + size, numCols - 1); u++) {
    417                         maskData[v][u] |= PM_SUBTRACTION_MASK_FOOTPRINT | PM_SUBTRACTION_MASK_CONVOLVE;
    418                     }
    419                     // Right side
    420                     for (int u = x + size + 1; u <= PS_MIN(x + footprint + size, numCols - 1); u++) {
    421                         maskData[v][u] |= PM_SUBTRACTION_MASK_FOOTPRINT;
    422                     }
    423                 }
    424                 // Top stripe
    425                 for (int v = y + size + 1; v <= PS_MIN(y + footprint + size, numRows - 1); v++) {
    426                     for (int u = PS_MAX(x - footprint - size, 0);
    427                          u <= PS_MIN(x + footprint + size, numCols - 1); u++) {
    428                         maskData[v][u] |= PM_SUBTRACTION_MASK_FOOTPRINT;
    429                     }
    430                 }
    431             }
    432         }
    433     }
    434 
    435     return mask;
    436 }
    437 
    438412bool pmSubtractionCalculateEquation(psArray *stamps, const psImage *reference, const psImage *input,
    439413                                    const psImage *weight, const pmSubtractionKernels *kernels, int footprint)
     
    504478                    // Generate the convolutions
    505479                    for (int i = 0; i < numKernels; i++) {
    506 #if 0
     480#ifdef CAN_PASS_STATIC_INLINE
    507481                        convolutions->data.F64[i] = convolvePixel(kernels, i, x, y, reference, polyValues,
    508482                                                                  imageWeighting);
     
    533507            psFree(polyValues);
    534508
    535             // Fill in lower diagonal of symmetric matrix, while checking for bad values
    536             bool bad = false;           // Are there bad values?
     509            // Fill in lower diagonal of symmetric matrix
    537510            for (int i = 0; i < numKernels; i++) {
    538511                for (int j = 0; j < i; j++) {
    539                     if (!isfinite(stampMatrix->data.F64[j][i])) {
    540                         bad = true;
    541                     }
    542512                    stampMatrix->data.F64[i][j] = stampMatrix->data.F64[j][i];
    543513                }
    544                 if (!isfinite(stampMatrix->data.F64[i][bgIndex]) ||
    545                     !isfinite(stampMatrix->data.F64[i][i]) ||
    546                     !isfinite(stampVector->data.F64[i])) {
    547                     bad = true;
    548                 }
    549514                stampMatrix->data.F64[bgIndex][i] = stampMatrix->data.F64[i][bgIndex];
    550515            }
    551             if (!isfinite(stampVector->data.F64[bgIndex])) {
    552                 bad = true;
    553             }
    554 
    555             if (bad) {
    556                 stamp->status = PM_SUBTRACTION_STAMP_REJECTED;
    557                 psTrace("psModules.imcombine", 3, "Rejecting stamp %d because of bad equation\n", i);
    558             } else {
    559                 stamp->status = PM_SUBTRACTION_STAMP_USED;
    560             }
     516
     517            stamp->status = PM_SUBTRACTION_STAMP_USED;
    561518
    562519            if (psTraceGetLevel("psModules.imcombine.equation") >= 10) {
     
    653610
    654611int pmSubtractionRejectStamps(psArray *stamps, const psImage *refImage, psImage *inImage,
    655                               psImage *subMask, const psVector *solution, int footprint, float sigmaRej,
    656                               const pmSubtractionKernels *kernels)
     612                              psImage *mask, psMaskType badStampMaskVal, const psVector *solution,
     613                              int footprint, float sigmaRej, const pmSubtractionKernels *kernels)
    657614{
    658615    PS_ASSERT_ARRAY_NON_NULL(stamps, -1);
     
    662619    PS_ASSERT_IMAGE_TYPE(inImage, PS_TYPE_F32, -1);
    663620    PS_ASSERT_IMAGES_SIZE_EQUAL(refImage, inImage, -1);
    664     PS_ASSERT_IMAGE_NON_EMPTY(subMask, -1);
    665     PS_ASSERT_IMAGE_TYPE(subMask, PS_TYPE_MASK, -1);
    666     PS_ASSERT_IMAGES_SIZE_EQUAL(refImage, subMask, -1);
     621    PS_ASSERT_IMAGE_NON_EMPTY(mask, -1);
     622    PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, -1);
     623    PS_ASSERT_IMAGES_SIZE_EQUAL(refImage, mask, -1);
    667624    PS_ASSERT_VECTOR_NON_NULL(solution, -1);
    668625    PS_ASSERT_VECTOR_TYPE(solution, PS_TYPE_F64, -1);
     
    707664                for (int x = footprint; x <= footprint; x++) {
    708665                    for (int k = 0; k < numKernels; k++) {
    709 #if 0
     666#ifdef CAN_PASS_STATIC_INLINE
    710667                        convolvedStamp->data.F32[y + footprint][x + footprint] +=
    711668                            convolvePixel(kernels, k, xStamp + x, yStamp + y, refImage, polyValues,
     
    753710        if (stamp->status == PM_SUBTRACTION_STAMP_USED && deviations->data.F32[i] > limit) {
    754711            // Mask out the stamp in the image so you it's not found again
    755             psTrace("psModules.imcombine", 3, "Clipping stamp %d\n", i);
     712            psTrace("psModules.imcombine", 3, "Rejecting stamp %d\n", i);
    756713            numRejected++;
    757714            for (int y = stamp->y - footprint; y <= stamp->y + footprint; y++) {
    758715                for (int x = stamp->x - footprint; x <= stamp->x + footprint; x++) {
    759                     subMask->data.PS_TYPE_MASK_DATA[y][x] |= PM_SUBTRACTION_MASK_REJ;
     716                    mask->data.PS_TYPE_MASK_DATA[y][x] |= badStampMaskVal;
    760717                }
    761718            }
     
    794751
    795752    // The appropriate kernel
    796 #if 0
     753#ifdef CAN_PASS_STATIC_INLINE
    797754    psKernel *kernel = solvedKernel(NULL, solution, kernels, polyValues, imageWeighting);
    798755#else
     
    810767
    811768bool pmSubtractionConvolve(psImage **outImage, psImage **outWeight, psImage **outMask,
    812                            const psImage *inImage, const psImage *inWeight, const psImage *subMask,
    813                            psMaskType blank, const psVector *solution, const pmSubtractionKernels *kernels)
     769                           const psImage *inImage, const psImage *inWeight, const psImage *inMask,
     770                           psMaskType maskVal, psMaskType blank,
     771                           const psVector *solution, const pmSubtractionKernels *kernels)
    814772{
    815773    PS_ASSERT_IMAGE_NON_NULL(inImage, false);
    816774    PS_ASSERT_IMAGE_TYPE(inImage, PS_TYPE_F32, false);
    817     if (subMask) {
    818         PS_ASSERT_IMAGE_NON_NULL(subMask, false);
    819         PS_ASSERT_IMAGE_TYPE(subMask, PS_TYPE_MASK, false);
    820         PS_ASSERT_IMAGES_SIZE_EQUAL(subMask, inImage, false);
     775    if (inMask) {
     776        PS_ASSERT_IMAGE_NON_NULL(inMask, false);
     777        PS_ASSERT_IMAGE_TYPE(inMask, PS_TYPE_MASK, false);
     778        PS_ASSERT_IMAGES_SIZE_EQUAL(inMask, inImage, false);
    821779    }
    822780    if (inWeight) {
     
    835793        PS_ASSERT_IMAGES_SIZE_EQUAL(*outMask, inImage, false);
    836794        PS_ASSERT_IMAGE_TYPE(*outMask, PS_TYPE_MASK, false);
    837         PS_ASSERT_IMAGE_NON_NULL(subMask, false);
     795        PS_ASSERT_IMAGE_NON_NULL(inMask, false);
    838796    }
    839797    if (outWeight && *outWeight) {
     
    865823    }
    866824    psImage *convMask = NULL;           // Convolved mask image
    867     if (outMask && subMask) {
     825    if (outMask && inMask) {
    868826        if (!*outMask) {
    869827            *outMask = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
     
    896854                                           2.0 * (float)(i + size - numCols/2.0) / (float)numCols,
    897855                                           2.0 * (float)(j + size - numRows/2.0) / (float)numRows);
    898 #if 0
     856#ifdef CAN_PASS_STATIC_INLINE
    899857            kernelImage = solvedKernel(kernelImage, solution, kernels, polyValues, imageWeighting);
    900858            if (inWeight) {
     
    914872
    915873                    // Check and propagate the kernel footprint, if required
    916                     if (subMask && (subMask->data.PS_TYPE_MASK_DATA[y][x] &
    917                                     (PM_SUBTRACTION_MASK_INPUT | PM_SUBTRACTION_MASK_CONVOLVE))) {
    918                         convMask->data.PS_TYPE_MASK_DATA[y][x] |= blank;
    919                         convImage->data.F32[y][x] = NAN;
    920                         if (inWeight) {
    921                             convWeight->data.F32[y][x] = NAN;
     874                    if (inMask) {
     875                        for (int v = -size; v <= size; v++) {
     876                            for (int u = -size; u <= size; u++) {
     877                                convMask->data.PS_TYPE_MASK_DATA[y][x] |=
     878                                    inMask->data.PS_TYPE_MASK_DATA[y + v][x + u];
     879                            }
    922880                        }
    923                         continue;
     881                        if (convMask->data.PS_TYPE_MASK_DATA[y][x] & maskVal) {
     882                            convImage->data.F32[y][x] = NAN;
     883                            if (inWeight) {
     884                                convWeight->data.F32[y][x] = NAN;
     885                            }
     886                            continue;
     887                        }
    924888                    }
    925889
Note: See TracChangeset for help on using the changeset viewer.