IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 36278


Ignore:
Timestamp:
Nov 11, 2013, 10:13:29 AM (13 years ago)
Author:
eugene
Message:

finish psImageConvolve2dCache, and add test

Location:
branches/eam_branches/ipp-20130904/psLib
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20130904/psLib/src/imageops/Makefile.am

    r21207 r36278  
    77        psImageBackground.c \
    88        psImageConvolve.c \
     9        psImageConvolve2dCache.c \
    910        psImageCovariance.c \
    1011        psImageGeomManip.c \
  • branches/eam_branches/ipp-20130904/psLib/src/imageops/psImageConvolve.h

    r36275 r36278  
    326326bool psImageConvolveGetThreads(void);
    327327
     328psImageSmooth2dCacheData *psImageSmooth2dCacheAlloc (void);
     329bool psImageSmooth2dCacheKernel_PS1_V1 (psImageSmooth2dCacheData *smdata, float sigma, float kappa);
     330bool psImageSmooth2dCache_F32(psImage *image, psImageSmooth2dCacheData *smdata);
     331
    328332/// @}
    329333#endif // #ifndef PS_IMAGE_CONVOLVE_H
  • branches/eam_branches/ipp-20130904/psLib/src/imageops/psImageConvolve2dCache.c

    r36277 r36278  
    5050};
    5151
     52# define ADD_AXIS(RAD,DD) s += radflux[RAD]*(vi[iy - DD][ix] + \
     53                                             vi[iy + DD][ix] + \
     54                                             vi[iy][ix - DD] + \
     55                                             vi[iy][ix + DD]);
     56
     57# define ADD_DIAG(RAD,DD) s += radflux[RAD]*(vi[iy - DD][ix - DD] + \
     58                                             vi[iy - DD][ix + DD] + \
     59                                             vi[iy + DD][ix - DD] + \
     60                                             vi[iy + DD][ix + DD]);
     61
     62# define ADD_RAND(RAD,DX,DY) s += radflux[RAD]*(vi[iy - DY][ix - DX] + \
     63                                                vi[iy - DY][ix + DX] + \
     64                                                vi[iy + DY][ix - DX] + \
     65                                                vi[iy + DY][ix + DX] + \
     66                                                vi[iy - DX][ix - DY] + \
     67                                                vi[iy - DX][ix + DY] + \
     68                                                vi[iy + DX][ix - DY] + \
     69                                                vi[iy + DX][ix + DY]);
     70
     71# if (0)
    5272# define ADD_AXIS(RAD,DD) s += radflux[RAD]*(vi[p - DD] + vi[p + DD] + vi[p - DD*Nx] + vi[p + DD*Nx]);
    5373# define ADD_DIAG(RAD,DD) s += radflux[RAD]*(vi[p - DD - DD*Nx] + vi[p + DD - DD*Nx] + vi[p - DD + DD*Nx] + vi[p + DD + DD*Nx]);
    54 # define ADD_RAND(RAD,DX,DY) s += radflux[RAD]*(vi[p - DX - DY*Nx] + vi[p + DX - DY*Nx] + vi[p - DX + DY*Nx] + vi[p + DX + DY*Nx] + \
    55                                                 vi[p - DY - DX*Nx] + vi[p + DY - DX*Nx] + vi[p - DY + DX*Nx] + vi[p + DY + DX*Nx]);
     74# define ADD_RAND(RAD,DX,DY) s += radflux[RAD]*(vi[p - DX - DY*Nx] + vi[p + DX - DY*Nx] + vi[p - DX + DY*Nx] + vi[p + DX + DY*Nx] +
     75                                                vi[p - DY - DX*Nx] + vi[p + DY - DX*Nx] + vi[p - DY + DX*Nx] + vi[p + DY + DX*Nx]);
     76# endif
    5677
    5778void psImageSmooth2dCacheDataFree (psImageSmooth2dCacheData *smdata) {
     79
     80    if (smdata->radflux == NULL) return;
    5881    psFree (smdata->radflux);
    5982}
    6083
    6184// allocate the psImageSmooth2dCache data structure, but do not define the kernel
    62 psImageSmooth2dCacheData *psImageSmooth2dCacheAlloc (psImage *image, double sigma, double Nsigma) {
     85psImageSmooth2dCacheData *psImageSmooth2dCacheAlloc (void) {
    6386
    6487    psImageSmooth2dCacheData *smdata = psAlloc(sizeof(psImageSmooth2dCacheData));
     
    6689
    6790    smdata->radflux = NULL;
     91    smdata->Nsigma = 3;
     92    smdata->Ns = -1;
    6893
    6994    return smdata;
    7095}
    7196
    72 // generate a 2D smoothing kernel for supplied sigma & kappa (PS1_V1 profile).  sigma here
    73 // does not need to match that used to allocate the structure, but it is recommended
     97// generate a 2D smoothing kernel for supplied sigma & kappa (PS1_V1 profile). 
    7498bool psImageSmooth2dCacheKernel_PS1_V1 (psImageSmooth2dCacheData *smdata, float sigma, float kappa) {
     99
    75100    // check for NULL structure elements?
    76 
    77     int size = smdata->Nrange;
    78 
    79     smdata->sigma = sigma;
    80 
    81     smdata->Ns = (int)(smdata->Nsigma * sigma);
    82     smdata->Ns = MAX (3, MIN (smdata->Ns, 10));
     101    int Ns = (int)(smdata->Nsigma * sigma);
     102    Ns = PS_MAX (3, PS_MIN (Ns, 10));
     103    smdata->Ns = Ns;
    83104
    84105    int Ns2 = Ns * Ns;
    85106
    86     // we are going to use a hard-wired radial profile
     107    // we are going to use a hard-wired set of radial points
    87108    smdata->radflux = psAlloc(sizeof(float)*NRAD_MAX);
    88109
    89110    float sum = 0.0;
    90     for (i = 0; i < NRAD_MAX; i++) {
    91       float z = radii2[i] / SQ(sigma);
    92       smdata->radflux[i] = 1.0 / (1.0 + kappa*z + pow(z,1.666));
    93       if (radii2[i] > Ns2) continue;
    94       sum += radiiN[i] * smdata->radflux[i];
    95     }
    96     for (i = 0; i < NRAD_MAX; i++) {
    97       smdata->radflux[i] = smdata->radflux[i] / sum;
     111    for (int i = 0; i < NRAD_MAX; i++) {
     112        if (radii2[i] > Ns2) {
     113            smdata->radflux[i] = 0.0;
     114            continue;
     115        }
     116        float z = radii2[i] / PS_SQR(sigma);
     117        smdata->radflux[i] = 1.0 / (1.0 + kappa*z + pow(z,1.666));
     118        sum += radiiN[i] * smdata->radflux[i];
     119    }
     120    for (int i = 0; i < NRAD_MAX; i++) {
     121        smdata->radflux[i] = smdata->radflux[i] / sum;
    98122    }
    99123
     
    105129{
    106130    PS_ASSERT_IMAGE_NON_NULL(image, false);
    107     PS_ASSERT_NON_NULL(smdata->radflux, false);
     131    PS_ASSERT_PTR_NON_NULL(smdata->radflux, false);
    108132    // assert on data type
    109133
    110134    // relevant terms
    111     int Nrange = smdata->Nrange;    // Number of pixels either side for convolution kernel
    112     int Nx = smdata->Nx;            // Number of columns
    113     int Ny = smdata->Ny;            // Number of rows
    114 
    115     psF32 *gauss = &smdata->kernel->data.F32[Nrange];
    116     psF32 *resultX = smdata->resultX;
    117     psF32 *resultY = smdata->resultY;
     135    int Ns = smdata->Ns;    // Number of pixels either side for convolution kernel
    118136       
    119     /* Smooth in X direction */
    120     {
    121         for (int j = 0; j < Ny; j++) {
    122             psF32 *vi = image->data.F32[j];
    123             int xMax = PS_MIN(Nrange, Nx);
    124             /* Smooth first Nrange pixels, with renorm */
    125             for (int i = 0; i < xMax; i++, vi++) {
    126                 int convRange = PS_MIN(Nrange + 1, Nx - i);
    127                 psF32 *vr = vi - i;
    128                 psF32 *vg = gauss - i;
    129                 double g = 0.0;
    130                 double s = 0.0;
    131                 for (int n = -i; n < convRange; n++, vr++, vg++) {
    132                     s += *vg * *vr;
    133                     g += *vg;
    134                 }
    135                 resultX[i] = s / g;
    136             }
    137             /* If that's all the pixels we have, then we're done already */
    138             if (Nx > Nrange) {
    139                 /* Smooth middle pixels; if Nx < 2*Nrange, this pass is skipped */
    140                 for (int i = Nrange; i < Nx - Nrange; i++, vi++) {
    141                     psF32 *vr = vi - Nrange;
    142                     psF32 *vg = gauss - Nrange;
    143                     double s = 0;
    144                     for (int n = -Nrange; n < Nrange + 1; n++, vr++, vg++) {
    145                         s += *vg * *vr;
    146                     }
    147                     resultX[i] = s;
    148                 }
    149                 /* Smooth last Nrange pixels, with renorm */
    150                 // if Nx < 2*Nrange, this pass starts at i == Nrange
    151                 int xMin = PS_MAX(Nx - Nrange, Nrange);
    152                 for (int i = xMin; i < Nx; i++, vi++) {
    153                     psF32 *vr = vi - Nrange;
    154                     psF32 *vg = gauss - Nrange;
    155                     double g = 0.0;
    156                     double s = 0.0;
    157                     for (int n = -Nrange; n < Nx - i; n++, vr++, vg++) {
    158                         s += *vg * *vr;
    159                         g += *vg;
    160                     }
    161                     resultX[i] = s / g;
    162                 }
    163             }
    164             memcpy(image->data.F32[j], resultX, Nx*sizeof(psF32));
    165         }
    166     }
    167        
    168     // this section probably hits the cache poorly for large images, but is probably OK for small ones
    169     /* Smooth in Y direction */
    170     {
    171         for (int i = 0; i < Nx; i++) {
    172             int yMax = PS_MIN(Nrange, Ny);
    173             /* Smooth first Nrange pixels, with renorm */
    174             for (int j = 0; j < yMax; j++) {
    175                 int convRange = PS_MIN(Nrange + 1, Ny - j);
    176                 psF32 *vg = gauss - j;
    177                 double g = 0.0;
    178                 double s = 0.0;
    179                 for (int n = -j; n < convRange; n++, vg++) {
    180                     psF32 vr = image->data.F32[j+n][i];
    181                     s += *vg * vr;
    182                     g += *vg;
    183                 }
    184                 resultY[j] = s / g;
    185             }
    186             /* If that's all the pixels we have, then we're done already */
    187             if (Ny > Nrange) {
    188                 /* Smooth middle pixels */
    189                 for (int j = Nrange; j < Ny - Nrange; j++) {
    190                     psF32 *vg = gauss - Nrange;
    191                     double s = 0;
    192                     for (int n = -Nrange; n < Nrange + 1; n++, vg++) {
    193                         psF32 vr = image->data.F32[j+n][i];
    194                         s += *vg * vr;
    195                     }
    196                     resultY[j] = s;
    197                 }
    198                 /* Smooth last Nrange pixels, with renorm */
    199                 // if Ny < 2*Nrange, this pass starts at j == Nrange
    200                 int yMin = PS_MAX(Ny - Nrange, Nrange);
    201                 for (int j = yMin; j < Ny; j++) {
    202                     psF32 *vg = gauss - Nrange;
    203                     double g = 0.0;
    204                     double s = 0.0;
    205                     for (int n = -Nrange; n < Ny - j; n++, vg++) {
    206                         psF32 vr = image->data.F32[j+n][i];
    207                         s += *vg * vr;
    208                         g += *vg;
    209                     }
    210                     resultY[j] = s / g;
    211                 }
    212             }
    213             // loop here
    214             for (int j = 0; j < Ny; j++) {
    215                 image->data.F32[j][i] = resultY[j];
    216             }
    217         }
    218     }
     137    int Nx = image->numCols;
     138    int Ny = image->numRows;
     139
     140    int Nxtmp = Nx + 2*Ns;
     141    int Nytmp = Ny + 2*Ns;
     142
     143    // copy input image into a buffer padded by Ns on either side
     144    float **vi = (float **) psAlloc(sizeof(float *)*Nytmp);
     145    for (int iy = 0; iy < Nytmp; iy ++) {
     146        int Iy = iy - Ns;
     147        vi[iy] = (float *) psAlloc(sizeof(float)*Nxtmp);
     148        memset (vi[iy], 0, sizeof(float)*Nxtmp);
     149        if (Iy < 0) continue;
     150        if (Iy >= image->numRows) continue;
     151        for (int Ix = 0; Ix < image->numCols; Ix ++) {
     152            int ix = Ix + Ns;
     153            vi[iy][ix] = image->data.F32[Iy][Ix];
     154        }
     155    }
     156
     157    // set up the output buffer (different from input)
     158    float **vo = (float **) psAlloc(sizeof(float *)*Nytmp);
     159    for (int iy = 0; iy < Nytmp; iy ++) {
     160        vo[iy] = (float *) psAlloc(sizeof(float)*Nxtmp);
     161        memset (vo[iy], 0, sizeof(float)*Nxtmp);
     162    }
     163
     164    float *radflux = smdata->radflux;
     165
     166    // smooth in 2D (ix,iy is the coordinate in the input and output images, only need to
     167    // transform the region inside the padding.
     168    for (int iy = Ns; iy < Ny + Ns; iy ++) {
     169        for (int ix = Ns; ix < Nx + Ns; ix ++) {
     170
     171            float s = radflux[0] * vi[iy][ix];
     172
     173            // r <= 1.0
     174            ADD_AXIS (1,  1);      // r^2 = 1
     175
     176            // r <= 2.0
     177            ADD_DIAG (2,  1);      // r^2 = 2
     178            ADD_AXIS (3,  2);      // r^2 = 4
     179
     180            // r <= 3.0
     181            ADD_RAND (4,  1,  2);  // r^2 = 5
     182            ADD_DIAG (5,  2);      // r^2 = 8
     183            ADD_AXIS (6,  3);      // r^2 = 9
     184            if (Ns <= 3) goto finish;
     185
     186            // r <= 4.0
     187            ADD_RAND (7,  1,  3);  // r^2 = 10
     188            ADD_RAND (8,  2,  3);  // r^2 = 13
     189            ADD_AXIS (9,  4);      // r^2 = 16
     190            if (Ns <= 4) goto finish;
     191
     192            // r <= 5.0
     193            ADD_RAND (10,  1,  4); // r^2 = 17
     194            ADD_DIAG (11,  3);     // r^2 = 18
     195            ADD_RAND (12,  2,  4); // r^2 = 20
     196            ADD_RAND (13,  3,  4); // r^2 = 25
     197            ADD_AXIS (13,  5);     // r^2 = 25
     198            if (Ns <= 5) goto finish;
     199
     200            // r <= 6.0
     201            ADD_RAND (14,  1,  5); // r^2 = 26
     202            ADD_RAND (15,  2,  5); // r^2 = 29
     203            ADD_DIAG (16,  4);     // r^2 = 32
     204            ADD_RAND (17,  3,  5); // r^2 = 34
     205            ADD_AXIS (18,  6);     // r^2 = 36
     206            if (Ns <= 6) goto finish;
     207
     208            // r <= 7.0
     209            ADD_RAND (19,  1,  6); // r^2 = 37
     210            ADD_RAND (20,  2,  6); // r^2 = 40
     211            ADD_RAND (21,  4,  5); // r^2 = 41
     212            ADD_RAND (22,  3,  6); // r^2 = 45
     213            ADD_AXIS (23,  7);     // r^2 = 49
     214            if (Ns <= 7) goto finish;
     215
     216            // r <= 8.0
     217            ADD_RAND (24,  1,  7); // r^2 = 50
     218            ADD_DIAG (24,  5);     // r^2 = 50
     219            ADD_RAND (25,  4,  6); // r^2 =   52
     220            ADD_RAND (26,  2,  7); // r^2 =   53
     221            ADD_RAND (27,  3,  7); // r^2 =   58
     222            ADD_RAND (28,  5,  6); // r^2 =   61
     223            ADD_AXIS (29,  8);     // r^2 =   64
     224            if (Ns <= 8) goto finish;
     225
     226            ADD_RAND (30,  1,  8); // r^2 =   65 *
     227            ADD_RAND (30,  4,  7); // r^2 =   65 *
     228            ADD_RAND (31,  2,  8); // r^2 =   68
     229            ADD_DIAG (32,  6);     // r^2 =   72
     230            ADD_RAND (33,  3,  8); // r^2 =   73
     231            ADD_RAND (34,  5,  7); // r^2 =   74
     232            ADD_RAND (35,  4,  8); // r^2 =   80
     233            ADD_AXIS (36,  9);     // r^2 =   81
     234            if (Ns <= 9) goto finish;
     235
     236            ADD_RAND (37,  1,  9); // r^2 =   82
     237            ADD_RAND (38,  2,  9); // r^2 =   85 *
     238            ADD_RAND (38,  6,  7); // r^2 =   85 *
     239            ADD_RAND (39,  5,  8); // r^2 =   89
     240            ADD_RAND (40,  3,  9); // r^2 =   90
     241            ADD_RAND (41,  4,  9); // r^2 =   97
     242            ADD_DIAG (42,  7);     // r^2 =   98
     243            ADD_RAND (43,  6,  8); // r^2 =  100 *
     244            ADD_AXIS (43, 10);     // r^2 =  100 *
     245            if (Ns <= 10) goto finish;
     246
     247        finish:
     248            vo[iy][ix] = s;
     249        }
     250    }
     251   
     252    for (int iy = 0; iy < Ny; iy ++) {
     253        int Iy = iy + Ns;
     254        for (int ix = 0; ix < Nx; ix ++) {
     255            int Ix = ix + Ns;
     256            image->data.F32[iy][ix] = vo[Iy][Ix];
     257        }
     258    }
     259
     260    for (int iy = 0; iy < Nytmp; iy ++) {
     261        psFree (vi[iy]);
     262        psFree (vo[iy]);
     263    }
     264    psFree (vi);
     265    psFree (vo);
     266       
    219267    return true;
    220268}
  • branches/eam_branches/ipp-20130904/psLib/test/imageops/Makefile.am

    r35767 r36278  
    2222        tap_psImageConvolve \
    2323        tap_psImageConvolve2 \
     24        tap_psImageConvolve2dCache \
    2425        tap_psImagePixelExtract \
    2526        tap_psImageInterpolate2 \
Note: See TracChangeset for help on using the changeset viewer.