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
00042
00043
00055
00056 double TYPE_ADD(cpl_tools_get_variancesum)(const PIXEL_TYPE * a,
00057 int n, double * pmean)
00058 {
00059 double varsum = 0.0;
00060 double mean = 0.0;
00061 int i;
00062
00063 cpl_ensure(a != NULL, CPL_ERROR_NULL_INPUT, 0.0);
00064 cpl_ensure(n >= 0, CPL_ERROR_ILLEGAL_INPUT, 0.0);
00065
00066 for (i=0; i < n; i++) {
00067 const double delta = (double)a[i] - mean;
00068
00069 varsum += i * delta * delta / (double)(i + 1);
00070 mean += delta / (double)(i + 1);
00071 }
00072
00073 if (pmean != NULL) *pmean = mean;
00074
00075 return varsum;
00076 }
00077
00078
00093
00094 static
00095 PIXEL_TYPE TYPE_ADD(cpl_tools_get_kth)(PIXEL_TYPE * self,
00096 int n,
00097 int k)
00098 {
00099 register int l = 0;
00100 register int m = n - 1;
00101 register int i = l;
00102 register int j = m;
00103
00104 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, (PIXEL_TYPE)0);
00105 cpl_ensure(k >= 0, CPL_ERROR_ILLEGAL_INPUT, (PIXEL_TYPE)0);
00106 cpl_ensure(k < n, CPL_ERROR_ACCESS_OUT_OF_RANGE, (PIXEL_TYPE)0);
00107
00108 while (l < m) {
00109 register const PIXEL_TYPE x = self[k];
00110
00111 do {
00112 while (self[i] < x) i++;
00113 while (x < self[j]) j--;
00114 if (i <= j) {
00115 PIXEL_TYPE_SWAP(self[i], self[j]);
00116 i++; j--;
00117 }
00118 } while (i <= j);
00119
00120
00121
00122
00123
00124
00125
00126
00127 if (k <= j) {
00128
00129 m = j;
00130 i = l;
00131 } else {
00132 if (k < i) {
00133 m = j;
00134 } else {
00135 j = m;
00136 }
00137 l = i;
00138 }
00139 }
00140 return self[k];
00141 }
00142
00143
00144
00155
00156 static
00157 cpl_error_code TYPE_ADD(visir_util_clip_kappa_sigma)(cpl_imagelist * self,
00158 cpl_imagelist * devlist,
00159 double keepfrac,
00160 double kappa, int maxite,
00161 const int * shifts)
00162 {
00163 const int nz = cpl_imagelist_get_size(self);
00164 const cpl_image * img = cpl_imagelist_get_const(self, 0);
00165 const int nx = cpl_image_get_size_x(img);
00166 const int ny = cpl_image_get_size_y(img);
00167
00168 const int minrej = (int)((double)nz * 0.5 * (1.0 - keepfrac) + 0.5);
00169 PIXEL_TYPE * pvalues = (PIXEL_TYPE*)cpl_malloc(nz * sizeof(*pvalues));
00170
00171 const PIXEL_TYPE ** pimg = cpl_malloc((size_t)nz * sizeof(PIXEL_TYPE *));
00172 cpl_binary ** pbpm = cpl_malloc((size_t)nz * sizeof(cpl_binary *));
00173 cpl_image * imgstdev0 = cpl_image_new(nx, ny, STDEV_TYPE);
00174 cpl_image * imgstdevn = cpl_image_new(nx, ny, STDEV_TYPE);
00175 int k, i, j;
00176
00177
00178 bug_if(cpl_image_get_type(img) != PIXEL_TYPE_CPL);
00179
00180
00181
00182 error_if(keepfrac < 0.0, CPL_ERROR_ILLEGAL_INPUT, "Parameter keepfrac = "
00183 "%g < 0.0", keepfrac);
00184 error_if(keepfrac > 1.0, CPL_ERROR_ILLEGAL_INPUT, "Parameter keepfrac = "
00185 "%g > 1.0", keepfrac);
00186 error_if(kappa < 0.0, CPL_ERROR_ILLEGAL_INPUT, "Parameter kappa = "
00187 "%g < 0.0", kappa);
00188 error_if(maxite < 0, CPL_ERROR_ILLEGAL_INPUT, "Parameter maxite = "
00189 "%d < 0", maxite);
00190
00191 for (k = 0; k < nz; k++) {
00192 cpl_image * imgk = cpl_imagelist_get(self, k);
00193 cpl_mask * bpm = cpl_image_get_bpm(imgk);
00194
00195 pimg[k] = TYPE_ADD_CONST(cpl_image_get_data)(imgk);
00196 pbpm[k] = cpl_mask_get_data(bpm);
00197
00198 bug_if(pimg[k] == NULL);
00199 bug_if(pbpm[k] == NULL);
00200
00201 }
00202
00203 for (j = 0; j < ny; j++) {
00204 for (i = 0; i < nx; i++) {
00205 int nok = 0;
00206
00207 for (k = 0; k < nz; k++) {
00208 const int ii = (i + shifts[k * 2]) +
00209 (j + shifts[k * 2 + 1]) * nx;
00210 if (i + shifts[k * 2] >= nx || i + shifts[k * 2] < 0 ||
00211 j + shifts[k * 2 + 1] >= ny || j + shifts[k * 2 + 1] < 0)
00212 continue;
00213
00214 if (!pbpm[k][ii]) {
00215 pvalues[nok++] = pimg[k][ii];
00216 }
00217 }
00218
00219 if (nok > 1) {
00220
00221 const int ithmin = minrej - (nz - nok) / 2 - 1;
00222 double median, mean, stdev, varsum;
00223 PIXEL_TYPE * pmedian = pvalues;
00224 int nmedian = nok;
00225 int nite;
00226
00227 if (0 <= ithmin && 2 * ithmin + 3 <= nok) {
00228
00229
00230 const int ithmax = nok - ithmin - 1;
00231 (void)TYPE_ADD(cpl_tools_get_kth)(pvalues, nok, ithmax);
00232 (void)TYPE_ADD(cpl_tools_get_kth)(pvalues, ithmax, ithmin);
00233
00234 pmedian += ithmin + 1;
00235 nmedian -= ithmin * 2 + 2;
00236 }
00237 bug_if( nmedian <= 1 );
00238
00239 median = (double)TYPE_ADD(cpl_tools_get_kth)(pmedian, nmedian,
00240 (nmedian - 1) / 2);
00241 if (!(nmedian & 1)) {
00242
00243
00244 median += (double)TYPE_ADD(cpl_tools_get_kth)(pmedian +
00245 nmedian / 2,
00246 nmedian / 2,
00247 0);
00248 median *= 0.5;
00249 }
00250
00251 varsum = TYPE_ADD(cpl_tools_get_variancesum)(pmedian, nmedian,
00252 NULL);
00253 stdev = sqrt(varsum / (double)(nmedian - 1));
00254
00255 bug_if(cpl_image_set(imgstdev0, 1 + i, 1 + j, stdev));
00256
00257 for (nite = 0; nite < maxite; nite++) {
00258
00259 const double center = nite ? mean : median;
00260 const double lolim = center - kappa * stdev;
00261 const double hilim = center + kappa * stdev;
00262 const int prevok = nok;
00263
00264 nok = 0;
00265 mean = 0.0;
00266 varsum = 0.0;
00267
00268 for (k = 0; k < nz; k++) {
00269 const int ii = (i + shifts[k * 2]) +
00270 (j + shifts[k * 2 + 1]) * nx;
00271 if (i + shifts[k * 2] >= nx || i + shifts[k * 2] < 0 ||
00272 j + shifts[k * 2 + 1] >= ny || j + shifts[k * 2 + 1] < 0) {
00273 continue;
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 if (!pbpm[k][ii]) {
00286 if (lolim <= pimg[k][ii] &&
00287 pimg[k][ii] <= hilim) {
00288
00289
00290 const double delta =
00291 (double)pimg[k][ii] - mean;
00292
00293 varsum += nok * delta * delta
00294 / (double)(nok + 1);
00295 mean += delta / (double)(nok + 1);
00296
00297 nok++;
00298 } else {
00299
00300 cpl_msg_debug(cpl_func, "rejected");
00301 pbpm[k][ii] = CPL_BINARY_1;
00302 }
00303 }
00304 }
00305
00306 if (nok < 2) {
00307 stdev = 0.0;
00308 break;
00309 }
00310 if (nok == prevok) break;
00311 stdev = sqrt(varsum / (double)(nok - 1));
00312 }
00313 bug_if(cpl_image_set(imgstdevn, 1 + i, 1 + j, stdev));
00314 }
00315 }
00316 }
00317
00318 bug_if(cpl_imagelist_set(devlist, imgstdev0, 0));
00319 imgstdev0 = NULL;
00320 bug_if(cpl_imagelist_set(devlist, imgstdevn, 1));
00321 imgstdevn = NULL;
00322
00323 end_skip;
00324
00325 cpl_image_delete(imgstdev0);
00326 cpl_image_delete(imgstdevn);
00327 cpl_free(pvalues);
00328 cpl_free(pimg);
00329 cpl_free(pbpm);
00330
00331 return cpl_error_get_code();
00332 }
00333
00334 #undef PIXEL_TYPE_SWAP