IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 6937


Ignore:
Timestamp:
Apr 21, 2006, 10:45:56 AM (20 years ago)
Author:
magnier
Message:

replaced psImageSmooth with faster version

File:
1 edited

Legend:

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

    r6226 r6937  
    55 *  @author Robert DeSonia, MHPCC
    66 *
    7  *  @version $Revision: 1.30 $ $Name: not supported by cvs2svn $
    8  *  @date $Date: 2006-01-27 20:08:58 $
     7 *  @version $Revision: 1.31 $ $Name: not supported by cvs2svn $
     8 *  @date $Date: 2006-04-21 20:45:56 $
    99 *
    1010 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    487487}
    488488
     489// XXX this is the old version from MHPCC
     490# if 0
    489491bool psImageSmooth (psImage *image,
    490492                    double  sigma,
     
    576578    return true;
    577579}
    578 
     580# else
     581
     582    // XXX EAM : we MUST use this version : it is a factor of >7 faster than the above
     583    bool psImageSmooth (psImage *image,
     584                        double  sigma,
     585                        double  Nsigma)
     586{
     587    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
     588
     589    int Nx, Ny, Npixel, Nrange, Nr;
     590    double factor, g, s, sum;
     591    psVector *temp;
     592
     593    // relevant terms
     594    Nrange = sigma*Nsigma + 0.5;
     595    Npixel = 2*Nrange + 1;
     596    factor = -0.5/(sigma*sigma);
     597
     598    Nx = image->numCols;
     599    Ny = image->numRows;
     600
     601    #define IMAGESMOOTH_CASE(TYPE) \
     602case PS_TYPE_##TYPE: { \
     603        /* generate normalized gaussian */ \
     604        psVector *gaussnorm = psVectorAlloc (Npixel, PS_TYPE_##TYPE); \
     605        sum = 0.0; \
     606        for (int i = -Nrange; i < Nrange + 1; i++) { \
     607            gaussnorm->data.TYPE[i+Nrange] = exp (factor*i*i); \
     608            sum += gaussnorm->data.TYPE[i+Nrange]; \
     609        } \
     610        for (int i = -Nrange; i < Nrange + 1; i++) { \
     611            gaussnorm->data.TYPE[i+Nrange] /= sum; \
     612        } \
     613        ps##TYPE *gauss = &gaussnorm->data.TYPE[Nrange]; \
     614        \
     615        /* smooth in X direction */ \
     616        temp = psVectorAlloc (Nx, PS_TYPE_##TYPE); \
     617        for (int j = 0; j < Ny; j++) { \
     618            ps##TYPE *vi = image->data.TYPE[j]; \
     619            ps##TYPE *vo = temp->data.TYPE; \
     620            /* smooth first Nrange pixels, with renorm */ \
     621            /* XXX need to check that this does not run over end for narrow images */ \
     622            for (int i = 0; i < Nrange; i++, vi++, vo++) { \
     623                ps##TYPE *vr = vi - i; \
     624                ps##TYPE *vg = gauss - i; \
     625                g = s = 0; \
     626                for (int n = -i; n < Nrange + 1; n++, vr++, vg++) { \
     627                    s += *vg * *vr; \
     628                    g += *vg; \
     629                } \
     630                *vo = s / g; \
     631            } \
     632            /* smooth middle pixels */ \
     633            for (int i = Nrange; i < Nx - Nrange; i++, vi++, vo++) { \
     634                ps##TYPE *vr = vi - Nrange; \
     635                ps##TYPE *vg = gauss - Nrange; \
     636                s = 0; \
     637                for (int n = -Nrange; n < Nrange + 1; n++, vr++, vg++) { \
     638                    s += *vg * *vr; \
     639                } \
     640                *vo = s; \
     641            } \
     642            /* smooth last Nrange pixels, with renorm */ \
     643            /* XXX does this miss the last column? */ \
     644            for (int i = Nx - Nrange; i < Nx; i++, vi++, vo++) { \
     645                ps##TYPE *vr = vi - Nrange; \
     646                ps##TYPE *vg = gauss - Nrange; \
     647                g = s = 0; \
     648                for (int n = -Nrange; n < Nx - i - 1; n++, vr++, vg++) { \
     649                    s += *vg * *vr; \
     650                    g += *vg; \
     651                } \
     652                *vo = s / g; \
     653            } \
     654            memcpy (image->data.TYPE[j], temp->data.TYPE, Nx*sizeof(ps##TYPE)); \
     655        } \
     656        psFree (temp); \
     657        \
     658        /* smooth in Y direction */ \
     659        psArray *temprows = psArrayAlloc (Nrange); \
     660        temprows->n = Nrange; \
     661        for (int j = 0; j < Nrange; j++) { \
     662            temp = psVectorAlloc (Nx, PS_TYPE_##TYPE); \
     663            /* zero the output row */ \
     664            memset (temp->data.TYPE, 0, Nx*sizeof(PS_TYPE_##TYPE)); \
     665            for (int n = -j, sum = 0; n < Nrange + 1; n++) { sum += gauss[n]; } \
     666            for (int n = -j; n < Nrange + 1; n++) { \
     667                ps##TYPE *vi = image->data.TYPE[j+n]; \
     668                ps##TYPE *vo = temp->data.TYPE; \
     669                g = gauss[n]; \
     670                for (int i = 0; i < Nx; i++, vi++, vo++) { \
     671                    *vo += *vi * g; \
     672                } \
     673            } \
     674            /* save output rows on temp array */ \
     675            temprows->data[j] = temp; \
     676        } \
     677        for (int j = Nrange; j < Ny - Nrange; j++) { \
     678            /* save the Nrange-offset output row, then zero */ \
     679            Nr = j % Nrange; \
     680            temp = temprows->data[Nr]; \
     681            memcpy (image->data.TYPE[j-Nrange], temp->data.TYPE, Nx*sizeof(ps##TYPE)); \
     682            memset (temp->data.TYPE, 0, Nx*sizeof(PS_TYPE_##TYPE)); \
     683            for (int n = -Nrange; n < Nrange + 1; n++) { \
     684                ps##TYPE *vi = image->data.TYPE[j+n]; \
     685                ps##TYPE *vo = temp->data.TYPE; \
     686                g = gauss[n]; \
     687                for (int i = 0; i < Nx; i++, vi++, vo++) { \
     688                    *vo += *vi * g; \
     689                } \
     690            } \
     691        } \
     692        for (int j = Ny - Nrange; j < Ny; j++) { \
     693            /* save the Nrange-offset output row, then zero */ \
     694            Nr = j % Nrange; \
     695            temp = temprows->data[Nr]; \
     696            memcpy (image->data.TYPE[j-Nrange], temp->data.TYPE, Nx*sizeof(ps##TYPE)); \
     697            memset (temp->data.TYPE, 0, Nx*sizeof(PS_TYPE_##TYPE)); \
     698            for (int n = -Nrange, sum = 0; n < Ny - j - 1; n++) { sum += gauss[n]; } \
     699            for (int n = -Nrange; n < Ny - j - 1; n++) { \
     700                ps##TYPE *vi = image->data.TYPE[j+n]; \
     701                ps##TYPE *vo = temp->data.TYPE; \
     702                g = gauss[n]; \
     703                for (int i = 0; i < Nx; i++, vi++, vo++) { \
     704                    *vo += *vi * g; \
     705                } \
     706            } \
     707        } \
     708        for (int j = Ny; j < Ny + Nrange; j++) { \
     709            /* save the Nrange-offset output row, then zero */ \
     710            Nr = j % Nrange; \
     711            temp = temprows->data[Nr]; \
     712            memcpy (image->data.TYPE[j-Nrange], temp->data.TYPE, Nx*sizeof(ps##TYPE)); \
     713        } \
     714        psFree (temprows); \
     715        psFree (gaussnorm); \
     716        break; \
     717    }
     718
     719    switch (image->type.type) {
     720        IMAGESMOOTH_CASE(F32);
     721        IMAGESMOOTH_CASE(F64);
     722    default: {
     723            char* typeStr;
     724            PS_TYPE_NAME(typeStr,image->type.type);
     725            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
     726                    PS_ERRORTEXT_psImage_IMAGE_TYPE_UNSUPPORTED,
     727                    typeStr);
     728            return false;
     729        }
     730    }
     731    return true;
     732}
     733
     734# endif
Note: See TracChangeset for help on using the changeset viewer.