IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Aug 22, 2008, 12:45:36 PM (18 years ago)
Author:
Paul Price
Message:

Reworking the masking so as to avoid exploding the number of bad pixels in the convolved image. Introduced the bad/poor distinction. Bad pixels that are convolved now have a large 'poor' halo in the mask, with a smaller 'bad' halo. Got rid of the 'FOOTPRINT' mask value (internal subtraction mask): there's no need to convolve the mask in order to find out if a sprinkling of footprints are bad (not sure this is so efficient when a list of sources isn't supplied), and I needed the mask bits to signify the difference between 'bad' and 'poor'. Tested on a single subtraction, which seems to work.

File:
1 edited

Legend:

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

    r19148 r19164  
    249249    psImage *subConv = psImageSubset(convolved, psRegionSet(size, -size, size, -size)); // Cut off the edges
    250250
    251     if (threaded) {
    252         psMutexLock(target);
    253     }
    254     psImage *subTarget = psImageSubset(target, region); // Target for this subregion
    255     if (threaded) {
    256         psMutexUnlock(target);
    257     }
     251    int xMin = region.x0, xMax = region.x1, yMin = region.y0, yMax = region.y1; // Bounds of region
    258252    if (background != 0.0) {
    259         psBinaryOp(subTarget, subConv, "+", psScalarAlloc(background, PS_TYPE_F32));
     253        for (int yTarget = yMin, ySource = size; yTarget < yMax; yTarget++, ySource++) {
     254            for (int xTarget = xMin, xSource = size; xTarget < xMax; xTarget++, xSource++) {
     255                target->data.F32[yTarget][xTarget] = convolved->data.F32[ySource][xSource] + background;
     256            }
     257        }
    260258    } else {
    261         int numBytes = subTarget->numCols * PSELEMTYPE_SIZEOF(PS_TYPE_F32); // Number of bytes to copy
    262         for (int y = 0; y < subTarget->numRows; y++) {
    263             memcpy(subTarget->data.F32[y], subConv->data.F32[y], numBytes);
     259        int numBytes = (xMax - xMin) * PSELEMTYPE_SIZEOF(PS_TYPE_F32); // Number of bytes to copy
     260        for (int yTarget = yMin, ySource = size; yTarget < yMax; yTarget++, ySource++) {
     261            memcpy(&target->data.F32[yTarget][xMin], &convolved->data.F32[ySource][size], numBytes);
    264262        }
    265263    }
    266264    psFree(subConv);
    267265    psFree(convolved);
    268     if (threaded) {
    269         psMutexLock(target);
    270     }
    271     psFree(subTarget);
    272     if (threaded) {
    273         psMutexUnlock(target);
    274     }
    275266
    276267    return;
     
    291282            for (int v = -size; v <= size; v++) {
    292283                for (int u = -size; u <= size; u++) {
    293                     target->data.F32[y][x] += kernel->kernel[v][u] *
    294                         image->data.F32[y - v][x - u];
     284                    target->data.F32[y][x] += kernel->kernel[v][u] * image->data.F32[y - v][x - u];
    295285                }
    296286            }
     
    303293static inline void convolveRegion(psImage *convImage, // Convolved image (output)
    304294                                  psImage *convWeight, // Convolved weight map (output), or NULL
     295                                  psImage *convMask, // Convolve mask (output), or NULL
    305296                                  psKernel **kernelImage, // Convolution kernel for the image
    306297                                  psKernel **kernelWeight, // Convolution kernel for the weight map, or NULL
     
    308299                                  psImage *weight, // Weight map to convolve, or NULL
    309300                                  psImage *subMask, // Subtraction mask
    310                                   psMaskType maskVal, // Mask value to apply in convolution
    311301                                  const pmSubtractionKernels *kernels, // Kernels
    312302                                  psImage *polyValues, // Polynomial values
    313303                                  float background, // Background value to apply
    314304                                  psRegion region, // Region to convolve
     305                                  float poorFrac, // Fraction for "poor"
    315306                                  bool useFFT,  // Use FFT to convolve?
    316307                                  bool wantDual // Want the dual convolution?
     
    318309{
    319310    *kernelImage = solvedKernel(*kernelImage, kernels, polyValues, wantDual);
    320     if (weight) {
     311    if (weight || subMask) {
    321312        *kernelWeight = varianceKernel(*kernelWeight, *kernelImage);
    322313    }
    323314
     315    psMaskType maskSource;              // Mask these values when
     316    psMaskType maskTarget;              // Set this mask value when convolving
     317    if (kernels->mode == PM_SUBTRACTION_MODE_1 || (kernels->mode == PM_SUBTRACTION_MODE_DUAL && !wantDual)) {
     318        maskSource = PM_SUBTRACTION_MASK_BAD_1;
     319        maskTarget = PM_SUBTRACTION_MASK_CONVOLVE_BAD_1;
     320    } else {
     321        maskSource = PM_SUBTRACTION_MASK_BAD_2;
     322        maskTarget = PM_SUBTRACTION_MASK_CONVOLVE_BAD_2;
     323    }
     324
     325    // Convolve the image and weight
    324326    if (useFFT) {
    325327        // Use Fast Fourier Transform to do the convolution
    326328        // This provides a big speed-up for large kernels
    327 
    328         convolveFFT(convImage, image, subMask, maskVal, *kernelImage, region, background, kernels->size);
     329        convolveFFT(convImage, image, subMask, maskSource, *kernelImage, region, background, kernels->size);
    329330        if (weight) {
    330             convolveFFT(convWeight, weight, subMask, maskVal, *kernelWeight, region, 0.0, kernels->size);
     331            convolveFFT(convWeight, weight, subMask, maskSource, *kernelWeight, region, 0.0, kernels->size);
    331332        }
    332333    } else {
     
    334335        if (weight) {
    335336            convolveDirect(convWeight, weight, *kernelWeight, region, 0.0, kernels->size);
     337        }
     338    }
     339
     340    // Convolve the mask for bad pixels
     341    if (subMask && convMask) {
     342        psKernel *kernel = *kernelWeight; // Kernel of interest
     343        int xMin = kernel->xMin, xMax = kernel->xMax, yMin = kernel->yMin, yMax = kernel->yMax; // Bounds
     344
     345        // Determine the thresholds
     346        double sumKernel2 = 0.0;        // Sum of the kernel-squared
     347        for (int y = yMin; y <= yMax; y++) {
     348            for (int x = xMin; x <= xMax; x++) {
     349                sumKernel2 += kernel->kernel[y][x];
     350            }
     351        }
     352        float threshold = sumKernel2 * poorFrac; // Threshold between poor and bad
     353
     354        // Get bounds of threshold region
     355        // Start with the entire kernel, and keep reducing the size of the box until it drops below threshold
     356        int box = kernels->size;                    // Size of box with bad pixels
     357        for (double sumBox = sumKernel2; box > 0; box--) {
     358            for (int x = -box; x <= box; x++) {
     359                sumBox -= kernel->kernel[-box][x] + kernel->kernel[box][x];
     360            }
     361            for (int y = -box + 1; y <= box - 1; y++) {
     362                // Note: not doing corners
     363                sumBox -= kernel->kernel[y][-box] + kernel->kernel[y][box];
     364            }
     365            if (sumBox < threshold) {
     366                break;
     367            }
     368        }
     369
     370        if (box > 0) {
     371            bool threaded = pmSubtractionThreaded(); // Are we running threaded?
     372            if (threaded) {
     373                psMutexLock(subMask);
     374            }
     375            psImage *image = psImageSubset(subMask, psRegionSet(region.x0 + xMin, region.x1 + xMax,
     376                                                                region.y0 + yMin, region.y1 + yMax));
     377            if (threaded) {
     378                psMutexUnlock(subMask);
     379            }
     380
     381            psImage *convolved = psImageConvolveMask(NULL, image, maskSource, maskTarget,
     382                                                     -box, box, -box, box); // Convolved subtraction mask
     383
     384            if (threaded) {
     385                psMutexLock(subMask);
     386            }
     387            psFree(image);
     388            if (threaded) {
     389                psMutexUnlock(subMask);
     390            }
     391
     392            int colMin = region.x0, colMax = region.x1, rowMin = region.y0, rowMax = region.y1; // Bounds
     393            int numBytes = (colMax - colMin) * PSELEMTYPE_SIZEOF(PS_TYPE_MASK); // Number of bytes to copy
     394
     395            // Since we're copying back into the source, we need to lock
     396            if (threaded) {
     397                psMutexLock(subMask);
     398            }
     399            for (int yTarget = rowMin, ySource = -yMin; yTarget < rowMax; yTarget++, ySource++) {
     400                memcpy(&subMask->data.PS_TYPE_MASK_DATA[yTarget][colMin],
     401                       &convolved->data.PS_TYPE_MASK_DATA[ySource][-xMin], numBytes);
     402            }
     403            if (threaded) {
     404                psMutexUnlock(subMask);
     405            }
     406
     407            // No need to lock: we own this
     408            psFree(convolved);
    336409        }
    337410    }
     
    753826
    754827// XXX Put kernelImage, kernelWeight and polyValues on thread-dependent data
    755 static bool subtractionConvolvePatch(int numCols, int numRows, int x0, int y0,
    756                                      pmReadout *out1, pmReadout *out2, psImage *convMask,
    757                                      const pmReadout *ro1, const pmReadout *ro2, psImage *subMask,
    758                                      psMaskType blank, psMaskType maskSource, psMaskType maskTarget,
    759                                      const psRegion *region, const pmSubtractionKernels *kernels,
    760                                      bool doBG, bool useFFT)
     828static bool subtractionConvolvePatch(int numCols, int numRows, // Size of image
     829                                     int x0, int y0, // Offsets for image
     830                                     pmReadout *out1, pmReadout *out2, // Output readouts
     831                                     psImage *convMask, // Output convolved mask
     832                                     const pmReadout *ro1, const pmReadout *ro2, // Input readouts
     833                                     psImage *subMask, // Input subtraction mask
     834                                     psMaskType maskBad, // Mask value to give bad pixels
     835                                     psMaskType maskPoor, // Mask value to give poor pixels
     836                                     float poorFrac, // Fraction for "poor"
     837                                     const psRegion *region, // Patch to convolve
     838                                     const pmSubtractionKernels *kernels, // Kernels
     839                                     bool doBG, // Add in background when convolving?
     840                                     bool useFFT // Use FFT to do the convolution?
     841    )
    761842{
    762843    int size = kernels->size;           // Half-size of kernel
     
    782863
    783864    if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
    784         convolveRegion(out1->image, out1->weight, &kernelImage, &kernelWeight, ro1->image, ro1->weight,
    785                        subMask, maskSource, kernels, polyValues, background, *region, useFFT,
    786                        false);
     865        convolveRegion(out1->image, out1->weight, convMask, &kernelImage, &kernelWeight,
     866                       ro1->image, ro1->weight, subMask, kernels, polyValues, background,
     867                       *region, poorFrac, useFFT, false);
    787868    }
    788869    if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
    789         convolveRegion(out2->image, out2->weight, &kernelImage, &kernelWeight, ro2->image, ro2->weight,
    790                        subMask, maskSource, kernels, polyValues, background, *region, useFFT,
    791                        kernels->mode == PM_SUBTRACTION_MODE_DUAL);
     870        convolveRegion(out2->image, out2->weight, convMask, &kernelImage, &kernelWeight,
     871                       ro2->image, ro2->weight, subMask, kernels, polyValues, background,
     872                       *region, poorFrac, useFFT, kernels->mode == PM_SUBTRACTION_MODE_DUAL);
    792873    }
    793874
     
    796877    psFree(polyValues);
    797878
    798     // Propagate the mask
     879    // Propagate the subtraction mask
    799880    if (subMask) {
    800881        psMaskType **target = convMask->data.PS_TYPE_MASK_DATA; // Target mask
    801882        psMaskType **source = subMask->data.PS_TYPE_MASK_DATA; // Source mask
    802883
     884        psMaskType poor, bad;           // Mask value for "poor" and "bad" pixels in subtraction mask
     885        switch (kernels->mode) {
     886          case PM_SUBTRACTION_MODE_1:
     887            poor = PM_SUBTRACTION_MASK_CONVOLVE_1;
     888            bad = PM_SUBTRACTION_MASK_CONVOLVE_BAD_1 | PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_BAD_2;
     889            break;
     890          case PM_SUBTRACTION_MODE_2:
     891            poor = PM_SUBTRACTION_MASK_CONVOLVE_2;
     892            bad = PM_SUBTRACTION_MASK_CONVOLVE_BAD_2 | PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_BAD_2;
     893            break;
     894          case PM_SUBTRACTION_MODE_DUAL:
     895            poor = PM_SUBTRACTION_MASK_CONVOLVE_1 | PM_SUBTRACTION_MASK_CONVOLVE_1;
     896            bad = PM_SUBTRACTION_MASK_CONVOLVE_BAD_1 | PM_SUBTRACTION_MASK_CONVOLVE_BAD_2 |
     897                PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_BAD_2;
     898            break;
     899          default:
     900            psAbort("Unrecognised subtraction mode: %x", kernels->mode);
     901        }
     902
    803903        for (int y = yMin; y < yMax; y++) {
    804904            for (int x = xMin; x < xMax; x++) {
    805                 if (source[y][x] & maskTarget) {
    806                     target[y][x] |= blank;
     905                // Pixels marked as "bad" shouldn't also be marked as "poor"
     906                if (source[y][x] & bad) {
     907                    target[y][x] |= maskBad;
     908                } else if (source[y][x] & poor){
     909                    target[y][x] |= maskPoor;
    807910                }
    808911            }
     
    848951    const pmReadout *ro2 = args->data[8]; // Input readout 2
    849952    psImage *subMask = args->data[9]; // Subtraction mask
    850     psMaskType blank = PS_SCALAR_VALUE(args->data[10], U8); // Output mask value
    851     psMaskType maskSource = PS_SCALAR_VALUE(args->data[11], U8); // Mask value corresponding to source image
    852     psMaskType maskTarget = PS_SCALAR_VALUE(args->data[12], U8); // Mask value corresponding to target image
     953    psMaskType maskBad = PS_SCALAR_VALUE(args->data[10], U8); // Output mask value for bad pixels
     954    psMaskType maskPoor = PS_SCALAR_VALUE(args->data[11], U8); // Output mask value for poor pixels
     955    float poorFrac = PS_SCALAR_VALUE(args->data[12], F32); // Fraction for "poor"
    853956    const psRegion *region = args->data[13]; // Region to convolve
    854957    const pmSubtractionKernels *kernels = args->data[14]; // Kernels
     
    856959    bool useFFT = PS_SCALAR_VALUE(args->data[16], U8); // Use FFT for convolution?
    857960
    858     return subtractionConvolvePatch(numCols, numRows, x0, y0, out1, out2, convMask,
    859                                     ro1, ro2, subMask, blank, maskSource, maskTarget,
    860                                     region, kernels, doBG, useFFT);
     961    return subtractionConvolvePatch(numCols, numRows, x0, y0, out1, out2, convMask, ro1, ro2, subMask,
     962                                    maskBad, maskPoor, poorFrac, region, kernels, doBG, useFFT);
    861963}
    862964
    863965bool pmSubtractionConvolve(pmReadout *out1, pmReadout *out2, const pmReadout *ro1, const pmReadout *ro2,
    864                            psImage *subMask, psMaskType blank, const psRegion *region,
    865                            const pmSubtractionKernels *kernels, bool doBG, bool useFFT)
     966                           psImage *subMask, psMaskType maskBad, psMaskType maskPoor, float poorFrac,
     967                           const psRegion *region, const pmSubtractionKernels *kernels,
     968                           bool doBG, bool useFFT)
    866969{
    867970    int numCols = 0, numRows = 0;       // Image dimensions
     
    9981101        yMin = PS_MAX(region->y0, yMin);
    9991102        yMax = PS_MIN(region->y1, yMax);
    1000     }
    1001 
    1002     psMaskType maskSource;              // Mask these pixels when convolving
    1003     psMaskType maskTarget;              // Mark these pixels as bad when propagating the subtractionMask
    1004     switch (kernels->mode) {
    1005       case PM_SUBTRACTION_MODE_1:
    1006         maskSource = PM_SUBTRACTION_MASK_BAD_1;
    1007         maskTarget = PM_SUBTRACTION_MASK_BAD_2 | PM_SUBTRACTION_MASK_CONVOLVE_1;
    1008         break;
    1009       case PM_SUBTRACTION_MODE_2:
    1010         maskSource = PM_SUBTRACTION_MASK_BAD_2;
    1011         maskTarget = PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_CONVOLVE_2;
    1012         break;
    1013       case PM_SUBTRACTION_MODE_DUAL:
    1014         maskSource = PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_BAD_2;
    1015         maskTarget = PM_SUBTRACTION_MASK_CONVOLVE_1 | PM_SUBTRACTION_MASK_CONVOLVE_2;
    1016         break;
    1017       default:
    1018         psAbort("Unsupported subtraction mode: %x", kernels->mode);
    10191103    }
    10201104
     
    10451129                psArrayAdd(args, 1, (pmReadout*)ro2); // Casting away const
    10461130                psArrayAdd(args, 1, (psImage*)subMask); // Casting away const
    1047                 PS_ARRAY_ADD_SCALAR(args, blank, PS_TYPE_U8);
    1048                 PS_ARRAY_ADD_SCALAR(args, maskSource, PS_TYPE_U8);
    1049                 PS_ARRAY_ADD_SCALAR(args, maskTarget, PS_TYPE_U8);
     1131                PS_ARRAY_ADD_SCALAR(args, maskBad, PS_TYPE_U8);
     1132                PS_ARRAY_ADD_SCALAR(args, maskPoor, PS_TYPE_U8);
     1133                PS_ARRAY_ADD_SCALAR(args, poorFrac, PS_TYPE_F32);
    10501134                psArrayAdd(args, 1, subRegion);
    10511135                psArrayAdd(args, 1, (pmSubtractionKernels*)kernels); // Casting away const
     
    10601144            } else {
    10611145                subtractionConvolvePatch(numCols, numRows, x0, y0, out1, out2, convMask, ro1, ro2, subMask,
    1062                                          blank, maskSource, maskTarget, subRegion, kernels, doBG, useFFT);
     1146                                         maskBad, maskPoor, poorFrac, subRegion, kernels, doBG, useFFT);
    10631147            }
    10641148            psFree(subRegion);
Note: See TracChangeset for help on using the changeset viewer.