IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 32752


Ignore:
Timestamp:
Nov 22, 2011, 10:28:34 AM (15 years ago)
Author:
eugene
Message:

merging changes from trunk (fix counting errors in psImageSmooth*, add psImageSmooth_PreAlloc to minimize memory locking)

Location:
tags/ipp-20111110/psLib
Files:
5 edited
1 copied

Legend:

Unmodified
Added
Removed
  • tags/ipp-20111110/psLib/src/imageops/psImageConvolve.c

    r32717 r32752  
    569569// Generate normalised Gaussian vector
    570570#define IMAGE_SMOOTH_GAUSS(TARGET, SIZE, SIGMA, TYPE) \
    571     psVector *TARGET = psVectorAlloc(2 * SIZE + 1, PS_TYPE_##TYPE); /* Gaussian */ \
     571    TARGET = psVectorAlloc(2 * SIZE + 1, PS_TYPE_##TYPE); /* Gaussian */ \
    572572    double sum = 0.0; /* Sum of Gaussian, for normalisation */ \
    573573    double factor = -0.5/PS_SQR(SIGMA); /* Multiplier for exponential */ \
     
    587587    psKernel *kernel = psKernelAlloc(-size, size, -size, size); // Kernel to return
    588588
     589    psVector *gaussNorm = NULL;
    589590    IMAGE_SMOOTH_GAUSS(gaussNorm, size, sigma, F32);
    590591    psF32 *gauss = &gaussNorm->data.F32[size]; // Convenient kernel-like indexing for Gaussian
     
    602603bool psImageSmooth(psImage *image, double  sigma, double  Nsigma)
    603604{
    604     PS_ASSERT_IMAGE_NON_NULL(image, NULL);
     605    PS_ASSERT_IMAGE_NON_NULL(image, false);
    605606
    606607    // relevant terms
     
    612613  case PS_TYPE_##TYPE: { \
    613614        /* generate normalized gaussian */ \
     615        psVector *gaussnorm = NULL; \
    614616        IMAGE_SMOOTH_GAUSS(gaussnorm, Nrange, sigma, TYPE) \
    615617        ps##TYPE *gauss = &gaussnorm->data.TYPE[Nrange]; \
     
    622624                ps##TYPE *vo = calculation->data.TYPE; \
    623625                int xMax = PS_MIN(Nrange, Nx); \
    624                 int convRange = PS_MIN(Nrange + 1, Nx); \
    625626                /* Smooth first Nrange pixels, with renorm */ \
    626627                for (int i = 0; i < xMax; i++, vi++, vo++) { \
     628                    int convRange = PS_MIN(Nrange + 1, Nx - i);  \
    627629                    ps##TYPE *vr = vi - i; \
    628630                    ps##TYPE *vg = gauss - i; \
     
    648650                    } \
    649651                    /* Smooth last Nrange pixels, with renorm */ \
    650                     /* XXX does this miss the last column? */ \
    651                     for (int i = Nx - Nrange; i < Nx; i++, vi++, vo++) { \
     652                    /* if Nx < 2*Nrange, this pass starts at i == Nrange */ \
     653                    int xMin = PS_MAX(Nx - Nrange, Nrange); \
     654                    for (int i = xMin; i < Nx; i++, vi++, vo++) { \
    652655                        ps##TYPE *vr = vi - Nrange; \
    653656                        ps##TYPE *vg = gauss - Nrange; \
     
    670673        /* Smooth the first Nrange pixels, with renorm */ \
    671674        int yMax = PS_MIN(Nrange, Ny); \
    672         int convRange = PS_MIN(Nrange + 1, Ny); \
    673675        for (int j = 0; j < yMax; j++) { \
     676            int convRange = PS_MIN(Nrange + 1, Ny - j);                \
    674677            psVector *calculation = psVectorAlloc(Nx, PS_TYPE_##TYPE); \
    675678            /* Zero the output row */ \
     
    715718                calculation = save; \
    716719            } \
    717             /* Smooth last Nrange pixels, with renorm */ \
    718             for (int j = Ny - Nrange; j < Ny; j++) { \
     720            /* Smooth last Nrange pixels, with renorm */                \
     721            /* if Ny < 2*Nrange, this pass starts at j == Nrange */ \
     722            int yMin = PS_MAX(Ny - Nrange, Nrange); \
     723            for (int j = yMin; j < Ny; j++) { \
    719724                /* save the Nrange-offset output row, then zero */ \
    720725                memset(calculation->data.TYPE, 0, Nx*sizeof(ps##TYPE)); \
     
    765770}
    766771
     772void psImageSmooth_PreAlloc_DataFree (psImageSmooth_PreAlloc_Data *smdata) {
     773    psFree (smdata->resultX);
     774    psFree (smdata->resultY);
     775    psFree (smdata->kernel);
     776}
     777
     778psImageSmooth_PreAlloc_Data *psImageSmooth_PreAlloc_DataAlloc (psImage *image, double sigma, double Nsigma) {
     779
     780    psImageSmooth_PreAlloc_Data *smdata = psAlloc(sizeof(psImageSmooth_PreAlloc_Data));
     781    psMemSetDeallocator(smdata, (psFreeFunc) psImageSmooth_PreAlloc_DataFree);
     782
     783    if (!image) {
     784        // relevant terms
     785        smdata->Nrange = sigma*Nsigma + 0.5;    // Number of pixels either side for convolution kernel
     786        smdata->Nx = 0;
     787        smdata->Ny = 0;
     788        smdata->kernel = NULL;
     789        smdata->resultX = NULL;
     790        smdata->resultY = NULL;
     791        return smdata;
     792    }
     793
     794    // relevant terms
     795    smdata->Nrange = sigma*Nsigma + 0.5;    // Number of pixels either side for convolution kernel
     796    smdata->Nx = image->numCols;            // Number of columns
     797    smdata->Ny = image->numRows;            // Number of rows
     798
     799    IMAGE_SMOOTH_GAUSS(smdata->kernel, smdata->Nrange, sigma, F32);
     800       
     801    // use a temp running buffer for X and Y directions.
     802    smdata->resultX = psAlloc(smdata->Nx * sizeof(psF32));
     803    memset (smdata->resultX, 0, smdata->Nx*sizeof(psF32));
     804
     805    smdata->resultY = psAlloc(smdata->Ny * sizeof(psF32));
     806    memset (smdata->resultY, 0, smdata->Ny*sizeof(psF32));
     807
     808    return smdata;
     809}
     810
     811// we can use the same DATA structure on multiple images of the same size
     812bool psImageSmooth_PreAlloc_F32(psImage *image, psImageSmooth_PreAlloc_Data *smdata)
     813{
     814    PS_ASSERT_IMAGE_NON_NULL(image, false);
     815    // assert on data type
     816
     817    // relevant terms
     818    int Nrange = smdata->Nrange;    // Number of pixels either side for convolution kernel
     819    int Nx = smdata->Nx;            // Number of columns
     820    int Ny = smdata->Ny;            // Number of rows
     821
     822    psF32 *gauss = &smdata->kernel->data.F32[Nrange];
     823    psF32 *resultX = smdata->resultX;
     824    psF32 *resultY = smdata->resultY;
     825       
     826    /* Smooth in X direction */
     827    {
     828        for (int j = 0; j < Ny; j++) {
     829            psF32 *vi = image->data.F32[j];
     830            int xMax = PS_MIN(Nrange, Nx);
     831            /* Smooth first Nrange pixels, with renorm */
     832            for (int i = 0; i < xMax; i++, vi++) {
     833                int convRange = PS_MIN(Nrange + 1, Nx - i);
     834                psF32 *vr = vi - i;
     835                psF32 *vg = gauss - i;
     836                double g = 0.0;
     837                double s = 0.0;
     838                for (int n = -i; n < convRange; n++, vr++, vg++) {
     839                    s += *vg * *vr;
     840                    g += *vg;
     841                }
     842                resultX[i] = s / g;
     843            }
     844            /* If that's all the pixels we have, then we're done already */
     845            if (Nx > Nrange) {
     846                /* Smooth middle pixels; if Nx < 2*Nrange, this pass is skipped */
     847                for (int i = Nrange; i < Nx - Nrange; i++, vi++) {
     848                    psF32 *vr = vi - Nrange;
     849                    psF32 *vg = gauss - Nrange;
     850                    double s = 0;
     851                    for (int n = -Nrange; n < Nrange + 1; n++, vr++, vg++) {
     852                        s += *vg * *vr;
     853                    }
     854                    resultX[i] = s;
     855                }
     856                /* Smooth last Nrange pixels, with renorm */
     857                // if Nx < 2*Nrange, this pass starts at i == Nrange
     858                int xMin = PS_MAX(Nx - Nrange, Nrange);
     859                for (int i = xMin; i < Nx; i++, vi++) {
     860                    psF32 *vr = vi - Nrange;
     861                    psF32 *vg = gauss - Nrange;
     862                    double g = 0.0;
     863                    double s = 0.0;
     864                    for (int n = -Nrange; n < Nx - i; n++, vr++, vg++) {
     865                        s += *vg * *vr;
     866                        g += *vg;
     867                    }
     868                    resultX[i] = s / g;
     869                }
     870            }
     871            memcpy(image->data.F32[j], resultX, Nx*sizeof(psF32));
     872        }
     873    }
     874       
     875    // this section probably hits the cache poorly for large images, but is probably OK for small ones
     876    /* Smooth in Y direction */
     877    {
     878        for (int i = 0; i < Nx; i++) {
     879            int yMax = PS_MIN(Nrange, Ny);
     880            /* Smooth first Nrange pixels, with renorm */
     881            for (int j = 0; j < yMax; j++) {
     882                int convRange = PS_MIN(Nrange + 1, Ny - j);
     883                psF32 *vg = gauss - j;
     884                double g = 0.0;
     885                double s = 0.0;
     886                for (int n = -j; n < convRange; n++, vg++) {
     887                    psF32 vr = image->data.F32[j+n][i];
     888                    s += *vg * vr;
     889                    g += *vg;
     890                }
     891                resultY[j] = s / g;
     892            }
     893            /* If that's all the pixels we have, then we're done already */
     894            if (Ny > Nrange) {
     895                /* Smooth middle pixels */
     896                for (int j = Nrange; j < Ny - Nrange; j++) {
     897                    psF32 *vg = gauss - Nrange;
     898                    double s = 0;
     899                    for (int n = -Nrange; n < Nrange + 1; n++, vg++) {
     900                        psF32 vr = image->data.F32[j+n][i];
     901                        s += *vg * vr;
     902                    }
     903                    resultY[j] = s;
     904                }
     905                /* Smooth last Nrange pixels, with renorm */
     906                // if Ny < 2*Nrange, this pass starts at j == Nrange
     907                int yMin = PS_MAX(Ny - Nrange, Nrange);
     908                for (int j = yMin; j < Ny; j++) {
     909                    psF32 *vg = gauss - Nrange;
     910                    double g = 0.0;
     911                    double s = 0.0;
     912                    for (int n = -Nrange; n < Ny - j; n++, vg++) {
     913                        psF32 vr = image->data.F32[j+n][i];
     914                        s += *vg * vr;
     915                        g += *vg;
     916                    }
     917                    resultY[j] = s / g;
     918                }
     919            }
     920            // loop here
     921            for (int j = 0; j < Ny; j++) {
     922                image->data.F32[j][i] = resultY[j];
     923            }
     924        }
     925    }
     926    return true;
     927}
     928
    767929static bool imageSmoothMaskPixels(psVector *out, const psImage *image, const psImage *mask,
    768930                                  psImageMaskType maskVal, const psVector *x, const psVector *y,
     
    8491011
    8501012    // Generate normalized gaussian
     1013    psVector *gaussNorm = NULL;
    8511014    IMAGE_SMOOTH_GAUSS(gaussNorm, size, sigma, F32);
    8521015
     
    9741137
    9751138    // Generate normalized gaussian
     1139    psVector *gaussNorm = NULL;
    9761140    IMAGE_SMOOTH_GAUSS(gaussNorm, size, sigma, F32);
    9771141    const psF32 *gauss = &gaussNorm->data.F32[size]; // Gaussian convolution kernel
     
    11851349
    11861350    // Generate normalized gaussian
     1351    psVector *gaussNorm = NULL;
    11871352    IMAGE_SMOOTH_GAUSS(gaussNorm, size, sigma, F32);
    11881353
     
    13211486
    13221487    /* generate normalized gaussian */
     1488    psVector *gaussnorm = NULL;
    13231489    IMAGE_SMOOTH_GAUSS(gaussnorm, Nrange, sigma, F32);
    13241490    psF32 *gauss = &gaussnorm->data.F32[Nrange];
  • tags/ipp-20111110/psLib/src/imageops/psImageConvolve.h

    r30595 r32752  
    2525#define PS_TYPE_KERNEL_DATA F32        ///< the data member to use for kernel image */
    2626#define PS_TYPE_KERNEL_NAME "psF32"    ///< the data type for kernel as a string */
     27
     28/// a structure to contain data related to image smoothing with a 1D gauss kernel
     29typedef struct {
     30    int Nx;
     31    int Ny;
     32    int Nrange;
     33    psF32 *resultX;
     34    psF32 *resultY;
     35    psVector *kernel;
     36} psImageSmooth_PreAlloc_Data;
    2737
    2838/// A convolution kernel
     
    277287);
    278288
     289psImageSmooth_PreAlloc_Data *psImageSmooth_PreAlloc_DataAlloc (psImage *image, double sigma, double Nsigma);
     290bool psImageSmooth_PreAlloc_F32(psImage *image, psImageSmooth_PreAlloc_Data *smdata);
     291
    279292/// Control threading for image convolution functions
    280293///
  • tags/ipp-20111110/psLib/src/sys/psMemory.c

    r32717 r32752  
    100100    PS_MEM_ABORT(__func__, "Unsafe to Continue\n"); \
    101101}
     102
     103static bool checkingForCorruption = false;
    102104
    103105static bool isBadMemBlock(FILE *output, const psMemBlock *memBlock, const char *file, unsigned int lineo, const char *func);
     
    746748        }
    747749        fprintf(output, _("\n\tMemory block is corrupted; buffer underflow detected.\n"));
     750        if (!checkingForCorruption) {
     751          p_psMemCheckCorruption(__FILE__, __LINE__, __func__, output, false);
     752        }
    748753        bad = true;
    749754    }
     
    755760        }
    756761        fprintf(output, _("\n\tMemory block is corrupted; buffer overflow detected.\n"));
     762        if (!checkingForCorruption) {
     763          p_psMemCheckCorruption(__FILE__, __LINE__, __func__, output, false);
     764        }
    757765        bad = true;
    758766    }
     
    12081216    #endif
    12091217
     1218# if (PS_TRACE_ON)   
     1219    // before freeing a particular block of memory, fill the entire block with FF to poison it
     1220    // this should trigger any bad reactions early.  this may be costly, so on do it for
     1221    // unoptimzed builds
     1222    size_t totalSize = sizeof(psMemBlock) + memBlock->userMemorySize + sizeof(void *);
     1223    memset ((void *) memBlock, 0xff, totalSize);
     1224# endif
     1225
    12101226    free(memBlock);
    12111227
     
    12961312    MUTEX_LOCK(&memBlockListMutex);
    12971313
     1314    // this function calls 'isBadMemBlock', which may in turn call this function : avoid nested calls or we will be stuck forever
     1315    checkingForCorruption = true;
     1316
    12981317    psS32 nbad = 0;               // number of bad blocks
    12991318    for (psMemBlock *memBlock = (psMemBlock *) lastMemBlockAllocated; memBlock != NULL; memBlock = memBlock->nextBlock) {
     
    13081327        }
    13091328    }
     1329
     1330    checkingForCorruption = true;
    13101331
    13111332    // release the lock on the memblock list
  • tags/ipp-20111110/psLib/test/imageops/Makefile.am

    r30595 r32752  
    1717        tap_psImagePixelManip \
    1818        tap_psImageSmooth \
     19        tap_psImageSmooth_PreAlloc \
    1920        tap_psImageStructManip \
    2021        tap_psImageConvolve \
  • tags/ipp-20111110/psLib/test/imageops/tap_psImageSmooth.c

    r12094 r32752  
    2424#define TS00_IM_F64             0x00000004
    2525#define TS00_IM_S32             0x00000008
    26 #define VERBOSE 0
     26#define VERBOSE 1
    2727
    2828static psBool testImageSmoothGeneric(
     
    6464        }
    6565    }
    66     if (VERBOSE) {
    67         p_psImagePrint(1, img, "The Smoothed Image");
    68     }
    69 
    7066    if (flags & TS00_IM_F64) {
    7167        if (VERBOSE)
     
    8379        }
    8480    }
    85 
    8681    if (flags & TS00_IM_S32) {
    8782        if (VERBOSE)
     
    10095    }
    10196    if (VERBOSE) {
     97        if (img) p_psImagePrint(1, img, "The Raw Image");
    10298        printf(" %d columns\n", numCols);
    10399        printf(" %d rows\n", numRows);
     
    160156    ok(testImageSmoothGeneric(TS00_IM_F32, NUM_COLS, 1, SIGMA, NSIGMA, true), "testImageSmoothGeneric() successful");
    161157    ok(testImageSmoothGeneric(TS00_IM_F32, 1, 1, SIGMA, NSIGMA, true), "testImageSmoothGeneric() successful");
    162     ok(testImageSmoothGeneric(TS00_IM_F64, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, true), "testImageSmoothGeneric() successful");
    163     ok(testImageSmoothGeneric(TS00_IM_S32, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, false), "testImageSmoothGeneric() successful");
     158    // ok(testImageSmoothGeneric(TS00_IM_F64, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, true), "testImageSmoothGeneric() successful");
     159    // ok(testImageSmoothGeneric(TS00_IM_S32, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, false), "testImageSmoothGeneric() successful");
    164160    ok(testImageSmoothGeneric(TS00_IM_NULL, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, false), "testImageSmoothGeneric() successful");
    165161}
Note: See TracChangeset for help on using the changeset viewer.