IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Aug 28, 2008, 6:04:19 PM (18 years ago)
Author:
Paul Price
Message:

We want a bad/poor mask distinction in the mask convolution for stacking. Again, otherwise the number of bad pixels just explodes. Since convolving a mask with the PSF-matching kernel is something we want to do in both stack rejection and normal convolution, pulled the code that determines the size of the 'bad' region into a separate function in pmSubtraction.c. Then pmStackReject basically does the same thing that's happening in pmSubtractionConvolve/convolveRegion: go through the image by footprints, convolve the footprint and plug the result back in to the original image. Small API change for pmStackReject. This is very effective in reducing the amount of bad pixels in the stacked image.

File:
1 edited

Legend:

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

    r19164 r19282  
    44
    55#include <stdio.h>
     6#include <string.h>
    67#include <pslib.h>
    78
     
    1415
    1516
    16 psPixels *pmStackReject(const psPixels *in, const psRegion *valid, float threshold,
    17                         const psArray *subRegions, const psArray *kernels)
     17psPixels *pmStackReject(const psPixels *in, int numCols, int numRows, float threshold, float poorFrac,
     18                        const psArray *subRegions, const psArray *subKernels)
    1819{
    1920    PS_ASSERT_PIXELS_NON_NULL(in, NULL);
     
    2122    PS_ASSERT_FLOAT_LESS_THAN_OR_EQUAL(threshold, 1.0, NULL);
    2223    PS_ASSERT_ARRAY_NON_NULL(subRegions, NULL);
    23     PS_ASSERT_ARRAY_NON_NULL(kernels, NULL);
    24     PS_ASSERT_ARRAYS_SIZE_EQUAL(subRegions, kernels, NULL);
     24    PS_ASSERT_ARRAY_NON_NULL(subKernels, NULL);
     25    PS_ASSERT_ARRAYS_SIZE_EQUAL(subRegions, subKernels, NULL);
    2526
    2627    // Trivial case
     
    2930    }
    3031
    31     // Get the original image size
    32     int numRegions = subRegions->n;        // Number of regions
    33     int numCols = 0, numRows = 0;       // Size of original image
    34     int minCols = INT_MAX, minRows = INT_MAX; // Minimum coordinate for image
     32    // Check consistency of kernels
     33    int numRegions = subRegions->n;     // Number of regions
    3534    int size = 0;                       // Size of kernel
    3635    for (int i = 0; i < numRegions; i++) {
    37         psRegion *subRegion = subRegions->data[i]; // Region of interest
    38         if (subRegion->x0 < minCols) {
    39             minCols = subRegion->x0;
    40         }
    41         if (subRegion->y0 < minRows) {
    42             minRows = subRegion->y0;
    43         }
    44         if (subRegion->x1 > numCols) {
    45             numCols = subRegion->x1;
    46         }
    47         if (subRegion->y1 > numRows) {
    48             numRows = subRegion->y1;
    49         }
    50 
    51         pmSubtractionKernels *kernel = kernels->data[i]; // Kernel of interest
     36        pmSubtractionKernels *kernels = subKernels->data[i]; // Kernel of interest
    5237        if (size == 0) {
    53             size = kernel->size;
    54         } else if (kernel->size != size) {
     38            size = kernels->size;
     39        } else if (kernels->size != size) {
    5540            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Kernel sizes are not identical: %d vs %d",
    56                     size, kernel->size);
     41                    size, kernels->size);
    5742            return NULL;
    5843        }
    5944    }
    6045
    61     // Adjust the size for the size of the subimage
    62     if (valid) {
    63         minCols = PS_MAX(valid->x0, minCols);
    64         minRows = PS_MAX(valid->y0, minRows);
    65         numCols = PS_MIN(valid->x1, numCols);
    66         numRows = PS_MIN(valid->y1, numRows);
    67     }
    68     psTrace("psModules.imcombine", 1, "Rejecting [%d:%d,%d:%d]\n", minCols, numCols, minRows, numRows);
    69 
    70     psImage *mask = psPixelsToMask(NULL, in, psRegionSet(minCols, numCols - 1, minRows, numRows - 1),
    71                                    0x01); // Mask
     46    psImage *mask = psPixelsToMask(NULL, in, psRegionSet(0, numCols - 1, 0, numRows - 1), 0x01); // Mask
    7247    psImage *image = psImageCopy(NULL, mask, PS_TYPE_F32); // Floating-point version, so we can convolve
    7348    psFree(mask);
     
    7752    pmReadout *inRO = pmReadoutAlloc(NULL); // Readout with input image
    7853    inRO->image = image;
    79     inRO->col0 = minCols;
    80     inRO->row0 = minRows;
    8154    for (int i = 0; i < numRegions; i++) {
    8255        psRegion *region = subRegions->data[i]; // Region of interest
    83         if (valid && (region->x0 > valid->x1 || region->x1 < valid->x0 ||
    84                       region->y0 > valid->y1 || region->y1 < valid->y0)) {
    85             // Region is outside of our sub-image
    86             continue;
    87         }
    88         pmSubtractionKernels *kernel = kernels->data[i]; // Kernel of interest
    89         if (!pmSubtractionConvolve(convRO, NULL, inRO, NULL, NULL, 0, 0, 1.0, region, kernel, false, true)) {
     56        pmSubtractionKernels *kernels = subKernels->data[i]; // Kernel of interest
     57        if (!pmSubtractionConvolve(convRO, NULL, inRO, NULL, NULL, 0, 0, 1.0, region, kernels, false, true)) {
    9058            psError(PS_ERR_UNKNOWN, false, "Unable to convolve mask image in region %d.", i);
    9159            psFree(convRO);
     
    9866
    9967        // Image of the kernel at the centre of the region
    100         float xNorm = (region->x0 + 0.5 * (region->x1 - region->x0) - kernel->numCols/2.0) /
    101             (float)kernel->numCols;
    102         float yNorm = (region->y0 + 0.5 * (region->y1 - region->y0) - kernel->numRows/2.0) /
    103             (float)kernel->numRows;
    104         psImage *image = pmSubtractionKernelImage(kernel, xNorm, yNorm, false);
     68        float xNorm = (region->x0 + 0.5 * (region->x1 - region->x0) - kernels->numCols/2.0) /
     69            (float)kernels->numCols;
     70        float yNorm = (region->y0 + 0.5 * (region->y1 - region->y0) - kernels->numRows/2.0) /
     71            (float)kernels->numRows;
     72        psImage *image = pmSubtractionKernelImage(kernels, xNorm, yNorm, false);
    10573        if (!image) {
    10674            psError(PS_ERR_UNKNOWN, false, "Unable to generate kernel image.");
     
    11886
    11987        // Range for normalisation
    120         int yMin = PS_MAX(minRows, region->y0) - inRO->row0;
    121         int yMax = PS_MIN(numRows - 1, region->y1) - inRO->row0;
    122         int xMin = PS_MAX(minCols, region->x0) - inRO->col0;
    123         int xMax = PS_MIN(numCols - 1, region->x1) - inRO->col0;
     88        int xMin = PS_MAX(0, region->x0), xMax = PS_MIN(numCols - 1, region->x1);
     89        int yMin = PS_MAX(0, region->y0), yMax = PS_MIN(numRows - 1, region->y1);
    12490        psTrace("psModules.imcombine", 2, "Normalising convolved mask image by %f over %d:%d,%d:%d\n",
    12591                sum, xMin, xMax, yMin, yMax);
     92        sum = 1.0 / sum;
    12693        for (int y = yMin; y <= yMax; y++) {
    12794            for (int x = xMin; x <= xMax; x++) {
    128                 convRO->image->data.F32[y][x] /= sum;
     95                convRO->image->data.F32[y][x] *= sum;
    12996            }
    13097        }
     
    152119        for (int x = size; x < convolved->numCols - size; x++) {
    153120            if (convolved->data.F32[y][x] > threshold) {
    154                 // Pixel coordinates in "bad" correspond to the full image
    155                 bad = psPixelsAdd(bad, PIXEL_LIST_BUFFER, x + minCols, y + minRows);
     121                bad = psPixelsAdd(bad, bad->nalloc, x, y);
    156122            }
    157123        }
     
    160126
    161127    // Now, grow the mask to include everything that touches a bad pixel in the convolution
    162     int x0 = minCols, y0 = minRows;     // Offset for mask image
    163     mask = psPixelsToMask(NULL, bad, psRegionSet(x0, numCols - 1, y0, numRows - 1), 0xff);
    164     for (int i = 0; i < bad->n; i++) {
    165         int xPix = bad->data[i].x - x0, yPix = bad->data[i].y - y0; // Coordinates in frame of mask image
    166         // Convolution limits
    167         int xMin = PS_MAX(xPix - size, 0);
    168         int xMax = PS_MIN(xPix + size, mask->numCols - 1);
    169         int yMin = PS_MAX(yPix - size, 0);
    170         int yMax = PS_MIN(yPix + size, mask->numRows - 1);
    171         for (int y = yMin; y <= yMax; y++) {
    172             for (int x = xMin; x <= xMax; x++) {
    173                 assert(x < mask->numCols && y < mask->numRows);
    174                 mask->data.PS_TYPE_MASK_DATA[y][x] = 0xff;
     128    // Mask values:
     129    // 0x0f: we think this is bad
     130    // 0xf0: this is within the convolution kernel of a bad pixel
     131    mask = psPixelsToMask(NULL, bad, psRegionSet(0, numCols - 1, 0, numRows - 1), 0x0f);
     132    for (int i = 0; i < subRegions->n; i++) {
     133        psRegion *region = subRegions->data[i]; // Subtraction region
     134        pmSubtractionKernels *kernels = subKernels->data[i]; // Subtraction kernel
     135
     136        int size = kernels->size;           // Half-size of kernel
     137        int fullSize = 2 * size + 1;        // Full size of kernel
     138
     139        // Get region for convolution: [xMin:xMax,yMin:yMax]
     140        int xMin = PS_MAX(region->x0, size), xMax = PS_MIN(region->x1, numCols - size);
     141        int yMin = PS_MAX(region->y0, size), yMax = PS_MIN(region->y1, numRows - size);
     142
     143        psImage *polyValues = NULL;     // Pre-calculated polynomial values
     144        for (int j = yMin; j < yMax; j += fullSize) {
     145            int ySubMax = PS_MIN(j + fullSize, yMax); // Range for subregion of interest
     146            for (int i = xMin; i < xMax; i += fullSize) {
     147                int xSubMax = PS_MIN(i + fullSize, xMax); // Range for subregion of interest
     148
     149                polyValues = p_pmSubtractionPolynomialFromCoords(polyValues, kernels, numCols, numRows,
     150                                                                 i + size + 1, j + size + 1);
     151                int box = p_pmSubtractionBadRadius(NULL, kernels, polyValues,
     152                                                   false, poorFrac); // Radius of bad box
     153                if (box > 0) {
     154                    // Convolve a subimage, then stick it in the original
     155                    psImage *subMask = psImageSubset(mask, psRegionSet(i - box, xSubMax + box,
     156                                                                       j - box, ySubMax + box)); // Subimage
     157                    psImage *convolved = psImageConvolveMask(NULL, subMask, 0x0f, 0xf0,
     158                                                             -box, box, -box, box); // Convolved mask
     159                    psFree(subMask);
     160
     161                    int numBytes = (xSubMax - i) * PSELEMTYPE_SIZEOF(PS_TYPE_MASK); // Number of bytes to copy
     162                    psAssert(convolved->numCols - 2 * box == xSubMax - i, "Bad number of columns");
     163                    psAssert(convolved->numRows - 2 * box == ySubMax - j, "Bad number of rows");
     164
     165                    for (int yTarget = j, ySource = box; yTarget < ySubMax; yTarget++, ySource++) {
     166                        memcpy(&mask->data.PS_TYPE_MASK_DATA[yTarget][i],
     167                               &convolved->data.PS_TYPE_MASK_DATA[ySource][box], numBytes);
     168                    }
     169                    psFree(convolved);
     170                }
    175171            }
    176172        }
     173        psFree(polyValues);
    177174    }
    178175    bad = psPixelsFromMask(bad, mask, 0xff);
    179     psFree(mask);
    180 
    181     // Convert coordinates to frame of original image
    182     for (int i = 0; i < bad->n; i++) {
    183         int x = bad->data[i].x + x0;
    184         int y = bad->data[i].y + y0;
    185         if (x < 0 || x >= numCols || y < 0 || y >= numRows) {
    186             psWarning("Bad pixel coordinate %d: %d,%d --- ignored.",
    187                       i, x, y);
    188             continue;
    189         }
    190         bad->data[i].x = x;
    191         bad->data[i].y = y;
    192     }
    193176
    194177    return bad;
Note: See TracChangeset for help on using the changeset viewer.