IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Oct 3, 2008, 4:37:51 PM (18 years ago)
Author:
Paul Price
Message:

Adding psImageSmoothMask: a faster version of psImageSmoothMaskF32 (by about 30% when running optimised on ipp002).

File:
1 edited

Legend:

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

    r19298 r19895  
    77/// @author Eugene Magnier, IfA
    88///
    9 /// @version $Revision: 1.76 $ $Name: not supported by cvs2svn $
    10 /// @date $Date: 2008-08-30 02:24:21 $
     9/// @version $Revision: 1.77 $ $Name: not supported by cvs2svn $
     10/// @date $Date: 2008-10-04 02:37:51 $
    1111///
    1212/// Copyright 2004-2007 Institute for Astronomy, University of Hawaii
     
    3333
    3434#include "psImageConvolve.h"
     35
     36#define MIN_GAUSS_FRAC 0.25             // Minimum Gaussian fraction to accept when smoothing
     37
    3538
    3639static bool threaded = false;           // Run image convolution threaded?
     
    642645}
    643646
     647// Smooth an image with masked pixels
     648// The calculation and calcMask images are *deliberately* backwards (row,col instead of col,row or
     649// [col][row] instead of [row][col]) to optimise the iteration over rows; such instances are marked "BW"
     650#define IMAGESMOOTH_MASK_CASE(TYPE) \
     651case PS_TYPE_##TYPE: { \
     652    psImage *calculation = psImageAlloc(numRows, numCols, PS_TYPE_##TYPE); /* Calculation image; BW */ \
     653    psImage *calcMask = psImageAlloc(numRows, numCols, PS_TYPE_MASK); /* Mask for calculation image; BW */ \
     654    \
     655    /** Smooth in X direction **/ \
     656    for (int j = 0; j < numRows; j++) { \
     657        for (int i = 0; i < numCols; i++) { \
     658            int xMin = PS_MAX(i - size, 0); \
     659            int xMax = PS_MIN(i + size, xLast); \
     660            const psMaskType *maskData = &mask->data.PS_TYPE_MASK_DATA[j][xMin]; \
     661            const ps##TYPE *imageData = &image->data.TYPE[j][xMin]; \
     662            int uMin = - PS_MIN(i, size); /* Minimum kernel index */ \
     663            const psF32 *gaussData = &gauss[uMin]; \
     664            double sumIG = 0.0, sumG = 0.0; /* Sums for convolution */ \
     665            for (int x = xMin; x <= xMax; x++, maskData++, imageData++, gaussData++) { \
     666                if (*maskData & maskVal) { \
     667                    continue; \
     668                } \
     669                sumIG += *imageData * *gaussData; \
     670                sumG += *gaussData; \
     671            } \
     672            if (sumG > MIN_GAUSS_FRAC) { \
     673                /* BW */ \
     674                calculation->data.TYPE[i][j] = sumIG / sumG; \
     675                calcMask->data.PS_TYPE_MASK_DATA[i][j] = 0; \
     676            } else { \
     677                /* BW */ \
     678                calcMask->data.PS_TYPE_MASK_DATA[i][j] = 0xFF; \
     679            } \
     680        } \
     681    } \
     682    \
     683    output = psImageRecycle(output, numCols, numRows, PS_TYPE_##TYPE); \
     684    \
     685    /** Smooth in Y direction  **/ \
     686    for (int i = 0; i < numCols; i++) { \
     687        for (int j = 0; j < numRows; j++) { \
     688            int yMin = PS_MAX(j - size, 0); \
     689            int yMax = PS_MIN(j + size, yLast); \
     690            const psMaskType *maskData = &calcMask->data.PS_TYPE_MASK_DATA[i][yMin]; /* BW */ \
     691            const ps##TYPE *imageData = &calculation->data.TYPE[i][yMin]; /* BW */ \
     692            int vMin = - PS_MIN(j, size); /* Minimum kernel index */ \
     693            const psF32 *gaussData = &gauss[vMin]; \
     694            double sumIG = 0.0, sumG = 0.0; /* Sums for convolution */ \
     695            for (int y = yMin; y <= yMax; y++, maskData++, imageData++, gaussData++) { \
     696                if (*maskData) { \
     697                    continue; \
     698                } \
     699                sumIG += *imageData * *gaussData; \
     700                sumG += *gaussData; \
     701            } \
     702            output->data.TYPE[j][i] = (sumG > MIN_GAUSS_FRAC) ? sumIG / sumG : NAN; \
     703        } \
     704    } \
     705    \
     706    psFree(calculation); \
     707    psFree(calcMask); \
     708    psFree(gaussNorm); \
     709    \
     710    return output; \
     711}
     712
     713
     714
     715psImage *psImageSmoothMask(psImage *output,
     716                           const psImage *image,
     717                           const psImage *mask,
     718                           psMaskType maskVal,
     719                           double sigma,
     720                           double numSigma)
     721{
     722    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
     723    PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
     724    PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL);
     725    PS_ASSERT_IMAGES_SIZE_EQUAL(image, mask, NULL);
     726
     727    int numCols = image->numCols, numRows = image->numRows; // Size of image
     728    int xLast = numCols - 1, yLast = numRows - 1; // Last index
     729
     730    // relevant terms
     731    int size = sigma * numSigma + 0.5;  // Half-size of kernel
     732    int fullSize = 2*size + 1;          // Total number of pixels in convolution kernel
     733
     734    // Generate normalized gaussian
     735    psVector *gaussNorm = psVectorAlloc(fullSize + 1, PS_TYPE_F32); // Normalised Gaussian
     736    {
     737        double sum = 0.0;
     738        double norm = -0.5/(sigma*sigma);
     739        for (int i = 0, u = -size; i <= fullSize; i++, u++) {
     740            float value = expf(norm*PS_SQR(u));
     741            gaussNorm->data.F32[i] = value;
     742            sum += value;
     743        }
     744        sum = 1.0 / sum;
     745        for (int i = 0; i <= fullSize; i++) {
     746            gaussNorm->data.F32[i] *= sum;
     747        }
     748    }
     749    const psF32 *gauss = &gaussNorm->data.F32[size]; // Gaussian convolution kernel
     750
     751    switch (image->type.type) {
     752        IMAGESMOOTH_MASK_CASE(F32);
     753        IMAGESMOOTH_MASK_CASE(F64);
     754      default:
     755        psFree(gaussNorm);
     756        char *typeStr;
     757        PS_TYPE_NAME(typeStr,image->type.type);
     758        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
     759                _("Specified psImage type, %s, is not supported."),
     760                typeStr);
     761        return false;
     762    }
     763
     764    psAbort("Should never reach here.");
     765    return false;
     766}
     767
     768
    644769bool psImageSmoothMaskF32 (psImage *image,
    645770                           psImage *mask,
     
    695820                g += *sg;
    696821            }
    697             *vo = (g > 0.25) ? s / g : NAN;
     822            *vo = (g > MIN_GAUSS_FRAC) ? s / g : NAN;
    698823        }
    699824        memcpy(image->data.F32[j], calculation->data.F32, Nx*sizeof(psF32));
     
    740865        psF32 *vs = outsum->data.F32;
    741866        for (int i = 0; i < Nx; i++, vo++, vs++) {
    742             *vo = (*vs > 0.25) ? *vo / *vs : NAN;
     867            *vo = (*vs > MIN_GAUSS_FRAC) ? *vo / *vs : NAN;
    743868        }
    744869
Note: See TracChangeset for help on using the changeset viewer.