IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 12179


Ignore:
Timestamp:
Mar 2, 2007, 11:05:52 AM (19 years ago)
Author:
Paul Price
Message:

Removing optional output image from psImageConvolve APIs due to concerns about polluting the input image when out == in. Turned direct convolution inside-out for optimisation.

Location:
trunk/psLib
Files:
3 edited

Legend:

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

    r12001 r12179  
    77/// @author Eugene Magnier, IfA
    88///
    9 /// @version $Revision: 1.47 $ $Name: not supported by cvs2svn $
    10 /// @date $Date: 2007-02-22 22:37:59 $
     9/// @version $Revision: 1.48 $ $Name: not supported by cvs2svn $
     10/// @date $Date: 2007-03-02 21:05:52 $
    1111///
    1212/// Copyright 2004-2007 Institute for Astronomy, University of Hawaii
     
    195195}
    196196
    197 psImage *psImageConvolveDirect(psImage *out,
    198                                const psImage *in,
     197psImage *psImageConvolveDirect(const psImage *in,
    199198                               const psKernel *kernel)
    200199{
     
    214213    int numCols = in->numCols;          // Number of columns
    215214
     215    psImage *out;                       // Image to be returned
     216
     217#if 0
     218
     219    // This is the usual way of doing the convolution, but it wastes time if there's a large number of zero
     220    // pixels in the kernel.
    216221#define SPATIAL_CONVOLVE_CASE(TYPE) \
    217222    case PS_TYPE_##TYPE: { \
    218         ps##TYPE **inData = in->data.TYPE; \
    219         out = psImageRecycle(out, numCols, numRows, PS_TYPE_##TYPE); \
     223        ps##TYPE **inData = in->data.TYPE; /* Dereference input data */ \
     224        out = psImageAlloc(numCols, numRows, PS_TYPE_##TYPE); \
    220225        for (int row = 0; row < numRows; row++) { \
    221226            ps##TYPE *outRow = out->data.TYPE[row]; \
     
    233238    break;
    234239
     240#else
     241
     242    // This turns the convolution inside-out, allowing us to skip kernel pixels that have no contribution.
     243#define SPATIAL_CONVOLVE_CASE(TYPE) \
     244    case PS_TYPE_##TYPE: { \
     245        ps##TYPE **inData = in->data.TYPE; /* Dereference input data */ \
     246        out = psImageAlloc(numCols, numRows, PS_TYPE_##TYPE); \
     247        psImageInit(out, 0.0); \
     248        for (int ky = yMin; ky <= yMax; ky++) { \
     249            for (int kx = xMin; kx <= xMax; kx++) { \
     250                float kValue = kernelData[ky][kx]; /* Kernel value */ \
     251                if (kValue == 0.0) { \
     252                    continue; \
     253                } \
     254                for (int y = PS_MAX(- ky, 0); y < PS_MIN(numRows, numRows - ky); y++) { \
     255                    for (int x = PS_MAX(- kx, 0); x < PS_MIN(numCols, numCols - kx); x++) { \
     256                        out->data.TYPE[y][x] += kValue * inData[y + ky][x + kx]; \
     257                    } \
     258                } \
     259            } \
     260        } \
     261    } \
     262    break;
     263
     264#endif
     265
    235266    switch (in->type.type) {
    236267        SPATIAL_CONVOLVE_CASE(F32);
     
    243274}
    244275
    245 psImage *psImageConvolveFFT(psImage *out,
    246                             const psImage *in,
     276psImage *psImageMaskConvolve(const psImage *mask, psMaskType maskVal, const psKernel *kernel)
     277{
     278    PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
     279    PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL);
     280    PS_ASSERT_PTR_NON_NULL(kernel, NULL);
     281    PS_ASSERT_PTR_NON_NULL(kernel->kernel, NULL);
     282
     283    // Pull out kernel parameters, for convenience
     284    int xMin = kernel->xMin;
     285    int xMax = kernel->xMax;
     286    int yMin = kernel->yMin;
     287    int yMax = kernel->yMax;
     288
     289    int numRows = mask->numRows;        // Number of rows
     290    int numCols = mask->numCols;        // Number of columns
     291
     292    psMaskType **maskData = mask->data.PS_TYPE_MASK_DATA;
     293    psImage *out = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
     294    psImageInit(out, 0);
     295
     296    for (int kRow = yMin; kRow <= yMax; kRow++) {
     297        for (int kCol = xMin; kCol <= xMax; kCol++) {
     298            psMaskType kValue = kernel->kernel[kRow][kCol]; // Value of the kernel
     299            if (kValue == 0) {
     300                continue;
     301            }
     302            for (int row = PS_MAX(kRow, 0); row < PS_MIN(numRows, numRows - kRow); row++) {
     303                for (int col = PS_MAX(kCol, 0); col < PS_MIN(numCols, numCols - kCol); col++) {
     304                    if (maskData[row][col] & maskVal) {
     305                        out->data.PS_TYPE_MASK_DATA[row + kRow][col + kCol] = maskVal;
     306                    }
     307                }
     308            }
     309        }
     310    }
     311
     312    return out;
     313}
     314
     315
     316psImage *psImageConvolveFFT(const psImage *in,
    247317                            const psKernel *kernel,
    248318                            float pad)
     
    356426    // Trim off the padding, then renormalise (which also does a copy, so there's no parent for the output)
    357427    psImage *convolved = psImageSubset(paddedConvolved, psRegionSet(0, numCols, 0, numRows));
    358     out = (psImage*)psBinaryOp(out, convolved, "*",
    359                                psScalarAlloc(1.0 / paddedCols / paddedRows, PS_TYPE_F32));
     428    psImage *out = (psImage*)psBinaryOp(NULL, convolved, "*",
     429                                        psScalarAlloc(1.0 / paddedCols / paddedRows, PS_TYPE_F32));
    360430    psFree(convolved);
    361431    psFree(paddedConvolved);
  • trunk/psLib/src/imageops/psImageConvolve.h

    r11703 r12179  
    55 * @author Robert DeSonia, MHPCC
    66 *
    7  * @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
    8  * @date $Date: 2007-02-08 04:17:58 $
     7 * @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
     8 * @date $Date: 2007-03-02 21:05:52 $
    99 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
    1010 */
     
    112112///
    113113psImage *psImageConvolveDirect(
    114     psImage *out,                       ///< a psImage to recycle.  If NULL, a new psImage is made.
    115114    const psImage *in,                  ///< the psImage to convolve
    116115    const psKernel *kernel              ///< kernel to colvolve with
     
    122121/// are suitably padded to avoid wrap-around effects.
    123122psImage *psImageConvolveFFT(
    124     psImage *out,                       ///< a psImage to recycle.  If NULL, a new psImage is made.
    125123    const psImage *in,                  ///< the psImage to convolve
    126124    const psKernel *kernel,             ///< kernel to colvolve with
  • trunk/psLib/test/imageops/tap_psImageConvolve2.c

    r11725 r12179  
    7171        psKernel *kernel = generateKernel();
    7272
    73         psImage *convolved = psImageConvolveDirect(NULL, image, kernel);
     73        psImage *convolved = psImageConvolveDirect(image, kernel);
    7474        ok(convolved, "convolution result");
    7575        skip_start(!convolved, 3, "convolution failed");
     
    9494        psKernel *kernel = generateKernel();
    9595
    96         psImage *convolved = psImageConvolveFFT(NULL, image, kernel, 0.0);
     96        psImage *convolved = psImageConvolveFFT(image, kernel, 0.0);
    9797        ok(convolved, "convolution result");
    9898        skip_start(!convolved, 3, "convolution failed");
Note: See TracChangeset for help on using the changeset viewer.