35 #include <cxmessages.h>
36 #include <cxstrutils.h>
40 #include <cpl_parameterlist.h>
41 #include <cpl_vector.h>
43 #include "gifiberutils.h"
45 #include "gistacking.h"
69 MIN_IMAGES_AVERAGE = 2,
70 MIN_IMAGES_MEDIAN = 3,
71 MIN_IMAGES_MINMAX = 3,
77 _image_array_count(GiImage **img_array)
81 if (img_array == NULL) {
85 while (img_array[count] != NULL) {
94 _image_array_same_size(GiImage **img_array)
102 num_images = _image_array_count(img_array);
104 if (num_images <= 0) {
111 for (i=1; i<num_images; i++) {
140 const cxchar *fctid =
"giraffe_stacking_average";
142 GiImage *result = NULL;
144 cxint num_images = 0,
152 cxdouble *pdresult = NULL,
159 num_images = _image_array_count(img_array);
162 cpl_msg_error(fctid,
"Empty array of images, aborting..." );
166 if (_image_array_same_size(img_array)==FALSE) {
167 cpl_msg_error(fctid,
"Input Images are not the same size, "
179 for (i = 0; i < npix; i++) {
183 for (i = 0; i < num_images; i++) {
190 inverse = 1.0 / num_images;
216 const cxchar *fctid =
"giraffe_stacking_median";
218 cxint num_images = 0;
226 cxdouble *pdresult = NULL;
227 cxdouble **pdimgs = NULL;
229 cpl_vector *zvalue = NULL;
231 GiImage *result = NULL;
237 num_images = _image_array_count(img_array);
239 if (num_images <= 0) {
240 cpl_msg_error(fctid,
"Empty array of images, aborting..." );
244 if (num_images < MIN_IMAGES_MEDIAN) {
245 cpl_msg_error(fctid,
"Not enough Images in array to perform median "
246 "stacking, aborting...");
250 if (_image_array_same_size(img_array) == FALSE) {
251 cpl_msg_error(fctid,
"Input Images are not the same size, "
263 pdimgs = cx_calloc(num_images,
sizeof(cxdouble*));
265 zvalue = cpl_vector_new(num_images);
267 for (i = 0; i < num_images; i++) {
271 for (j = 0; j < npix; j++) {
272 for (i = 0; i < num_images; i++) {
273 cpl_vector_set(zvalue, i, (pdimgs[i])[j]);
275 pdresult[j] = cpl_vector_get_median(zvalue);
278 cpl_vector_delete(zvalue);
317 const cxchar *fctid =
"giraffe_stacking_minmax";
325 cxint num_images = 0;
330 cxdouble daverage = 0.;
331 cxdouble dinvdeltan = 0.;
332 cxdouble *pdresult = NULL;
333 cxdouble **pdimgs = NULL;
335 cpl_vector *zvalue = NULL;
337 GiImage *result = NULL;
340 num_images = _image_array_count(img_array);
342 if (num_images <= 0) {
343 cpl_msg_error(fctid,
"Empty array of images, aborting...");
347 if (num_images < MIN_IMAGES_MINMAX) {
348 cpl_msg_error(fctid,
"Not enough Images in array to perform minmax "
349 "stacking, aborting...");
353 if (_image_array_same_size(img_array) == FALSE) {
354 cpl_msg_error(fctid,
"Input Images are not the same size, "
359 if ((config->rejectmin + config->rejectmax) >= num_images) {
360 cpl_msg_error(fctid,
"Max %d Input Images can be rejected, "
361 "aborting...", num_images - 1);
365 if ((config->rejectmin == 0) || (config->rejectmax == 0)) {
366 cpl_msg_error(fctid,
"At least one value should be rejected [%d,%d],"
367 " aborting...", config->rejectmin,
379 minn = config->rejectmin;
380 maxn = num_images - config->rejectmax;
382 dinvdeltan = 1. / (maxn - minn);
384 pdimgs = (cxdouble**) cx_calloc(num_images,
sizeof(cxdouble*));
386 zvalue = cpl_vector_new(num_images);
388 for (i = 0; i < num_images; i++) {
392 for (j = 0; j < npix; j++) {
393 for (i = 0; i < num_images; i++) {
394 cpl_vector_set(zvalue, i, (pdimgs[i])[j]);
397 cpl_vector_sort(zvalue, 1);
401 for (n = minn; n < maxn; n++) {
402 daverage += cpl_vector_get(zvalue, n);
405 pdresult[j] = daverage * dinvdeltan;
408 cpl_vector_delete(zvalue);
444 const cxchar *fctid =
"giraffe_stacking_ksigma";
450 cxint num_images = 0;
456 cxdouble *pdresult = NULL;
457 cxdouble **pdimgs = NULL;
459 cpl_vector *zvalue = NULL;
461 GiImage *result = NULL;
464 num_images = _image_array_count(img_array);
466 if (num_images <= 0) {
467 cpl_msg_error(fctid,
"Empty array of images, aborting...");
471 if (num_images < MIN_IMAGES_KSIGMA) {
472 cpl_msg_error(fctid,
"Not enough Images in array to perform "
473 "kappa-sigma stacking, aborting...");
477 if (_image_array_same_size(img_array) == FALSE) {
478 cpl_msg_error(fctid,
"Input Images are not the same size, "
490 pdimgs = (cxdouble**) cx_calloc(num_images,
sizeof(cxdouble*));
492 zvalue = cpl_vector_new(num_images);
494 for (i = 0; i < num_images; i++) {
498 for (j = 0; j < npix; j++) {
500 cxdouble median = 0.;
503 cxdouble low_median = 0.;
504 cxdouble high_median = 0.;
507 for (i = 0; i < num_images; i++) {
508 cpl_vector_set(zvalue, i, (pdimgs[i])[j]);
511 median = cpl_vector_get_median(zvalue);
513 for (n = 0; n < num_images; n++) {
514 sigma += fabs(cpl_vector_get(zvalue, n) - median);
519 low_median = median - ( sigma * config->ksigmalow );
520 high_median = median + ( sigma * config->ksigmahigh );
524 goodpix = num_images;
526 for (n = 0; n < num_images; n++) {
528 cxdouble _zvalue = cpl_vector_get(zvalue, n);
530 if ((_zvalue < low_median) || (_zvalue > high_median)) {
539 pdresult[j] = sum / goodpix;
542 cpl_vector_delete(zvalue);
580 const GiStackingConfig *config)
583 const cxchar *fctid =
"giraffe_stacking_stack_images";
585 GiImage *giimage_out;
586 cxint num_images = 0;
588 cpl_msg_debug(fctid,
"Procedure Start" );
590 if (config == NULL) {
594 if (img_array == NULL) {
598 num_images = _image_array_count(img_array);
600 switch (config->stackmethod) {
602 case GISTACKING_METHOD_AVERAGE :
604 cpl_msg_info(fctid,
"Combination method is Average");
605 cpl_msg_info(fctid,
"Averaging %d images\n", num_images);
611 case GISTACKING_METHOD_MEDIAN :
613 cpl_msg_info(fctid,
"Combination method is Median");
614 cpl_msg_info(fctid,
"Finding median of %d images", num_images);
620 case GISTACKING_METHOD_MINMAX :
622 cpl_msg_info(fctid,
"Combination method is MinMax Rejection");
625 "Rejecting lower %d and upper %d pixel values out of possible %d",
626 (cxint) (floor(num_images * config->rejectmin / 100.0)) + 1,
627 (cxint) (floor(num_images * config->rejectmax / 100.0)) + 1,
635 case GISTACKING_METHOD_KSIGMA :
637 cpl_msg_info(fctid,
"Combination method is K-Sigma Clipping");
640 "K Low = %3.1f sigma, K High = %3.1f sigma",
649 case GISTACKING_METHOD_UNDEFINED :
653 cpl_msg_error(fctid,
"Invalid stacking method, aborting...");
659 cpl_msg_debug(fctid,
"Procedure End" );
684 const cxchar *fctid =
"giraffe_stacking_config_create";
687 cxchar *method = NULL;
689 cpl_parameter *p = NULL;
691 GiStackingConfig *config = NULL;
698 config = cx_calloc(1,
sizeof *config);
705 config->stackmethod = GISTACKING_METHOD_UNDEFINED;
706 config->min_nr_frames = 0;
713 p = cpl_parameterlist_find(list,
"giraffe.stacking.method");
714 method = cx_strdup(cpl_parameter_get_string(p));
716 p = cpl_parameterlist_find(list,
"giraffe.stacking.ksigma.low");
717 config->ksigmalow = cpl_parameter_get_double(p);
719 p = cpl_parameterlist_find(list,
"giraffe.stacking.ksigma.high");
720 config->ksigmahigh = cpl_parameter_get_double(p);
722 p = cpl_parameterlist_find(list,
"giraffe.stacking.minmax.minimum");
723 config->rejectmin = cpl_parameter_get_int(p);
725 p = cpl_parameterlist_find(list,
"giraffe.stacking.minmax.maximum");
726 config->rejectmax = cpl_parameter_get_int(p);
733 if (strcmp(method,
"average") == 0) {
734 config->stackmethod = GISTACKING_METHOD_AVERAGE;
737 if (strcmp(method,
"median") == 0) {
738 config->stackmethod = GISTACKING_METHOD_MEDIAN;
741 if (strcmp(method,
"minmax") == 0) {
742 config->stackmethod = GISTACKING_METHOD_MINMAX;
745 if (strcmp(method,
"ksigma") == 0) {
746 config->stackmethod = GISTACKING_METHOD_KSIGMA;
751 switch (config->stackmethod) {
752 case GISTACKING_METHOD_AVERAGE:
753 config->min_nr_frames = MIN_IMAGES_AVERAGE;
756 case GISTACKING_METHOD_MEDIAN:
757 config->min_nr_frames = MIN_IMAGES_MEDIAN;
760 case GISTACKING_METHOD_MINMAX:
761 config->min_nr_frames = MIN_IMAGES_MINMAX;
764 case GISTACKING_METHOD_KSIGMA:
765 config->min_nr_frames = MIN_IMAGES_KSIGMA;
768 case GISTACKING_METHOD_UNDEFINED:
773 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
800 if (config != NULL) {
829 p = cpl_parameter_new_enum(
"giraffe.stacking.method",
831 "Stacking method: average, median, minmax or "
834 "average", 4,
"average",
"median",
837 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"stack-method");
838 cpl_parameterlist_append(list, p);
840 p = cpl_parameter_new_value(
"giraffe.stacking.ksigma.low",
842 "Lower threshold multiplier for method "
844 "giraffe.stacking.ksigma",
846 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"stack-ksigmalow");
847 cpl_parameterlist_append(list, p);
849 p = cpl_parameter_new_value(
"giraffe.stacking.ksigma.high",
851 "Upper threshold multiplier for method "
853 "giraffe.stacking.ksigma",
855 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"stack-ksigmahigh");
856 cpl_parameterlist_append(list, p);
858 p = cpl_parameter_new_value(
"giraffe.stacking.minmax.minimum",
860 "Minimum rejection level for method minmax",
861 "giraffe.stacking.minmax",
863 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"stack-minreject");
864 cpl_parameterlist_append(list, p);
866 p = cpl_parameter_new_value(
"giraffe.stacking.minmax.maximum",
868 "Maximum rejection level for method minmax",
869 "giraffe.stacking.minmax",
871 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"stack-maxreject");
872 cpl_parameterlist_append(list, p);