30#define TYPE_ADD(a) CONCAT2X(a, PIXEL_TYPE)
31#define TYPE_ADD_CONST(a) CONCAT2X(a, CONCAT2X(PIXEL_TYPE, const))
34#define PIXEL_TYPE_SWAP(a, b) \
35 { register const PIXEL_TYPE t=(a); (a)=(b); (b)=t; }
37static PIXEL_TYPE TYPE_ADD(cpl_tools_get_kth)(PIXEL_TYPE *, int, int);
40double TYPE_ADD(cpl_tools_get_variancesum)(
const PIXEL_TYPE *, int,
double *,
57double TYPE_ADD(cpl_tools_get_variancesum)(
const PIXEL_TYPE * a,
58 int n,
double * pmean,
65 cpl_ensure(a != NULL, CPL_ERROR_NULL_INPUT, 0.0);
66 cpl_ensure(n >= 0, CPL_ERROR_ILLEGAL_INPUT, 0.0);
68 for (i=0; i < n; i++) {
69 const double delta = (double)a[i] - mean;
73 varsum += i * delta * delta * ri;
77 if (pmean != NULL) *pmean = mean;
99PIXEL_TYPE TYPE_ADD(cpl_tools_get_kth)(PIXEL_TYPE * self,
104 register int m = n - 1;
108 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, (PIXEL_TYPE)0);
109 cpl_ensure(k >= 0, CPL_ERROR_ILLEGAL_INPUT, (PIXEL_TYPE)0);
110 cpl_ensure(k < n, CPL_ERROR_ACCESS_OUT_OF_RANGE, (PIXEL_TYPE)0);
113 register const PIXEL_TYPE x = self[k];
116 while (self[i] < x) i++;
117 while (x < self[j]) j--;
119 PIXEL_TYPE_SWAP(self[i], self[j]);
161cpl_error_code TYPE_ADD(visir_util_clip_kappa_sigma)(cpl_imagelist * self,
162 cpl_imagelist * devlist,
164 double kappa,
int maxite,
167 const int nz = cpl_imagelist_get_size(self);
168 const cpl_image * img = cpl_imagelist_get_const(self, 0);
169 const int nx = cpl_image_get_size_x(img);
170 const int ny = cpl_image_get_size_y(img);
172 const int minrej = (int)((
double)nz * 0.5 * (1.0 - keepfrac) + 0.5);
173 PIXEL_TYPE * pvalues = (PIXEL_TYPE*)cpl_malloc(nz *
sizeof(*pvalues));
175 const PIXEL_TYPE ** pimg = cpl_malloc((
size_t)nz *
sizeof(PIXEL_TYPE *));
176 cpl_binary ** pbpm = cpl_malloc((
size_t)nz *
sizeof(cpl_binary *));
177 cpl_image * imgstdev0 = cpl_image_new(nx, ny, STDEV_TYPE);
178 cpl_image * imgstdevn = cpl_image_new(nx, ny, STDEV_TYPE);
186OMP_PRAGMA(omp critical(clip_rnok_precompute))
187 if (prnok == NULL || prnok_nz < nz) {
190 prnok = cpl_malloc(nz *
sizeof(prnok[0]));
191 for (
int i = 0; i < nz; i++) {
192 prnok[i] = 1. / (i + 1);
198 bug_if(cpl_image_get_type(img) != PIXEL_TYPE_CPL);
202 error_if(keepfrac < 0.0, CPL_ERROR_ILLEGAL_INPUT,
"Parameter keepfrac = "
203 "%g < 0.0", keepfrac);
204 error_if(keepfrac > 1.0, CPL_ERROR_ILLEGAL_INPUT,
"Parameter keepfrac = "
205 "%g > 1.0", keepfrac);
206 error_if(kappa < 0.0, CPL_ERROR_ILLEGAL_INPUT,
"Parameter kappa = "
208 error_if(maxite < 0, CPL_ERROR_ILLEGAL_INPUT,
"Parameter maxite = "
211 for (
int k = 0; k < nz; k++) {
212 cpl_image * imgk = cpl_imagelist_get(self, k);
213 cpl_mask * bpm = cpl_image_get_bpm(imgk);
215 pimg[k] = TYPE_ADD_CONST(cpl_image_get_data)(imgk);
216 pbpm[k] = cpl_mask_get_data(bpm);
218 bug_if(pimg[k] == NULL);
219 bug_if(pbpm[k] == NULL);
223 for (
int j = 0; j < ny; j++) {
224 for (
int i = 0; i < nx; i++) {
227 for (
int k = 0; k < nz; k++) {
228 const int ii = (i + shifts[k * 2]) +
229 (j + shifts[k * 2 + 1]) * nx;
230 if (i + shifts[k * 2] >= nx || i + shifts[k * 2] < 0 ||
231 j + shifts[k * 2 + 1] >= ny || j + shifts[k * 2 + 1] < 0)
235 pvalues[nok++] = pimg[k][ii];
241 const int ithmin = minrej - (nz - nok) / 2 - 1;
242 double median, mean, stdev, varsum;
243 PIXEL_TYPE * pmedian = pvalues;
246 if (0 <= ithmin && 2 * ithmin + 3 <= nok) {
249 const int ithmax = nok - ithmin - 1;
250 (void)TYPE_ADD(cpl_tools_get_kth)(pvalues, nok, ithmax);
251 (void)TYPE_ADD(cpl_tools_get_kth)(pvalues, ithmax, ithmin);
253 pmedian += ithmin + 1;
254 nmedian -= ithmin * 2 + 2;
256 bug_if( nmedian <= 1 );
258 median = (double)TYPE_ADD(cpl_tools_get_kth)(pmedian, nmedian,
260 if (!(nmedian & 1)) {
263 median += (double)TYPE_ADD(cpl_tools_get_kth)(pmedian +
270 varsum = TYPE_ADD(cpl_tools_get_variancesum)(pmedian, nmedian,
272 stdev = sqrt(varsum / (
double)(nmedian - 1));
274 bug_if(cpl_image_set(imgstdev0, 1 + i, 1 + j, stdev));
276 for (
int nite = 0; nite < maxite; nite++) {
278 const double center = nite ? mean : median;
279 const double lolim = center - kappa * stdev;
280 const double hilim = center + kappa * stdev;
281 const int prevok = nok;
287 for (
int k = 0; k < nz; k++) {
288 const int ii = (i + shifts[k * 2]) +
289 (j + shifts[k * 2 + 1]) * nx;
290 if (i + shifts[k * 2] >= nx || i + shifts[k * 2] < 0 ||
291 j + shifts[k * 2 + 1] >= ny || j + shifts[k * 2 + 1] < 0) {
305 if (lolim <= pimg[k][ii] &&
306 pimg[k][ii] <= hilim) {
310 (double)pimg[k][ii] - mean;
311 double rnok = prnok[nok];
314 varsum += nok * delta * delta * rnok;
315 mean += delta * rnok;
320 pbpm[k][ii] = CPL_BINARY_1;
329 if (nok == prevok)
break;
330 stdev = sqrt(varsum / (
double)(nok - 1));
332 bug_if(cpl_image_set(imgstdevn, 1 + i, 1 + j, stdev));
337 bug_if(cpl_imagelist_set(devlist, imgstdev0, 0));
339 bug_if(cpl_imagelist_set(devlist, imgstdevn, 1));
344 cpl_image_delete(imgstdev0);
345 cpl_image_delete(imgstdevn);
350 return cpl_error_get_code();
353#undef PIXEL_TYPE_SWAP