00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <math.h>
00029
00030 #define TYPE_ADD(a) CONCAT2X(a, PIXEL_TYPE)
00031 #define TYPE_ADD_CONST(a) CONCAT2X(a, CONCAT2X(PIXEL_TYPE, const))
00032
00033
00034 #define PIXEL_TYPE_SWAP(a, b) \
00035 { register const PIXEL_TYPE t=(a); (a)=(b); (b)=t; }
00036
00037 static PIXEL_TYPE TYPE_ADD(cpl_tools_get_kth)(PIXEL_TYPE *, int, int);
00038
00039 static
00040 double TYPE_ADD(cpl_tools_get_variancesum)(const PIXEL_TYPE *, int, double *,
00041 const double *);
00042
00043
00044
00056
00057 double TYPE_ADD(cpl_tools_get_variancesum)(const PIXEL_TYPE * a,
00058 int n, double * pmean,
00059 const double * cache)
00060 {
00061 double varsum = 0.0;
00062 double mean = 0.0;
00063 int i;
00064
00065 cpl_ensure(a != NULL, CPL_ERROR_NULL_INPUT, 0.0);
00066 cpl_ensure(n >= 0, CPL_ERROR_ILLEGAL_INPUT, 0.0);
00067
00068 for (i=0; i < n; i++) {
00069 const double delta = (double)a[i] - mean;
00070 double ri = cache[i];
00071
00072
00073 varsum += i * delta * delta * ri;
00074 mean += delta * ri;
00075 }
00076
00077 if (pmean != NULL) *pmean = mean;
00078
00079 return varsum;
00080 }
00081
00082
00097
00098 static
00099 PIXEL_TYPE TYPE_ADD(cpl_tools_get_kth)(PIXEL_TYPE * self,
00100 int n,
00101 int k)
00102 {
00103 register int l = 0;
00104 register int m = n - 1;
00105 register int i = l;
00106 register int j = m;
00107
00108 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, (PIXEL_TYPE)0);
00109 cpl_ensure(k >= 0, CPL_ERROR_ILLEGAL_INPUT, (PIXEL_TYPE)0);
00110 cpl_ensure(k < n, CPL_ERROR_ACCESS_OUT_OF_RANGE, (PIXEL_TYPE)0);
00111
00112 while (l < m) {
00113 register const PIXEL_TYPE x = self[k];
00114
00115 do {
00116 while (self[i] < x) i++;
00117 while (x < self[j]) j--;
00118 if (i <= j) {
00119 PIXEL_TYPE_SWAP(self[i], self[j]);
00120 i++; j--;
00121 }
00122 } while (i <= j);
00123
00124
00125
00126
00127
00128
00129
00130
00131 if (k <= j) {
00132
00133 m = j;
00134 i = l;
00135 } else {
00136 if (k < i) {
00137 m = j;
00138 } else {
00139 j = m;
00140 }
00141 l = i;
00142 }
00143 }
00144 return self[k];
00145 }
00146
00147
00148
00159
00160 static
00161 cpl_error_code TYPE_ADD(visir_util_clip_kappa_sigma)(cpl_imagelist * self,
00162 cpl_imagelist * devlist,
00163 double keepfrac,
00164 double kappa, int maxite,
00165 const int * shifts)
00166 {
00167 const int nz = cpl_imagelist_get_size(self);
00168 const cpl_image * img = cpl_imagelist_get_const(self, 0);
00169 const int nx = cpl_image_get_size_x(img);
00170 const int ny = cpl_image_get_size_y(img);
00171
00172 const int minrej = (int)((double)nz * 0.5 * (1.0 - keepfrac) + 0.5);
00173 PIXEL_TYPE * pvalues = (PIXEL_TYPE*)cpl_malloc(nz * sizeof(*pvalues));
00174
00175 const PIXEL_TYPE ** pimg = cpl_malloc((size_t)nz * sizeof(PIXEL_TYPE *));
00176 cpl_binary ** pbpm = cpl_malloc((size_t)nz * sizeof(cpl_binary *));
00177 cpl_image * imgstdev0 = cpl_image_new(nx, ny, STDEV_TYPE);
00178 cpl_image * imgstdevn = cpl_image_new(nx, ny, STDEV_TYPE);
00179
00180
00181
00182
00183
00184
00185
00186 OMP_PRAGMA(omp critical(clip_rnok_precompute))
00187 if (prnok == NULL || prnok_nz < nz) {
00188 if (prnok)
00189 cpl_free(prnok);
00190 prnok = cpl_malloc(nz * sizeof(prnok[0]));
00191 for (int i = 0; i < nz; i++) {
00192 prnok[i] = 1. / (i + 1);
00193 }
00194 prnok_nz = nz;
00195 }
00196
00197
00198 bug_if(cpl_image_get_type(img) != PIXEL_TYPE_CPL);
00199
00200
00201
00202 error_if(keepfrac < 0.0, CPL_ERROR_ILLEGAL_INPUT, "Parameter keepfrac = "
00203 "%g < 0.0", keepfrac);
00204 error_if(keepfrac > 1.0, CPL_ERROR_ILLEGAL_INPUT, "Parameter keepfrac = "
00205 "%g > 1.0", keepfrac);
00206 error_if(kappa < 0.0, CPL_ERROR_ILLEGAL_INPUT, "Parameter kappa = "
00207 "%g < 0.0", kappa);
00208 error_if(maxite < 0, CPL_ERROR_ILLEGAL_INPUT, "Parameter maxite = "
00209 "%d < 0", maxite);
00210
00211 for (int k = 0; k < nz; k++) {
00212 cpl_image * imgk = cpl_imagelist_get(self, k);
00213 cpl_mask * bpm = cpl_image_get_bpm(imgk);
00214
00215 pimg[k] = TYPE_ADD_CONST(cpl_image_get_data)(imgk);
00216 pbpm[k] = cpl_mask_get_data(bpm);
00217
00218 bug_if(pimg[k] == NULL);
00219 bug_if(pbpm[k] == NULL);
00220
00221 }
00222
00223 for (int j = 0; j < ny; j++) {
00224 for (int i = 0; i < nx; i++) {
00225 int nok = 0;
00226
00227 for (int k = 0; k < nz; k++) {
00228 const int ii = (i + shifts[k * 2]) +
00229 (j + shifts[k * 2 + 1]) * nx;
00230 if (i + shifts[k * 2] >= nx || i + shifts[k * 2] < 0 ||
00231 j + shifts[k * 2 + 1] >= ny || j + shifts[k * 2 + 1] < 0)
00232 continue;
00233
00234 if (!pbpm[k][ii]) {
00235 pvalues[nok++] = pimg[k][ii];
00236 }
00237 }
00238
00239 if (nok > 1) {
00240
00241 const int ithmin = minrej - (nz - nok) / 2 - 1;
00242 double median, mean, stdev, varsum;
00243 PIXEL_TYPE * pmedian = pvalues;
00244 int nmedian = nok;
00245
00246 if (0 <= ithmin && 2 * ithmin + 3 <= nok) {
00247
00248
00249 const int ithmax = nok - ithmin - 1;
00250 (void)TYPE_ADD(cpl_tools_get_kth)(pvalues, nok, ithmax);
00251 (void)TYPE_ADD(cpl_tools_get_kth)(pvalues, ithmax, ithmin);
00252
00253 pmedian += ithmin + 1;
00254 nmedian -= ithmin * 2 + 2;
00255 }
00256 bug_if( nmedian <= 1 );
00257
00258 median = (double)TYPE_ADD(cpl_tools_get_kth)(pmedian, nmedian,
00259 (nmedian - 1) / 2);
00260 if (!(nmedian & 1)) {
00261
00262
00263 median += (double)TYPE_ADD(cpl_tools_get_kth)(pmedian +
00264 nmedian / 2,
00265 nmedian / 2,
00266 0);
00267 median *= 0.5;
00268 }
00269
00270 varsum = TYPE_ADD(cpl_tools_get_variancesum)(pmedian, nmedian,
00271 NULL, prnok);
00272 stdev = sqrt(varsum / (double)(nmedian - 1));
00273
00274 bug_if(cpl_image_set(imgstdev0, 1 + i, 1 + j, stdev));
00275
00276 for (int nite = 0; nite < maxite; nite++) {
00277
00278 const double center = nite ? mean : median;
00279 const double lolim = center - kappa * stdev;
00280 const double hilim = center + kappa * stdev;
00281 const int prevok = nok;
00282
00283 nok = 0;
00284 mean = 0.0;
00285 varsum = 0.0;
00286
00287 for (int k = 0; k < nz; k++) {
00288 const int ii = (i + shifts[k * 2]) +
00289 (j + shifts[k * 2 + 1]) * nx;
00290 if (i + shifts[k * 2] >= nx || i + shifts[k * 2] < 0 ||
00291 j + shifts[k * 2 + 1] >= ny || j + shifts[k * 2 + 1] < 0) {
00292 continue;
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 if (!pbpm[k][ii]) {
00305 if (lolim <= pimg[k][ii] &&
00306 pimg[k][ii] <= hilim) {
00307
00308
00309 const double delta =
00310 (double)pimg[k][ii] - mean;
00311 double rnok = prnok[nok];
00312
00313
00314 varsum += nok * delta * delta * rnok;
00315 mean += delta * rnok;
00316
00317 nok++;
00318 } else {
00319
00320 pbpm[k][ii] = CPL_BINARY_1;
00321 }
00322 }
00323 }
00324
00325 if (nok < 2) {
00326 stdev = 0.0;
00327 break;
00328 }
00329 if (nok == prevok) break;
00330 stdev = sqrt(varsum / (double)(nok - 1));
00331 }
00332 bug_if(cpl_image_set(imgstdevn, 1 + i, 1 + j, stdev));
00333 }
00334 }
00335 }
00336
00337 bug_if(cpl_imagelist_set(devlist, imgstdev0, 0));
00338 imgstdev0 = NULL;
00339 bug_if(cpl_imagelist_set(devlist, imgstdevn, 1));
00340 imgstdevn = NULL;
00341
00342 end_skip;
00343
00344 cpl_image_delete(imgstdev0);
00345 cpl_image_delete(imgstdevn);
00346 cpl_free(pvalues);
00347 cpl_free(pimg);
00348 cpl_free(pbpm);
00349
00350 return cpl_error_get_code();
00351 }
00352
00353 #undef PIXEL_TYPE_SWAP