CR2RE Pipeline Reference Manual 1.6.7
hdrl_bpm_2d.c
1/*
2 * This file is part of the HDRL
3 * Copyright (C) 2013,2014 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26-----------------------------------------------------------------------------*/
27
28#include "hdrl_types.h"
29#include "hdrl_image.h"
30#include "hdrl_imagelist.h"
31#include "hdrl_utils.h"
32
33#include "hdrl_bpm_2d.h"
34#include "hdrl_prototyping.h"
35
36#include <cpl.h>
37#include <string.h>
38#include <math.h>
39
40/*-----------------------------------------------------------------------------
41 Static
42 -----------------------------------------------------------------------------*/
43
44
54/*----------------------------------------------------------------------------*/
75/*----------------------------------------------------------------------------*/
76
82static cpl_image * hdrl_get_residuals_filtersmooth(cpl_size, cpl_size,
83 cpl_filter_mode, cpl_border_mode, cpl_image *, cpl_mask *);
84static cpl_image * hdrl_get_residuals_legendresmooth(const cpl_image *, int,
85 int, int, int, int, int) ;
86
87/*-----------------------------------------------------------------------------
88 BPM Parameters Definition
89 -----------------------------------------------------------------------------*/
90typedef struct {
91 HDRL_PARAMETER_HEAD;
92 cpl_filter_mode filter ;
93 cpl_border_mode border ;
94 double kappa_low ;
95 double kappa_high ;
96 int maxiter ;
97 int steps_x ;
98 int steps_y ;
99 int filter_size_x ;
100 int filter_size_y ;
101 int order_x ;
102 int order_y ;
103 int smooth_x ;
104 int smooth_y ;
105 hdrl_bpm_2d_method method ;
106} hdrl_bpm_2d_parameter;
107
108/* Parameter type */
109static hdrl_parameter_typeobj hdrl_bpm_2d_parameter_type = {
110 HDRL_PARAMETER_BPM_2D, /* type */
111 (hdrl_alloc *)&cpl_malloc, /* fp_alloc */
112 (hdrl_free *)&cpl_free, /* fp_free */
113 NULL, /* fp_destroy */
114 sizeof(hdrl_bpm_2d_parameter), /* obj_size */
115};
118/*----------------------------------------------------------------------------*/
136/*----------------------------------------------------------------------------*/
138 double kappa_low,
139 double kappa_high,
140 int maxiter,
141 cpl_filter_mode filter,
142 cpl_border_mode border,
143 int smooth_x,
144 int smooth_y)
145{
146 hdrl_bpm_2d_parameter * p = (hdrl_bpm_2d_parameter *)
147 hdrl_parameter_new(&hdrl_bpm_2d_parameter_type);
148 p->kappa_low = kappa_low ;
149 p->kappa_high = kappa_high ;
150 p->maxiter = maxiter ;
151 p->filter = filter ;
152 p->border = border ;
153 p->smooth_x = smooth_x ;
154 p->smooth_y = smooth_y ;
155 p->steps_x = 0 ;
156 p->steps_y = 0 ;
157 p->filter_size_x = 0 ;
158 p->filter_size_y = 0 ;
159 p->order_x = 0 ;
160 p->order_y = 0 ;
161 p->method = HDRL_BPM_2D_FILTERSMOOTH ;
162
163 if (hdrl_bpm_2d_parameter_verify((hdrl_parameter*)p) != CPL_ERROR_NONE) {
164 cpl_free(p);
165 return NULL;
166 }
167 return (hdrl_parameter *)p;
168}
169
170/*----------------------------------------------------------------------------*/
190/*----------------------------------------------------------------------------*/
192 double kappa_low,
193 double kappa_high,
194 int maxiter,
195 int steps_x,
196 int steps_y,
197 int filter_size_x,
198 int filter_size_y,
199 int order_x,
200 int order_y)
201{
202 hdrl_bpm_2d_parameter * p = (hdrl_bpm_2d_parameter *)
203 hdrl_parameter_new(&hdrl_bpm_2d_parameter_type);
204 p->kappa_low = kappa_low ;
205 p->kappa_high = kappa_high ;
206 p->maxiter = maxiter ;
207 p->filter = CPL_FILTER_MEDIAN ;
208 p->border = CPL_BORDER_FILTER ;
209 p->smooth_x = 0 ;
210 p->smooth_y = 0 ;
211 p->steps_x = steps_x ;
212 p->steps_y = steps_y ;
213 p->filter_size_x = filter_size_x ;
214 p->filter_size_y = filter_size_y ;
215 p->order_x = order_x ;
216 p->order_y = order_y ;
217 p->method = HDRL_BPM_2D_LEGENDRESMOOTH ;
218 if (hdrl_bpm_2d_parameter_verify((hdrl_parameter*)p) != CPL_ERROR_NONE) {
219 cpl_free(p);
220 return NULL;
221 }
222 return (hdrl_parameter *)p;
223}
224
225/*----------------------------------------------------------------------------*/
231/*----------------------------------------------------------------------------*/
233 const hdrl_parameter * param)
234{
235 const hdrl_bpm_2d_parameter * param_loc = (const hdrl_bpm_2d_parameter *)param ;
236
237 cpl_error_ensure(param != NULL, CPL_ERROR_NULL_INPUT,
238 return CPL_ERROR_NULL_INPUT, "NULL Input Parameters");
239 cpl_error_ensure(hdrl_bpm_2d_parameter_check(param),
240 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
241 "Expected BPM_2d parameter") ;
242
243 cpl_error_ensure(param_loc->method == HDRL_BPM_2D_LEGENDRESMOOTH ||
244 param_loc->method == HDRL_BPM_2D_FILTERSMOOTH,
245 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
246 "Unsupported method");
247
248 switch (param_loc->method) {
249 case HDRL_BPM_2D_FILTERSMOOTH:
250 cpl_error_ensure(param_loc->smooth_x >= 0, CPL_ERROR_ILLEGAL_INPUT,
251 return CPL_ERROR_ILLEGAL_INPUT, "smooth-x must be >=0");
252 cpl_error_ensure(param_loc->smooth_y >= 0, CPL_ERROR_ILLEGAL_INPUT,
253 return CPL_ERROR_ILLEGAL_INPUT, "smooth-y must be >=0");
254 /* Only odd-sized kernel are allowed */
255 cpl_error_ensure(((param_loc->smooth_x)&1) == 1, CPL_ERROR_ILLEGAL_INPUT,
256 return CPL_ERROR_ILLEGAL_INPUT, "smooth-x must be odd");
257 cpl_error_ensure(((param_loc->smooth_y)&1) == 1, CPL_ERROR_ILLEGAL_INPUT,
258 return CPL_ERROR_ILLEGAL_INPUT, "smooth-y must be odd");
259 if (param_loc->filter != CPL_FILTER_AVERAGE &&
260 param_loc->filter != CPL_FILTER_AVERAGE_FAST &&
261 param_loc->filter != CPL_FILTER_MEDIAN) {
262 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
263 "Function only supports filters: "
264 "CPL_FILTER_AVERAGE, CPL_FILTER_AVERAGE_FAST "
265 "and CPL_FILTER_MEDIAN");
266 return CPL_ERROR_ILLEGAL_INPUT;
267 }
268 break ;
269 case HDRL_BPM_2D_LEGENDRESMOOTH:
270 cpl_error_ensure(param_loc->order_x >= 0, CPL_ERROR_ILLEGAL_INPUT,
271 return CPL_ERROR_ILLEGAL_INPUT, "order-x must be >= 0");
272 cpl_error_ensure(param_loc->order_y >= 0, CPL_ERROR_ILLEGAL_INPUT,
273 return CPL_ERROR_ILLEGAL_INPUT, "order-y must be >= 0");
274 cpl_error_ensure(param_loc->steps_x > param_loc->order_x, CPL_ERROR_ILLEGAL_INPUT,
275 return CPL_ERROR_ILLEGAL_INPUT, "stepx_x must be > order-x");
276 cpl_error_ensure(param_loc->steps_y > param_loc->order_y, CPL_ERROR_ILLEGAL_INPUT,
277 return CPL_ERROR_ILLEGAL_INPUT, "stepx_y must be > order-y");
278 cpl_error_ensure(param_loc->filter_size_x > 0, CPL_ERROR_ILLEGAL_INPUT,
279 return CPL_ERROR_ILLEGAL_INPUT, "filter-size-x must be > 0");
280 cpl_error_ensure(param_loc->filter_size_y > 0, CPL_ERROR_ILLEGAL_INPUT,
281 return CPL_ERROR_ILLEGAL_INPUT, "filter-size-y must be > 0");
282 break ;
283 }
284
285 cpl_error_ensure(param_loc->kappa_low >= 0, CPL_ERROR_ILLEGAL_INPUT,
286 return CPL_ERROR_ILLEGAL_INPUT, "kappa-low must be >=0");
287 cpl_error_ensure(param_loc->kappa_high >= 0, CPL_ERROR_ILLEGAL_INPUT,
288 return CPL_ERROR_ILLEGAL_INPUT, "kappa-high must be >=0");
289 cpl_error_ensure(param_loc->maxiter >= 0, CPL_ERROR_ILLEGAL_INPUT,
290 return CPL_ERROR_ILLEGAL_INPUT, "maxiter must be >=0");
291 return CPL_ERROR_NONE ;
292}
293
294/*----------------------------------------------------------------------------*/
300/*----------------------------------------------------------------------------*/
301cpl_boolean hdrl_bpm_2d_parameter_check(const hdrl_parameter * self)
302{
303 return hdrl_parameter_check_type(self, &hdrl_bpm_2d_parameter_type);
304}
305
306/*----------------------------------------------------------------------------*/
312/*----------------------------------------------------------------------------*/
314 const hdrl_parameter * p)
315{
316 cpl_ensure(p, CPL_ERROR_NULL_INPUT, CPL_FILTER_EROSION);
317 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->filter : CPL_FILTER_EROSION;
318}
319
320/*----------------------------------------------------------------------------*/
326/*----------------------------------------------------------------------------*/
328 const hdrl_parameter * p)
329{
330 cpl_ensure(p, CPL_ERROR_NULL_INPUT, CPL_BORDER_FILTER);
331 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->border : CPL_BORDER_FILTER;
332}
333
334/*----------------------------------------------------------------------------*/
340/*----------------------------------------------------------------------------*/
342 const hdrl_parameter * p)
343{
344 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1.0);
345 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->kappa_low : 0.;
346}
347
348/*----------------------------------------------------------------------------*/
354/*----------------------------------------------------------------------------*/
356 const hdrl_parameter * p)
357{
358 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1.0);
359 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->kappa_high : 0.;
360}
361
362/*----------------------------------------------------------------------------*/
368/*----------------------------------------------------------------------------*/
370 const hdrl_parameter * p)
371{
372 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
373 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->maxiter : 0;
374}
375
376/*----------------------------------------------------------------------------*/
382/*----------------------------------------------------------------------------*/
384 const hdrl_parameter * p)
385{
386 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
387 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->steps_x : 0;
388}
389
390/*----------------------------------------------------------------------------*/
396/*----------------------------------------------------------------------------*/
398 const hdrl_parameter * p)
399{
400 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
401 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->steps_y : 0;
402}
403
404/*----------------------------------------------------------------------------*/
410/*----------------------------------------------------------------------------*/
412 const hdrl_parameter * p)
413{
414 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
415 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->filter_size_x : 0;
416}
417
418/*----------------------------------------------------------------------------*/
424/*----------------------------------------------------------------------------*/
426 const hdrl_parameter * p)
427{
428 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
429 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->filter_size_y : 0;
430}
431
432/*----------------------------------------------------------------------------*/
438/*----------------------------------------------------------------------------*/
440 const hdrl_parameter * p)
441{
442 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
443 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->order_x : 0;
444}
445
446/*----------------------------------------------------------------------------*/
452/*----------------------------------------------------------------------------*/
454 const hdrl_parameter * p)
455{
456 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
457 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->order_y : 0;
458}
459
460/*----------------------------------------------------------------------------*/
466/*----------------------------------------------------------------------------*/
468 const hdrl_parameter * p)
469{
470 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
471 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->smooth_y : 0;
472}
473
474/*----------------------------------------------------------------------------*/
480/*----------------------------------------------------------------------------*/
482 const hdrl_parameter * p)
483{
484 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
485 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->smooth_x : 0;
486}
487
488/*----------------------------------------------------------------------------*/
494/*----------------------------------------------------------------------------*/
496 const hdrl_parameter * p)
497{
498 cpl_ensure(p, CPL_ERROR_NULL_INPUT, HDRL_BPM_2D_LEGENDRESMOOTH);
499 return p != NULL ? ((const hdrl_bpm_2d_parameter *)p)->method : HDRL_BPM_2D_LEGENDRESMOOTH;
500}
501
502/*----------------------------------------------------------------------------*/
522/*----------------------------------------------------------------------------*/
523static cpl_parameterlist * hdrl_bpm_2d_legendresmooth_parameter_create_parlist(
524 const char *base_context,
525 const char *prefix,
526 const hdrl_parameter *deflt)
527{
528 cpl_ensure(prefix && base_context && deflt,
529 CPL_ERROR_NULL_INPUT, NULL);
530
531 cpl_ensure(hdrl_bpm_2d_parameter_check(deflt),
532 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
533
534 cpl_parameterlist * parlist = cpl_parameterlist_new();
535 char * context =
536 hdrl_join_string(".", 2, base_context, prefix);
537
538 double kappa_low_def = hdrl_bpm_2d_parameter_get_kappa_low(deflt);
539 double kappa_high_def = hdrl_bpm_2d_parameter_get_kappa_high(deflt);
540 int maxiter_def = hdrl_bpm_2d_parameter_get_maxiter(deflt);
541
542 /* --prefix.kappa_low */
543 hdrl_setup_vparameter(parlist, prefix, ".", "", "kappa-low", base_context,
544 "Low RMS scaling factor for image thresholding", CPL_TYPE_DOUBLE,
545 kappa_low_def) ;
546
547 /* --prefix.kappa_high */
548 hdrl_setup_vparameter(parlist, prefix, ".", "", "kappa-high", base_context,
549 "High RMS scaling factor for image thresholding", CPL_TYPE_DOUBLE,
550 kappa_high_def) ;
551
552 /* --prefix.maxiter */
553 hdrl_setup_vparameter(parlist, prefix, ".", "", "maxiter", base_context,
554 "Maximum number of algorithm iterations", CPL_TYPE_INT, maxiter_def);
555
556 /* --prefix.steps_x */
557 hdrl_setup_vparameter(parlist, prefix, ".", "", "steps-x",
558 base_context, "Number of image sampling points in x-dir for fitting",
559 CPL_TYPE_INT, hdrl_bpm_2d_parameter_get_steps_x(deflt));
560
561 /* --prefix.steps_y */
562 hdrl_setup_vparameter(parlist, prefix, ".", "", "steps-y",
563 base_context, "Number of image sampling points in y-dir for fitting",
564 CPL_TYPE_INT, hdrl_bpm_2d_parameter_get_steps_y(deflt)) ;
565
566 /* --prefix.filter_size_x */
567 hdrl_setup_vparameter(parlist, prefix, ".", "", "filter-size-x",
568 base_context, "X size of the median box around sampling points", CPL_TYPE_INT,
570
571 /* --prefix.filter_size_y */
572 hdrl_setup_vparameter(parlist, prefix, ".", "", "filter-size-y",
573 base_context, "Y size of the median box around sampling points", CPL_TYPE_INT,
575
576 /* --prefix.order_x */
577 hdrl_setup_vparameter(parlist, prefix, ".", "", "order-x",
578 base_context, "Order of x polynomial for the fit", CPL_TYPE_INT,
580
581 /* --prefix.order_y */
582 hdrl_setup_vparameter(parlist, prefix, ".", "", "order-y",
583 base_context, "Order of y polynomial for the fit", CPL_TYPE_INT,
585
586
587 cpl_free(context);
588 if (cpl_error_get_code()) {
589 cpl_parameterlist_delete(parlist);
590 return NULL;
591 }
592 return parlist;
593}
594
595
596static const char * filter_to_string(cpl_filter_mode filter)
597{
598 switch (filter) {
599 case CPL_FILTER_EROSION:
600 return "EROSION";
601 break;
602 case CPL_FILTER_DILATION:
603 return "DILATION";
604 break;
605 case CPL_FILTER_OPENING:
606 return "OPENING";
607 break;
608 case CPL_FILTER_CLOSING:
609 return "CLOSING";
610 break;
611 case CPL_FILTER_LINEAR:
612 return "LINEAR";
613 break;
614 case CPL_FILTER_LINEAR_SCALE:
615 return "LINEAR_SCALE";
616 break;
617 case CPL_FILTER_AVERAGE:
618 return "AVERAGE";
619 break;
620 case CPL_FILTER_AVERAGE_FAST:
621 return "AVERAGE_FAST";
622 break;
623 case CPL_FILTER_MEDIAN:
624 return "MEDIAN";
625 break;
626 case CPL_FILTER_STDEV:
627 return "STDEV";
628 break;
629 case CPL_FILTER_STDEV_FAST:
630 return "STDEV_FAST";
631 break;
632 case CPL_FILTER_MORPHO:
633 return "MORPHO";
634 break;
635 case CPL_FILTER_MORPHO_SCALE:
636 return "MORPHO_SCALE";
637 break;
638 default :
639 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT, "Filter unknown");
640 return "";
641 break;
642 }
643}
644
645static const char * border_to_string(cpl_border_mode border)
646{
647 switch (border) {
648 case CPL_BORDER_FILTER:
649 return "FILTER";
650 break;
651 case CPL_BORDER_ZERO:
652 return "ZERO";
653 break;
654 case CPL_BORDER_CROP:
655 return "CROP";
656 break;
657 case CPL_BORDER_NOP:
658 return "NOP";
659 break;
660 case CPL_BORDER_COPY:
661 return "COPY";
662 break;
663 default :
664 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT, "border unknown");
665 return "";
666 break;
667 }
668}
669
670/*----------------------------------------------------------------------------*/
688/*----------------------------------------------------------------------------*/
689static cpl_parameterlist * hdrl_bpm_2d_filtersmooth_parameter_create_parlist(
690 const char *base_context,
691 const char *prefix,
692 const hdrl_parameter *deflt)
693{
694 cpl_ensure(prefix && base_context && deflt,
695 CPL_ERROR_NULL_INPUT, NULL);
696
697 cpl_ensure(hdrl_bpm_2d_parameter_check(deflt),
698 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
699
700 char * name ;
701 cpl_parameterlist * parlist = cpl_parameterlist_new();
702 cpl_parameter * par ;
703 char * context =
704 hdrl_join_string(".", 2, base_context, prefix);
705
706 double kappa_low_def = hdrl_bpm_2d_parameter_get_kappa_low(deflt);
707 double kappa_high_def = hdrl_bpm_2d_parameter_get_kappa_high(deflt);
708 int maxiter_def = hdrl_bpm_2d_parameter_get_maxiter(deflt);
709
710 /* --prefix.kappa_low */
711 hdrl_setup_vparameter(parlist, prefix, ".", "", "kappa-low", base_context,
712 "Low RMS scaling factor for image thresholding", CPL_TYPE_DOUBLE, kappa_low_def) ;
713
714 /* --prefix.kappa_high */
715 hdrl_setup_vparameter(parlist, prefix, ".", "", "kappa-high", base_context,
716 "High RMS scaling factor for image thresholding", CPL_TYPE_DOUBLE, kappa_high_def) ;
717
718 /* --prefix.maxiter */
719 hdrl_setup_vparameter(parlist, prefix, ".", "", "maxiter", base_context,
720 "Maximum number of algorithm iterations", CPL_TYPE_INT, maxiter_def);
721
722 /* --prefix.filter */
723 cpl_filter_mode filter = hdrl_bpm_2d_parameter_get_filter(deflt);
724 const char * filter_def = filter_to_string(filter);
725 name = hdrl_join_string(".", 2, context, "filter");
726 par = cpl_parameter_new_enum(name, CPL_TYPE_STRING, "Filter mode for image smooting",
727 context, filter_def, 3, "AVERAGE", "AVERAGE_FAST", "MEDIAN");
728 cpl_free(name);
729 name = hdrl_join_string(".", 2, prefix, "filter");
730 cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI, name);
731 cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
732 cpl_free(name);
733 cpl_parameterlist_append(parlist, par);
734
735 /* --prefix.border */
736 cpl_border_mode border = hdrl_bpm_2d_parameter_get_border(deflt);
737 const char * border_def = border_to_string(border);
738 name = hdrl_join_string(".", 2, context, "border");
739 par = cpl_parameter_new_enum(name, CPL_TYPE_STRING,
740 "Border mode to use for the image smooting filter "
741 "(only for MEDIAN filter)",
742 context, border_def, 4, "FILTER", "CROP", "NOP", "COPY");
743 cpl_free(name);
744 name = hdrl_join_string(".", 2, prefix, "border");
745 cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI, name);
746 cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
747 cpl_free(name);
748 cpl_parameterlist_append(parlist, par);
749
750 /* --prefix.smooth_x */
751 hdrl_setup_vparameter(parlist, prefix, ".", "", "smooth-x",
752 base_context, "Kernel y size of the smoothing filter", CPL_TYPE_INT,
754
755 /* --prefix.smooth_y */
756 hdrl_setup_vparameter(parlist, prefix, ".", "", "smooth-y",
757 base_context, "Kernel y size of the image smoothing filter", CPL_TYPE_INT,
759
760 cpl_free(context);
761 if (cpl_error_get_code()) {
762 cpl_parameterlist_delete(parlist);
763 return NULL;
764 }
765
766 return parlist;
767}
768
769/*----------------------------------------------------------------------------*/
797/*----------------------------------------------------------------------------*/
799 const char *base_context,
800 const char *prefix,
801 const char *method_def,
802 const hdrl_parameter *filtersmooth_def,
803 const hdrl_parameter *legendresmooth_def)
804{
805 cpl_ensure(prefix && base_context && method_def,
806 CPL_ERROR_NULL_INPUT, NULL);
807
808 cpl_ensure(filtersmooth_def || legendresmooth_def,
809 CPL_ERROR_NULL_INPUT, NULL);
810
811 if(filtersmooth_def){
812 cpl_ensure(hdrl_bpm_2d_parameter_check(filtersmooth_def),
813 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
814 }
815
816 if(legendresmooth_def){
817 cpl_ensure(hdrl_bpm_2d_parameter_check(legendresmooth_def),
818 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
819 }
820
821 char * name ;
822 cpl_parameterlist * parlist = cpl_parameterlist_new();
823 cpl_parameter * par ;
824 char * context =
825 hdrl_join_string(".", 2, base_context, prefix);
826
827 /* --prefix.method */
828 name = hdrl_join_string(".", 2, context, "method");
829 par = cpl_parameter_new_enum(name, CPL_TYPE_STRING, "Method used", context,
830 method_def, 2, "FILTER", "LEGENDRE");
831 cpl_free(name);
832 name = hdrl_join_string(".", 2, prefix, "method");
833 cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI, name);
834 cpl_free(name);
835 cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
836 cpl_parameterlist_append(parlist, par);
837
838 /* --prefix.legendre */
839 name = hdrl_join_string(".", 2, prefix, "legendre");
840 cpl_parameterlist * pleg = hdrl_bpm_2d_legendresmooth_parameter_create_parlist(
841 base_context, name, legendresmooth_def);
842 cpl_free(name);
843 for (cpl_parameter * p = cpl_parameterlist_get_first(pleg) ;
844 p != NULL; p = cpl_parameterlist_get_next(pleg))
845 cpl_parameterlist_append(parlist, cpl_parameter_duplicate(p));
846 cpl_parameterlist_delete(pleg);
847
848 /* --prefix.filter */
849 name = hdrl_join_string(".", 2, prefix, "filter");
850 cpl_parameterlist * pfil = hdrl_bpm_2d_filtersmooth_parameter_create_parlist(
851 base_context, name, filtersmooth_def);
852 cpl_free(name);
853 for (cpl_parameter * p = cpl_parameterlist_get_first(pfil) ;
854 p != NULL; p = cpl_parameterlist_get_next(pfil))
855 cpl_parameterlist_append(parlist, cpl_parameter_duplicate(p));
856 cpl_parameterlist_delete(pfil);
857
858 cpl_free(context);
859 if (cpl_error_get_code()) {
860 cpl_parameterlist_delete(parlist);
861 return NULL;
862 }
863
864 return parlist;
865}
866
867/*----------------------------------------------------------------------------*/
895/*----------------------------------------------------------------------------*/
897 const cpl_parameterlist * parlist,
898 const char * prefix)
899{
900 cpl_ensure(prefix && parlist, CPL_ERROR_NULL_INPUT, NULL);
901 char * name ;
902 const cpl_parameter * par;
903 const char * tmp_str;
904 cpl_filter_mode filter = CPL_FILTER_EROSION ;
905 cpl_border_mode border = CPL_BORDER_FILTER ;
906 double kappa_low = -1.0 ;
907 double kappa_high = -1.0 ;
908 int maxiter = -1;
909 int steps_x = -1 ;
910 int steps_y = -1 ;
911 int filter_size_x = -1 ;
912 int filter_size_y = -1 ;
913 int order_x = -1 ;
914 int order_y = -1 ;
915 cpl_size smooth_x = -1 ;
916 cpl_size smooth_y = -1 ;
917 hdrl_bpm_2d_method method ;
918
919 /* --method */
920 name = hdrl_join_string(".", 2, prefix, "method");
921 par = cpl_parameterlist_find_const(parlist, name) ;
922 tmp_str = cpl_parameter_get_string(par);
923 if (tmp_str == NULL) {
924 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
925 "Parameter %s not found", name);
926 cpl_free(name);
927 return NULL;
928 }
929 cpl_free(name) ;
930 if(!strcmp(tmp_str, "FILTER")) {
931 method = HDRL_BPM_2D_FILTERSMOOTH ;
932 } else if(!strcmp(tmp_str, "LEGENDRE")) {
933 method = HDRL_BPM_2D_LEGENDRESMOOTH ;
934 } else {
935 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
936 "Invalid method: %s", tmp_str);
937 return NULL;
938 }
939
940 char * kappa_prefix = hdrl_join_string(".", 2, prefix,
941 method == HDRL_BPM_2D_FILTERSMOOTH ?
942 "filter" : "legendre" );
943
944 /* --kappa_low */
945 name = hdrl_join_string(".", 2, kappa_prefix, "kappa-low");
946 par=cpl_parameterlist_find_const(parlist, name);
947 kappa_low = cpl_parameter_get_double(par);
948 cpl_free(name) ;
949
950 /* --kappa_high */
951 name = hdrl_join_string(".", 2, kappa_prefix, "kappa-high");
952 par=cpl_parameterlist_find_const(parlist, name);
953 kappa_high = cpl_parameter_get_double(par);
954 cpl_free(name) ;
955
956 /* --maxiter */
957 name = hdrl_join_string(".", 2, kappa_prefix, "maxiter");
958 par=cpl_parameterlist_find_const(parlist, name);
959 maxiter = cpl_parameter_get_int(par);
960 cpl_free(name) ;
961
962 cpl_free(kappa_prefix);
963
964 /* --steps_x */
965 name = hdrl_join_string(".", 2, prefix, "legendre.steps-x");
966 par=cpl_parameterlist_find_const(parlist, name);
967 steps_x = cpl_parameter_get_int(par);
968 cpl_free(name) ;
969
970 /* --steps_y */
971 name = hdrl_join_string(".", 2, prefix, "legendre.steps-y");
972 par=cpl_parameterlist_find_const(parlist, name);
973 steps_y = cpl_parameter_get_int(par);
974 cpl_free(name) ;
975
976 /* --filter_size_x */
977 name = hdrl_join_string(".", 2, prefix, "legendre.filter-size-x");
978 par=cpl_parameterlist_find_const(parlist, name);
979 filter_size_x = cpl_parameter_get_int(par);
980 cpl_free(name) ;
981
982 /* --filter_size_y */
983 name = hdrl_join_string(".", 2, prefix, "legendre.filter-size-y");
984 par=cpl_parameterlist_find_const(parlist, name);
985 filter_size_y = cpl_parameter_get_int(par);
986 cpl_free(name) ;
987
988 /* --order_x */
989 name = hdrl_join_string(".", 2, prefix, "legendre.order-x");
990 par=cpl_parameterlist_find_const(parlist, name);
991 order_x = cpl_parameter_get_int(par);
992 cpl_free(name) ;
993
994 /* --order_y */
995 name = hdrl_join_string(".", 2, prefix, "legendre.order-y");
996 par=cpl_parameterlist_find_const(parlist, name);
997 order_y = cpl_parameter_get_int(par);
998 cpl_free(name) ;
999
1000 /* --filter */
1001 name = hdrl_join_string(".", 2, prefix, "filter.filter");
1002 par = cpl_parameterlist_find_const(parlist, name) ;
1003 tmp_str = cpl_parameter_get_string(par);
1004 if (tmp_str == NULL) {
1005 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1006 "Parameter %s not found", name);
1007 cpl_free(name);
1008 return NULL;
1009 }
1010 if(!strcmp(tmp_str, "erosion")) {
1011 filter = CPL_FILTER_EROSION ;
1012 } else if(!strcmp(tmp_str, "DILATION")) {
1013 filter = CPL_FILTER_DILATION ;
1014 } else if(!strcmp(tmp_str, "OPENING")) {
1015 filter = CPL_FILTER_OPENING ;
1016 } else if(!strcmp(tmp_str, "CLOSING")) {
1017 filter = CPL_FILTER_CLOSING ;
1018 } else if(!strcmp(tmp_str, "LINEAR")) {
1019 filter = CPL_FILTER_LINEAR ;
1020 } else if(!strcmp(tmp_str, "LINEAR_SCALE")) {
1021 filter = CPL_FILTER_LINEAR_SCALE ;
1022 } else if(!strcmp(tmp_str, "AVERAGE")) {
1023 filter = CPL_FILTER_AVERAGE ;
1024 } else if(!strcmp(tmp_str, "AVERAGE_FAST")) {
1025 filter = CPL_FILTER_AVERAGE_FAST ;
1026 } else if(!strcmp(tmp_str, "MEDIAN")) {
1027 filter = CPL_FILTER_MEDIAN ;
1028 } else if(!strcmp(tmp_str, "STDEV")) {
1029 filter = CPL_FILTER_STDEV ;
1030 } else if(!strcmp(tmp_str, "STDEV_FAST")) {
1031 filter = CPL_FILTER_STDEV_FAST ;
1032 } else if(!strcmp(tmp_str, "MORPHO")) {
1033 filter = CPL_FILTER_MORPHO ;
1034 } else if(!strcmp(tmp_str, "MORPHO_SCALE")) {
1035 filter = CPL_FILTER_MORPHO_SCALE ;
1036 }
1037 cpl_free(name) ;
1038
1039 /* --border */
1040 name = hdrl_join_string(".", 2, prefix, "filter.border");
1041 par = cpl_parameterlist_find_const(parlist, name) ;
1042 tmp_str = cpl_parameter_get_string(par);
1043 if (tmp_str == NULL) {
1044 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1045 "Parameter %s not found", name);
1046 cpl_free(name);
1047 return NULL;
1048 }
1049 if(!strcmp(tmp_str, "filter")) {
1050 border = CPL_BORDER_FILTER ;
1051 } else if(!strcmp(tmp_str, "ZERO")) {
1052 border = CPL_BORDER_ZERO ;
1053 } else if(!strcmp(tmp_str, "CROP")) {
1054 border = CPL_BORDER_CROP ;
1055 } else if(!strcmp(tmp_str, "NOP")) {
1056 border = CPL_BORDER_NOP ;
1057 } else if(!strcmp(tmp_str, "COPY")) {
1058 border = CPL_BORDER_COPY ;
1059 }
1060 cpl_free(name) ;
1061
1062 /* --smooth_x */
1063 name = hdrl_join_string(".", 2, prefix, "filter.smooth-x");
1064 par=cpl_parameterlist_find_const(parlist, name);
1065 smooth_x = cpl_parameter_get_int(par);
1066 cpl_free(name) ;
1067
1068 /* --smooth_y */
1069 name = hdrl_join_string(".", 2, prefix, "filter.smooth-y");
1070 par=cpl_parameterlist_find_const(parlist, name);
1071 smooth_y = cpl_parameter_get_int(par);
1072 cpl_free(name) ;
1073
1074 /* Return */
1075 if (cpl_error_get_code()) {
1076 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1077 "Error while parsing parameterlist with prefix %s", prefix);
1078 return NULL;
1079 } else {
1080 if (method == HDRL_BPM_2D_FILTERSMOOTH) {
1082 kappa_high, maxiter, filter, border, smooth_x, smooth_y) ;
1083 } else if (method == HDRL_BPM_2D_LEGENDRESMOOTH) {
1085 kappa_high, maxiter, steps_x, steps_y, filter_size_x,
1086 filter_size_y, order_x, order_y) ;
1087 } else {
1088 return NULL ;
1089 }
1090 }
1091}
1092
1093/*----------------------------------------------------------------------------*/
1135/*----------------------------------------------------------------------------*/
1137 const hdrl_image * img_in,
1138 const hdrl_parameter * params)
1139{
1140 cpl_image * img;
1141 cpl_mask * mask_iter, * img_mask;
1142
1143 /* Check Entries */
1144 cpl_error_ensure(img_in && params, CPL_ERROR_NULL_INPUT,
1145 return NULL, "NULL input");
1146 if (hdrl_bpm_2d_parameter_verify(params) != CPL_ERROR_NONE) return NULL;
1147
1148 /* Local Usage Parameters */
1149 const hdrl_bpm_2d_parameter * p_loc = (const hdrl_bpm_2d_parameter *)params ;
1150
1151 img = cpl_image_duplicate(hdrl_image_get_image_const(img_in));
1152 img_mask = cpl_mask_duplicate(cpl_image_get_bpm(img));
1153
1154 /* The first iteration contains the passed mask */
1155 mask_iter = cpl_mask_duplicate(img_mask);
1156
1157
1158 for (int var = 0; var < p_loc->maxiter; ++var) {
1159 cpl_image * img_res = NULL;
1160 cpl_mask * mask_iter_startloop = cpl_mask_duplicate(mask_iter);
1161 double median, mad, std_mad, std_mad_low, std_mad_high ;
1162
1163 /*Add original bad pixels to previous iteration*/
1164 cpl_mask_or(mask_iter, img_mask);
1165
1166 /* Filter the image */
1167 if (p_loc->method == HDRL_BPM_2D_FILTERSMOOTH){
1168 img_res = hdrl_get_residuals_filtersmooth(p_loc->smooth_x,
1169 p_loc->smooth_y, p_loc->filter, p_loc->border, img,
1170 mask_iter);
1171 } else if (p_loc->method == HDRL_BPM_2D_LEGENDRESMOOTH) {
1172 img_res = hdrl_get_residuals_legendresmooth(img, p_loc->steps_x,
1173 p_loc->steps_y, p_loc->filter_size_x, p_loc->filter_size_y,
1174 p_loc->order_x, p_loc->order_y);
1175 }
1176
1177 /*
1178 For a Gaussian distribution the Median Absolute Deviation (MAD) is a
1179 robust and consistent estimate of the Standard Deviation (STD) in the
1180 sense that the STD is approximately K * MAD, where K is a constant
1181 equal to approximately 1.4826 == CPL_MATH_STD_MAD
1182 */
1183
1184 /* Calculating the mad and assuming that after subtraction image has a
1185 mean of Zero */
1186
1187 median = cpl_image_get_mad(img_res, &mad);
1188 //mad = cpl_image_get_stdev(img_res);
1189 if(mad <= 0){
1190 mad=nextafter(0,1.0);
1191 }
1192 std_mad = CPL_MATH_STD_MAD * mad;
1193 std_mad_low = median -(std_mad * p_loc->kappa_low);
1194 std_mad_high = median + (std_mad * p_loc->kappa_high);
1195
1196 /*restore the original mask as we only want to add the new bad pixels
1197 * to the originally passed mask - done by the threshold function*/
1198
1199 cpl_image_reject_from_mask(img_res, img_mask);
1200
1201 /*Reset all pixels to good in the mask as we only want the new bad
1202 * pixels */
1203 cpl_mask_xor(mask_iter, mask_iter);
1204
1205 cpl_mask_threshold_image(mask_iter, img_res, std_mad_low, std_mad_high,
1206 CPL_BINARY_0);
1207
1208 /* Currently the cpl function assigns the "outside" value
1209 * also to the bad pixels - thus if one only wants to have the new bad
1210 * pixel, one has to do the bitwise or */
1211 cpl_mask_xor(mask_iter, img_mask);
1212 cpl_image_delete(img_res);
1213
1214 if (!hdrl_check_maskequality(mask_iter, mask_iter_startloop)) {
1215 cpl_mask_delete(mask_iter_startloop);
1216 cpl_msg_debug(cpl_func, "iter: %d", var);
1217 break;
1218 }
1219 cpl_mask_delete(mask_iter_startloop);
1220 cpl_msg_debug(cpl_func, "iter: %d", var);
1221 }
1222 cpl_mask_delete(img_mask);
1223 cpl_image_delete(img);
1224
1225 return mask_iter ;
1226}
1227
1230/*----------------------------------------------------------------------------*/
1247/*----------------------------------------------------------------------------*/
1248static cpl_image * hdrl_get_residuals_legendresmooth(
1249 const cpl_image * img,
1250 int steps_x,
1251 int steps_y,
1252 int filter_size_x,
1253 int filter_size_y,
1254 int order_x,
1255 int order_y)
1256{
1257 cpl_image * img_res;
1258 cpl_image * img_filtered;
1259 cpl_size nx = cpl_image_get_size_x(img);
1260 cpl_size ny = cpl_image_get_size_y(img);
1261 cpl_size sx = CX_MAX(nx / steps_x, 1);
1262 cpl_size sy = CX_MAX(ny / steps_y, 1);
1263
1264 /* fit to stepped grid */
1265 cpl_matrix * x = hdrl_matrix_linspace(sx / 2, nx, sx);
1266 cpl_matrix * y = hdrl_matrix_linspace(sy / 2, ny, sy);
1267 cpl_image * imgtmp_mod =
1268 hdrl_medianfilter_image_grid(img, x, y,
1269 filter_size_x,
1270 filter_size_y);
1271 cpl_matrix * coeffs = hdrl_fit_legendre(imgtmp_mod,
1272 order_x, order_y,
1273 x, y, nx, ny);
1274 /* TODO: naming conventions: hdrl_matrix_legendre_to_image() */
1275 img_filtered = hdrl_legendre_to_image(coeffs, order_x, order_y, nx, ny);
1276 img_res = cpl_image_subtract_create(img, img_filtered);
1277 if (cpl_msg_get_level() == CPL_MSG_DEBUG)
1278 cpl_matrix_dump(coeffs, stdout);
1279 cpl_matrix_delete(coeffs);
1280 cpl_matrix_delete(x);
1281 cpl_matrix_delete(y);
1282 cpl_image_delete(imgtmp_mod);
1283 cpl_image_delete(img_filtered);
1284 return img_res;
1285}
1286
1287/*----------------------------------------------------------------------------*/
1298/*----------------------------------------------------------------------------*/
1299static cpl_image * hdrl_get_residuals_filtersmooth(
1300 cpl_size kernel_size_x,
1301 cpl_size kernel_size_y,
1302 cpl_filter_mode filter,
1303 cpl_border_mode border,
1304 cpl_image * img,
1305 cpl_mask * mask_iter)
1306{
1307 cpl_mask * kernel ;
1308 cpl_image * img_res = NULL;
1309 cpl_image * img_filtered = NULL;
1310
1311 cpl_size nx = cpl_image_get_size_x(img);
1312 cpl_size ny = cpl_image_get_size_y(img);
1313
1314
1315 /* Create the kernel */
1316 kernel = cpl_mask_new(kernel_size_x, kernel_size_y) ;
1317 cpl_mask_not(kernel);
1318 if (kernel == NULL) return NULL ;
1319
1320 /* Filter the image */
1321 cpl_image_reject_from_mask(img, mask_iter);
1322 if (border == CPL_BORDER_FILTER) {
1323 img_filtered = hdrl_parallel_filter_image(img, NULL, kernel, filter);
1324 }
1325 else {
1326 img_filtered = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
1327 cpl_image_filter_mask(img_filtered, img, kernel, filter, border);
1328 }
1329 cpl_mask_delete(kernel) ;
1330 img_res = cpl_image_subtract_create(img, img_filtered);
1331 cpl_image_delete(img_filtered);
1332
1333 return img_res;
1334}
1335
cpl_mask * hdrl_bpm_2d_compute(const hdrl_image *img_in, const hdrl_parameter *params)
Detect bad pixels on a single image with an iterative process.
Definition: hdrl_bpm_2d.c:1136
hdrl_bpm_2d_method hdrl_bpm_2d_parameter_get_method(const hdrl_parameter *p)
Access the method in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:495
double hdrl_bpm_2d_parameter_get_kappa_high(const hdrl_parameter *p)
Access the kappa_high in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:355
int hdrl_bpm_2d_parameter_get_maxiter(const hdrl_parameter *p)
Access the maxiter in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:369
cpl_border_mode hdrl_bpm_2d_parameter_get_border(const hdrl_parameter *p)
Access the border in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:327
int hdrl_bpm_2d_parameter_get_filter_size_y(const hdrl_parameter *p)
Access the filter_size_y in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:425
int hdrl_bpm_2d_parameter_get_smooth_y(const hdrl_parameter *p)
Access the smooth_y in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:467
int hdrl_bpm_2d_parameter_get_order_y(const hdrl_parameter *p)
Access the order_y in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:453
hdrl_parameter * hdrl_bpm_2d_parameter_parse_parlist(const cpl_parameterlist *parlist, const char *prefix)
Parse parameter list to create input parameters for the BPM_2D.
Definition: hdrl_bpm_2d.c:896
int hdrl_bpm_2d_parameter_get_filter_size_x(const hdrl_parameter *p)
Access the filter_size_x in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:411
hdrl_parameter * hdrl_bpm_2d_parameter_create_filtersmooth(double kappa_low, double kappa_high, int maxiter, cpl_filter_mode filter, cpl_border_mode border, int smooth_x, int smooth_y)
Creates BPM_2D Parameters object for HDRL_BPM_2D_FILTERSMOOTH.
Definition: hdrl_bpm_2d.c:137
int hdrl_bpm_2d_parameter_get_smooth_x(const hdrl_parameter *p)
Access the smooth_x in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:481
int hdrl_bpm_2d_parameter_get_steps_x(const hdrl_parameter *p)
Access the steps_x in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:383
cpl_filter_mode hdrl_bpm_2d_parameter_get_filter(const hdrl_parameter *p)
Access the filter in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:313
cpl_error_code hdrl_bpm_2d_parameter_verify(const hdrl_parameter *param)
Verify basic correctness of the BPM_2D parameters.
Definition: hdrl_bpm_2d.c:232
cpl_parameterlist * hdrl_bpm_2d_parameter_create_parlist(const char *base_context, const char *prefix, const char *method_def, const hdrl_parameter *filtersmooth_def, const hdrl_parameter *legendresmooth_def)
Create parameter list for the BPM_2D computation.
Definition: hdrl_bpm_2d.c:798
int hdrl_bpm_2d_parameter_get_order_x(const hdrl_parameter *p)
Access the order_x in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:439
int hdrl_bpm_2d_parameter_get_steps_y(const hdrl_parameter *p)
Access the steps_y in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:397
hdrl_parameter * hdrl_bpm_2d_parameter_create_legendresmooth(double kappa_low, double kappa_high, int maxiter, int steps_x, int steps_y, int filter_size_x, int filter_size_y, int order_x, int order_y)
Creates BPM_2D Parameters object for HDRL_BPM_2D_LEGENDRESMOOTH.
Definition: hdrl_bpm_2d.c:191
cpl_boolean hdrl_bpm_2d_parameter_check(const hdrl_parameter *self)
Check that the parameter is a BPM_2D parameter.
Definition: hdrl_bpm_2d.c:301
double hdrl_bpm_2d_parameter_get_kappa_low(const hdrl_parameter *p)
Access the kappa_low in the BPM_2D parameter.
Definition: hdrl_bpm_2d.c:341
const cpl_image * hdrl_image_get_image_const(const hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:118
char * hdrl_join_string(const char *sep_, int n,...)
join strings together
Definition: hdrl_utils.c:812