Changeset 36278
- Timestamp:
- Nov 11, 2013, 10:13:29 AM (13 years ago)
- Location:
- branches/eam_branches/ipp-20130904/psLib
- Files:
-
- 1 added
- 4 edited
-
src/imageops/Makefile.am (modified) (1 diff)
-
src/imageops/psImageConvolve.h (modified) (1 diff)
-
src/imageops/psImageConvolve2dCache.c (modified) (3 diffs)
-
test/imageops/Makefile.am (modified) (1 diff)
-
test/imageops/tap_psImageConvolve2dCache.c (added)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-20130904/psLib/src/imageops/Makefile.am
r21207 r36278 7 7 psImageBackground.c \ 8 8 psImageConvolve.c \ 9 psImageConvolve2dCache.c \ 9 10 psImageCovariance.c \ 10 11 psImageGeomManip.c \ -
branches/eam_branches/ipp-20130904/psLib/src/imageops/psImageConvolve.h
r36275 r36278 326 326 bool psImageConvolveGetThreads(void); 327 327 328 psImageSmooth2dCacheData *psImageSmooth2dCacheAlloc (void); 329 bool psImageSmooth2dCacheKernel_PS1_V1 (psImageSmooth2dCacheData *smdata, float sigma, float kappa); 330 bool psImageSmooth2dCache_F32(psImage *image, psImageSmooth2dCacheData *smdata); 331 328 332 /// @} 329 333 #endif // #ifndef PS_IMAGE_CONVOLVE_H -
branches/eam_branches/ipp-20130904/psLib/src/imageops/psImageConvolve2dCache.c
r36277 r36278 50 50 }; 51 51 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) 52 72 # define ADD_AXIS(RAD,DD) s += radflux[RAD]*(vi[p - DD] + vi[p + DD] + vi[p - DD*Nx] + vi[p + DD*Nx]); 53 73 # 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 56 77 57 78 void psImageSmooth2dCacheDataFree (psImageSmooth2dCacheData *smdata) { 79 80 if (smdata->radflux == NULL) return; 58 81 psFree (smdata->radflux); 59 82 } 60 83 61 84 // allocate the psImageSmooth2dCache data structure, but do not define the kernel 62 psImageSmooth2dCacheData *psImageSmooth2dCacheAlloc ( psImage *image, double sigma, double Nsigma) {85 psImageSmooth2dCacheData *psImageSmooth2dCacheAlloc (void) { 63 86 64 87 psImageSmooth2dCacheData *smdata = psAlloc(sizeof(psImageSmooth2dCacheData)); … … 66 89 67 90 smdata->radflux = NULL; 91 smdata->Nsigma = 3; 92 smdata->Ns = -1; 68 93 69 94 return smdata; 70 95 } 71 96 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). 74 98 bool psImageSmooth2dCacheKernel_PS1_V1 (psImageSmooth2dCacheData *smdata, float sigma, float kappa) { 99 75 100 // 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; 83 104 84 105 int Ns2 = Ns * Ns; 85 106 86 // we are going to use a hard-wired radial profile107 // we are going to use a hard-wired set of radial points 87 108 smdata->radflux = psAlloc(sizeof(float)*NRAD_MAX); 88 109 89 110 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; 98 122 } 99 123 … … 105 129 { 106 130 PS_ASSERT_IMAGE_NON_NULL(image, false); 107 PS_ASSERT_ NON_NULL(smdata->radflux, false);131 PS_ASSERT_PTR_NON_NULL(smdata->radflux, false); 108 132 // assert on data type 109 133 110 134 // 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 118 136 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 219 267 return true; 220 268 } -
branches/eam_branches/ipp-20130904/psLib/test/imageops/Makefile.am
r35767 r36278 22 22 tap_psImageConvolve \ 23 23 tap_psImageConvolve2 \ 24 tap_psImageConvolve2dCache \ 24 25 tap_psImagePixelExtract \ 25 26 tap_psImageInterpolate2 \
Note:
See TracChangeset
for help on using the changeset viewer.
