27 #include <cxmessages.h>
28 #include <cxstrutils.h>
32 #include <cpl_parameterlist.h>
33 #include <cpl_vector.h>
35 #include "gifiberutils.h"
37 #include "gistacking.h"
61 MIN_IMAGES_AVERAGE = 2,
62 MIN_IMAGES_MEDIAN = 3,
63 MIN_IMAGES_MINMAX = 3,
69 _image_array_count(GiImage **img_array)
73 if (img_array == NULL) {
77 while (img_array[count] != NULL) {
86 _image_array_same_size(GiImage **img_array)
94 num_images = _image_array_count(img_array);
96 if (num_images <= 0) {
103 for (i=1; i<num_images; i++) {
132 const cxchar *fctid =
"giraffe_stacking_average";
134 GiImage *result = NULL;
136 cxint num_images = 0,
144 cxdouble *pdresult = NULL,
151 num_images = _image_array_count(img_array);
154 cpl_msg_error(fctid,
"Empty array of images, aborting..." );
158 if (_image_array_same_size(img_array)==FALSE) {
159 cpl_msg_error(fctid,
"Input Images are not the same size, "
171 for (i = 0; i < npix; i++) {
175 for (i = 0; i < num_images; i++) {
182 inverse = 1.0 / num_images;
208 const cxchar *fctid =
"giraffe_stacking_median";
210 cxint num_images = 0;
218 cxdouble *pdresult = NULL;
219 cxdouble **pdimgs = NULL;
221 cpl_vector *zvalue = NULL;
223 GiImage *result = NULL;
229 num_images = _image_array_count(img_array);
231 if (num_images <= 0) {
232 cpl_msg_error(fctid,
"Empty array of images, aborting..." );
236 if (num_images < MIN_IMAGES_MEDIAN) {
237 cpl_msg_error(fctid,
"Not enough Images in array to perform median "
238 "stacking, aborting...");
242 if (_image_array_same_size(img_array) == FALSE) {
243 cpl_msg_error(fctid,
"Input Images are not the same size, "
255 pdimgs = cx_calloc(num_images,
sizeof(cxdouble*));
257 zvalue = cpl_vector_new(num_images);
259 for (i = 0; i < num_images; i++) {
263 for (j = 0; j < npix; j++) {
264 for (i = 0; i < num_images; i++) {
265 cpl_vector_set(zvalue, i, (pdimgs[i])[j]);
267 pdresult[j] = cpl_vector_get_median(zvalue);
270 cpl_vector_delete(zvalue);
309 const cxchar *fctid =
"giraffe_stacking_minmax";
317 cxint num_images = 0;
322 cxdouble daverage = 0.;
323 cxdouble dinvdeltan = 0.;
324 cxdouble *pdresult = NULL;
325 cxdouble **pdimgs = NULL;
327 cpl_vector *zvalue = NULL;
329 GiImage *result = NULL;
332 num_images = _image_array_count(img_array);
334 if (num_images <= 0) {
335 cpl_msg_error(fctid,
"Empty array of images, aborting...");
339 if (num_images < MIN_IMAGES_MINMAX) {
340 cpl_msg_error(fctid,
"Not enough Images in array to perform minmax "
341 "stacking, aborting...");
345 if (_image_array_same_size(img_array) == FALSE) {
346 cpl_msg_error(fctid,
"Input Images are not the same size, "
351 if ((config->rejectmin + config->rejectmax) >= num_images) {
352 cpl_msg_error(fctid,
"Max %d Input Images can be rejected, "
353 "aborting...", num_images - 1);
357 if ((config->rejectmin == 0) || (config->rejectmax == 0)) {
358 cpl_msg_error(fctid,
"At least one value should be rejected [%d,%d],"
359 " aborting...", config->rejectmin,
371 minn = config->rejectmin;
372 maxn = num_images - config->rejectmax;
374 dinvdeltan = 1. / (maxn - minn);
376 pdimgs = (cxdouble**) cx_calloc(num_images,
sizeof(cxdouble*));
378 zvalue = cpl_vector_new(num_images);
380 for (i = 0; i < num_images; i++) {
384 for (j = 0; j < npix; j++) {
385 for (i = 0; i < num_images; i++) {
386 cpl_vector_set(zvalue, i, (pdimgs[i])[j]);
389 cpl_vector_sort(zvalue, 1);
393 for (n = minn; n < maxn; n++) {
394 daverage += cpl_vector_get(zvalue, n);
397 pdresult[j] = daverage * dinvdeltan;
400 cpl_vector_delete(zvalue);
436 const cxchar *fctid =
"giraffe_stacking_ksigma";
442 cxint num_images = 0;
448 cxdouble *pdresult = NULL;
449 cxdouble **pdimgs = NULL;
451 cpl_vector *zvalue = NULL;
453 GiImage *result = NULL;
456 num_images = _image_array_count(img_array);
458 if (num_images <= 0) {
459 cpl_msg_error(fctid,
"Empty array of images, aborting...");
463 if (num_images < MIN_IMAGES_KSIGMA) {
464 cpl_msg_error(fctid,
"Not enough Images in array to perform "
465 "kappa-sigma stacking, aborting...");
469 if (_image_array_same_size(img_array) == FALSE) {
470 cpl_msg_error(fctid,
"Input Images are not the same size, "
482 pdimgs = (cxdouble**) cx_calloc(num_images,
sizeof(cxdouble*));
484 zvalue = cpl_vector_new(num_images);
486 for (i = 0; i < num_images; i++) {
490 for (j = 0; j < npix; j++) {
492 cxdouble median = 0.;
495 cxdouble low_median = 0.;
496 cxdouble high_median = 0.;
499 for (i = 0; i < num_images; i++) {
500 cpl_vector_set(zvalue, i, (pdimgs[i])[j]);
503 median = cpl_vector_get_median(zvalue);
505 for (n = 0; n < num_images; n++) {
506 sigma += fabs(cpl_vector_get(zvalue, n) - median);
511 low_median = median - ( sigma * config->ksigmalow );
512 high_median = median + ( sigma * config->ksigmahigh );
516 goodpix = num_images;
518 for (n = 0; n < num_images; n++) {
520 cxdouble _zvalue = cpl_vector_get(zvalue, n);
522 if ((_zvalue < low_median) || (_zvalue > high_median)) {
531 pdresult[j] = sum / goodpix;
534 cpl_vector_delete(zvalue);
572 const GiStackingConfig *config)
575 const cxchar *fctid =
"giraffe_stacking_stack_images";
577 GiImage *giimage_out;
578 cxint num_images = 0;
580 cpl_msg_debug(fctid,
"Procedure Start" );
582 if (config == NULL) {
586 if (img_array == NULL) {
590 num_images = _image_array_count(img_array);
592 switch (config->stackmethod) {
594 case GISTACKING_METHOD_AVERAGE :
596 cpl_msg_info(fctid,
"Combination method is Average");
597 cpl_msg_info(fctid,
"Averaging %d images\n", num_images);
603 case GISTACKING_METHOD_MEDIAN :
605 cpl_msg_info(fctid,
"Combination method is Median");
606 cpl_msg_info(fctid,
"Finding median of %d images", num_images);
612 case GISTACKING_METHOD_MINMAX :
614 cpl_msg_info(fctid,
"Combination method is MinMax Rejection");
617 "Rejecting lower %d and upper %d pixel values out of possible %d",
618 (cxint) (floor(num_images * config->rejectmin / 100.0)) + 1,
619 (cxint) (floor(num_images * config->rejectmax / 100.0)) + 1,
627 case GISTACKING_METHOD_KSIGMA :
629 cpl_msg_info(fctid,
"Combination method is K-Sigma Clipping");
632 "K Low = %3.1f sigma, K High = %3.1f sigma",
641 case GISTACKING_METHOD_UNDEFINED :
645 cpl_msg_error(fctid,
"Invalid stacking method, aborting...");
651 cpl_msg_debug(fctid,
"Procedure End" );
676 const cxchar *fctid =
"giraffe_stacking_config_create";
679 cxchar *method = NULL;
681 cpl_parameter *p = NULL;
683 GiStackingConfig *config = NULL;
690 config = cx_calloc(1,
sizeof *config);
697 config->stackmethod = GISTACKING_METHOD_UNDEFINED;
698 config->min_nr_frames = 0;
705 p = cpl_parameterlist_find(list,
"giraffe.stacking.method");
706 method = cx_strdup(cpl_parameter_get_string(p));
708 p = cpl_parameterlist_find(list,
"giraffe.stacking.ksigma.low");
709 config->ksigmalow = cpl_parameter_get_double(p);
711 p = cpl_parameterlist_find(list,
"giraffe.stacking.ksigma.high");
712 config->ksigmahigh = cpl_parameter_get_double(p);
714 p = cpl_parameterlist_find(list,
"giraffe.stacking.minmax.minimum");
715 config->rejectmin = cpl_parameter_get_int(p);
717 p = cpl_parameterlist_find(list,
"giraffe.stacking.minmax.maximum");
718 config->rejectmax = cpl_parameter_get_int(p);
725 if (strcmp(method,
"average") == 0) {
726 config->stackmethod = GISTACKING_METHOD_AVERAGE;
729 if (strcmp(method,
"median") == 0) {
730 config->stackmethod = GISTACKING_METHOD_MEDIAN;
733 if (strcmp(method,
"minmax") == 0) {
734 config->stackmethod = GISTACKING_METHOD_MINMAX;
737 if (strcmp(method,
"ksigma") == 0) {
738 config->stackmethod = GISTACKING_METHOD_KSIGMA;
743 switch (config->stackmethod) {
744 case GISTACKING_METHOD_AVERAGE:
745 config->min_nr_frames = MIN_IMAGES_AVERAGE;
748 case GISTACKING_METHOD_MEDIAN:
749 config->min_nr_frames = MIN_IMAGES_MEDIAN;
752 case GISTACKING_METHOD_MINMAX:
753 config->min_nr_frames = MIN_IMAGES_MINMAX;
756 case GISTACKING_METHOD_KSIGMA:
757 config->min_nr_frames = MIN_IMAGES_KSIGMA;
760 case GISTACKING_METHOD_UNDEFINED:
765 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
792 if (config != NULL) {
821 p = cpl_parameter_new_enum(
"giraffe.stacking.method",
823 "Stacking method: average, median, minmax or "
826 "average", 4,
"average",
"median",
829 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"stack-method");
830 cpl_parameterlist_append(list, p);
832 p = cpl_parameter_new_value(
"giraffe.stacking.ksigma.low",
834 "Lower threshold multiplier for method "
836 "giraffe.stacking.ksigma",
838 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"stack-ksigmalow");
839 cpl_parameterlist_append(list, p);
841 p = cpl_parameter_new_value(
"giraffe.stacking.ksigma.high",
843 "Upper threshold multiplier for method "
845 "giraffe.stacking.ksigma",
847 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"stack-ksigmahigh");
848 cpl_parameterlist_append(list, p);
850 p = cpl_parameter_new_value(
"giraffe.stacking.minmax.minimum",
852 "Minimum rejection level for method minmax",
853 "giraffe.stacking.minmax",
855 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"stack-minreject");
856 cpl_parameterlist_append(list, p);
858 p = cpl_parameter_new_value(
"giraffe.stacking.minmax.maximum",
860 "Maximum rejection level for method minmax",
861 "giraffe.stacking.minmax",
863 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"stack-maxreject");
864 cpl_parameterlist_append(list, p);
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
GiImage * giraffe_image_create(cpl_type type, cxint nx, cxint ny)
Creates an image container of a given type.
void giraffe_stacking_config_add(cpl_parameterlist *list)
Adds parameters for the stacking of images.
GiImage * giraffe_stacking_median(GiImage **img_array, const GiStackingConfig *config)
Stack a list of images using median and return the resulting image.
GiImage * giraffe_stacking_average(GiImage **img_array, const GiStackingConfig *config)
Stack a list of images using averaging and return the resulting image.
void giraffe_stacking_config_destroy(GiStackingConfig *config)
Destroys a setup structure for the stacking of images.
GiStackingConfig * giraffe_stacking_config_create(cpl_parameterlist *list)
Creates a setup structure for the stacking of images.
GiImage * giraffe_stacking_stack_images(GiImage **img_array, const GiStackingConfig *config)
Stack a list of images using one of four different kinds of stacking and return the resulting image.
GiImage * giraffe_stacking_ksigma(GiImage **img_array, const GiStackingConfig *config)
Stack a list of images using Kappa Sigma Clipping and return the resulting image.
GiImage * giraffe_stacking_minmax(GiImage **img_array, const GiStackingConfig *config)
Stack a list of images using minmax rejection and return the resulting image.