IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 15321


Ignore:
Timestamp:
Oct 16, 2007, 3:49:12 PM (19 years ago)
Author:
Paul Price
Message:

Expanding psImageConvolveMaskDirect and psImageConvolveMaskFFT to allow convolution in-place, and expanding operations.

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

Legend:

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

    r15320 r15321  
    77/// @author Eugene Magnier, IfA
    88///
    9 /// @version $Revision: 1.58 $ $Name: not supported by cvs2svn $
    10 /// @date $Date: 2007-10-16 23:31:03 $
     9/// @version $Revision: 1.59 $ $Name: not supported by cvs2svn $
     10/// @date $Date: 2007-10-17 01:49:12 $
    1111///
    1212/// Copyright 2004-2007 Institute for Astronomy, University of Hawaii
     
    6161{
    6262    // Check the inputs to make sure max > min; if not, switch.
     63    // following is explicitly spelled out in the SDRS as a requirement
    6364    if (yMin > yMax) {
    64         psLogMsg(__func__, PS_LOG_WARN,
    65                  "Specified yMin, %d, was greater than yMax, %d.  Values swapped.",
     65        psWarning("Specified yMin, %d, was greater than yMax, %d.  Values swapped.",
    6666                 yMin, yMax);
    6767
     
    7070        yMax = temp;
    7171    }
    72 
    73     // following is explicitly spelled out in the SDRS as a requirement
    7472    if (xMin > xMax) {
    75         psLogMsg(__func__, PS_LOG_WARN,
    76                  "Specified xMin, %d, was greater than xMax, %d.  Values swapped.",
     73        psWarning("Specified xMin, %d, was greater than xMax, %d.  Values swapped.",
    7774                 xMin, xMax);
    7875
     
    313310}
    314311
    315 psImage *psImageConvolveMaskDirect(const psImage *mask, psMaskType maskVal, const psKernel *kernel)
     312psImage *psImageConvolveMaskDirect(psImage *out, const psImage *mask, psMaskType maskVal,
     313                                   psMaskType setVal, int xMin, int xMax, int yMin, int yMax)
    316314{
    317315    PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
    318316    PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL);
    319     PS_ASSERT_PTR_NON_NULL(kernel, NULL);
    320     PS_ASSERT_PTR_NON_NULL(kernel->kernel, NULL);
    321 
    322     // Pull out kernel parameters, for convenience
    323     int xMin = kernel->xMin;
    324     int xMax = kernel->xMax;
    325     int yMin = kernel->yMin;
    326     int yMax = kernel->yMax;
     317    if (out == mask && ((maskVal & setVal) || !setVal)) {
     318        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     319                "Can't convolve mask in-place if values to set contains values to convolve.");
     320        return NULL;
     321    }
     322
     323    if (yMin > yMax) {
     324        psWarning("Specified yMin, %d, was greater than yMax, %d.  Values swapped.",
     325                 yMin, yMax);
     326
     327        int temp = yMin;
     328        yMin = yMax;
     329        yMax = temp;
     330    }
     331    if (xMin > xMax) {
     332        psWarning("Specified xMin, %d, was greater than xMax, %d.  Values swapped.",
     333                 xMin, xMax);
     334
     335        int temp = xMin;
     336        xMin = xMax;
     337        xMax = temp;
     338    }
    327339
    328340    int numRows = mask->numRows;        // Number of rows
    329341    int numCols = mask->numCols;        // Number of columns
    330342
    331     psImage *out = psImageAlloc(numCols, numRows, PS_TYPE_MASK); // Output mask
     343    if (!out) {
     344        // Propagate the non-masked values
     345        out = (psImage*)psBinaryOp(NULL, (const psPtr)mask, "&", psScalarAlloc(~maskVal, PS_TYPE_MASK));
     346    }
    332347
    333348    // Dereference mask images
     
    335350    psMaskType **outData = out->data.PS_TYPE_MASK_DATA;
    336351
    337     // Propagate the non-masked values
    338     for (int row = 0; row < numRows; row++) {
    339         for (int col = 0; col < numCols; col++) {
    340             outData[row][col] = maskData[row][col] & ~maskVal;
    341         }
    342     }
    343 
    344     for (int row = 0; row < numRows; row++) {
    345         for (int col = 0; col < numCols; col++) {
    346             if (maskData[row][col] & maskVal) {
    347                 // It's already masked --- move on
    348                 continue;
    349             }
    350             psMaskType pixel = 0;       // New pixel value
    351             for (int kRow = PS_MAX(yMin, -row); kRow <= PS_MIN(yMax, numRows - row - 1); kRow++) {
    352                 for (int kCol = PS_MAX(xMin, -col); kCol <= PS_MIN(xMax, numCols - col - 1); kCol++) {
    353                     pixel |= maskData[row + kRow][col + kCol] & maskVal;
     352    if (setVal) {
     353        // Grow any pixels matching maskVal, setting setVal
     354        for (int row = 0; row < numRows; row++) {
     355            for (int col = 0; col < numCols; col++) {
     356                if (maskData[row][col] & maskVal) {
     357                    for (int kRow = PS_MAX(yMin, -row); kRow <= PS_MIN(yMax, numRows - row - 1); kRow++) {
     358                        for (int kCol = PS_MAX(xMin, -col); kCol <= PS_MIN(xMax, numCols - col - 1); kCol++) {
     359                            outData[row + kRow][col + kCol] |= setVal;
     360                        }
     361                    }
    354362                }
    355363            }
    356             outData[row][col] |= pixel;
     364        }
     365    } else {
     366        // Each pixel receives any maskVal bits set within the convolution window
     367        for (int row = 0; row < numRows; row++) {
     368            for (int col = 0; col < numCols; col++) {
     369                psMaskType pixel = outData[row][col]; // Pixel value to set
     370                if (pixel & maskVal) {
     371                    // Already done this one
     372                    continue;
     373                }
     374                for (int kRow = PS_MAX(yMin, -row); kRow <= PS_MIN(yMax, numRows - row - 1); kRow++) {
     375                    for (int kCol = PS_MAX(xMin, -col); kCol <= PS_MIN(xMax, numCols - col - 1); kCol++) {
     376                        pixel |= maskData[row][col] & maskVal;
     377                    }
     378                }
     379                outData[row][col] = pixel;
     380            }
    357381        }
    358382    }
     
    494518
    495519
    496 psImage *psImageConvolveMaskFFT(const psImage *mask, psMaskType maskVal, const psKernel *kernel, float thresh)
     520psImage *psImageConvolveMaskFFT(psImage *out, const psImage *mask, psMaskType maskVal,
     521                                psMaskType setVal, int xMin, int xMax, int yMin, int yMax, float thresh)
    497522{
    498523    PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
    499524    PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL);
    500     PS_ASSERT_PTR_NON_NULL(kernel, NULL);
    501     PS_ASSERT_PTR_NON_NULL(kernel->kernel, NULL);
    502525    PS_ASSERT_FLOAT_LARGER_THAN(thresh, 0.0, NULL);
    503526    PS_ASSERT_FLOAT_LESS_THAN(thresh, 1.0, NULL);
     527    if (out == mask && (maskVal & setVal)) {
     528        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     529                "Can't convolve mask in-place if values to set contains values to convolve.");
     530        return NULL;
     531    }
     532
     533    if (yMin > yMax) {
     534        psWarning("Specified yMin, %d, was greater than yMax, %d.  Values swapped.",
     535                 yMin, yMax);
     536
     537        int temp = yMin;
     538        yMin = yMax;
     539        yMax = temp;
     540    }
     541    if (xMin > xMax) {
     542        psWarning("Specified xMin, %d, was greater than xMax, %d.  Values swapped.",
     543                 xMin, xMax);
     544
     545        int temp = xMin;
     546        xMin = xMax;
     547        xMax = temp;
     548    }
    504549
    505550    int numRows = mask->numRows, numCols = mask->numCols; // Size of image
    506551
    507     psImage *onoff = (psImage*)psBinaryOp(NULL, (const psPtr)mask, "&", // Casting away const so I can use
    508                                           psScalarAlloc(maskVal, PS_TYPE_MASK)); // Pixels on or off
    509     psImage *copy = psImageCopy(NULL, onoff, PS_TYPE_F32); // Floating-point copy
    510     psImage *convolved = psImageConvolveFFT(copy, NULL, 0, kernel, 0.0);
    511     psFree(copy);
    512 
    513     thresh *= maskVal;
     552    if (!psMemIncrRefCounter(out)) {
     553        out = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
     554    }
     555
     556    psImage *onoff = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Pixels on or off
     557    psImageInit(onoff, 0);
    514558    for (int y = 0; y < numRows; y++) {
    515559        for (int x = 0; x < numCols; x++) {
    516             onoff->data.PS_TYPE_MASK_DATA[y][x] = (convolved->data.F32[y][x] >= thresh) ?
    517                 (mask->data.PS_TYPE_MASK_DATA[y][x] | maskVal) : mask->data.PS_TYPE_MASK_DATA[y][x];
     560            if (mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal) {
     561                onoff->data.F32[y][x] = 1.0;
     562            }
     563        }
     564    }
     565
     566    psKernel *kernel = psKernelAlloc(xMin, xMax, yMin, yMax);
     567    psImageInit(kernel->image, 1.0);
     568    psImage *convolved = psImageConvolveFFT(onoff, NULL, 0, kernel, 0.0);
     569    psFree(onoff);
     570    psFree(kernel);
     571    if (!convolved) {
     572        psError(PS_ERR_UNKNOWN, false, "Unable to convolve mask.");
     573        psFree(out);
     574        return NULL;
     575    }
     576
     577    thresh *= maskVal;
     578
     579    if (!setVal) {
     580        setVal = maskVal;
     581    }
     582
     583    for (int y = 0; y < numRows; y++) {
     584        for (int x = 0; x < numCols; x++) {
     585            out->data.PS_TYPE_MASK_DATA[y][x] = (convolved->data.F32[y][x] >= thresh) ?
     586                (mask->data.PS_TYPE_MASK_DATA[y][x] | setVal) : mask->data.PS_TYPE_MASK_DATA[y][x];
    518587        }
    519588    }
     
    521590    psFree(convolved);
    522591
    523     return onoff;
     592    return out;
    524593}
    525594
  • trunk/psLib/src/imageops/psImageConvolve.h

    r15320 r15321  
    55 * @author Robert DeSonia, MHPCC
    66 *
    7  * @version $Revision: 1.30 $ $Name: not supported by cvs2svn $
    8  * @date $Date: 2007-10-16 23:31:03 $
     7 * @version $Revision: 1.31 $ $Name: not supported by cvs2svn $
     8 * @date $Date: 2007-10-17 01:49:12 $
    99 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
    1010 */
     
    155155/// Convolve a mask image with a kernel, using direct convolution
    156156///
    157 /// Returns a mask, grown by the supplied kernel.  Only those pixels specified by the maskVal are grown; the
    158 /// rest are simply propagated.
    159 psImage *psImageConvolveMaskDirect(const psImage *mask, ///< Mask to convolve
     157/// Returns a mask, grown by the supplied convolution bounds.  Only those pixels specified by the maskVal are
     158/// grown, being ORed with setVal; the rest are simply propagated.  If setVal is zero, then individual bits
     159/// matching maskVal are grown.
     160psImage *psImageConvolveMaskDirect(psImage *out, ///< Output image, or NULL
     161                                   const psImage *mask, ///< Mask to convolve
    160162                                   psMaskType maskVal, ///< Mask value to convolve
    161                                    const psKernel *kernel ///< Kernel by which to convolve
     163                                   psMaskType setVal, ///< Mask value to set; 0 to propagate maskVal
     164                                   int xMin, int xMax, int yMin, int yMax ///< Convolution bounds
    162165    );
    163166
    164167/// Convolve a mask image with a kernel, using the FFT
    165168///
    166 /// Returns a mask, grown by the supplied kernel.  Only those pixels specified by the maskVal are grown; the
    167 /// rest are simply propagated.  Uses psImageConvolveFFT to convolve the mask, and then thresholds at the
    168 /// specified level.
    169 psImage *psImageConvolveMaskFFT(const psImage *mask, ///< Mask to convolve
     169/// Returns a mask, grown by the supplied convolution bounds.  Only those pixels specified by the maskVal are
     170/// grown, being ORed with setVal; the rest are simply propagated.  If setVal is zero, uses maskVal; note that
     171/// the mode of growing individual bits in maskVal is NOT supported because this algorithm does not enable it.
     172/// Uses psImageConvolveFFT to convolve those pixels which are masked, and then thresholds at the specified
     173/// level.
     174psImage *psImageConvolveMaskFFT(psImage *out, ///< Output image, or NULL
     175                                const psImage *mask, ///< Mask to convolve
    170176                                psMaskType maskVal, ///< Mask value to convolve
    171                                 const psKernel *kernel, ///< Kernel by which to convolve
     177                                psMaskType setVal, ///< Mask value to set; 0 to use maskVal
     178                                int xMin, int xMax, int yMin, int yMax, ///< Convolution bounds
    172179                                float thresh ///< Threshold (0..1) for convolved floating-point image
    173180    );
    174 
    175181
    176182/// Smooths an image by parts using 1D Gaussian independently in x and y.
Note: See TracChangeset for help on using the changeset viewer.