CR2RE Pipeline Reference Manual 1.6.10
hdrl_flat.c
1/* $Id: hdrl_flat.c,v 1.29 2013-09-25 11:04:29 jtaylor Exp $
2 *
3 * This file is part of the HDRL
4 * Copyright (C) 2013 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/*
22 * $Author: jtaylor $
23 * $Date: 2013-09-25 11:04:29 $
24 * $Revision: 1.29 $
25 * $Name: not supported by cvs2svn $
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31
32/*-----------------------------------------------------------------------------
33 Includes
34-----------------------------------------------------------------------------*/
35
36#include "hdrl_flat.h"
37#include <string.h>
38#include <assert.h>
39
40/*-----------------------------------------------------------------------------
41 Static
42 -----------------------------------------------------------------------------*/
43
44/*----------------------------------------------------------------------------*/
93/*----------------------------------------------------------------------------*/
94
100/*-----------------------------------------------------------------------------
101 FLAT Parameters Definition
102 -----------------------------------------------------------------------------*/
103typedef struct {
104 HDRL_PARAMETER_HEAD;
105 cpl_size filter_size_x ;
106 cpl_size filter_size_y ;
107 hdrl_flat_method method ;
108} hdrl_flat_parameter;
109
110/* Parameter type */
111static hdrl_parameter_typeobj hdrl_flat_parameter_type = {
112 HDRL_PARAMETER_FLAT, /* type */
113 (hdrl_alloc *)&cpl_malloc, /* fp_alloc */
114 (hdrl_free *)&cpl_free, /* fp_free */
115 NULL, /* fp_destroy */
116 sizeof(hdrl_flat_parameter), /* obj_size */
117};
118
119/*----------------------------------------------------------------------------*/
126/*----------------------------------------------------------------------------*/
127static cpl_error_code hdrl_flat_parameter_verify(
128 const hdrl_parameter * param)
129{
130 const hdrl_flat_parameter * param_loc = (const hdrl_flat_parameter *)param ;
131
132 cpl_error_ensure(param != NULL, CPL_ERROR_NULL_INPUT,
133 return CPL_ERROR_NULL_INPUT, "NULL Input Parameters");
134 cpl_error_ensure(hdrl_flat_parameter_check(param),
135 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
136 "Expected FLAT image parameter") ;
137
138 cpl_error_ensure(param_loc->method == HDRL_FLAT_FREQ_LOW ||
139 param_loc->method == HDRL_FLAT_FREQ_HIGH,
140 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
141 "Unsupported method");
142 cpl_error_ensure(param_loc->filter_size_x > 0,
143 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
144 "filter_size_x must be > 0");
145 cpl_error_ensure(param_loc->filter_size_y > 0,
146 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
147 "filter_size_y must be > 0");
148 cpl_error_ensure((param_loc->filter_size_x % 2) == 1,
149 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
150 "filter_size_x must an odd number");
151 cpl_error_ensure((param_loc->filter_size_y % 2) == 1,
152 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
153 "filter_size_y must an odd number");
154 return CPL_ERROR_NONE ;
155}
156
159/* ---------------------------------------------------------------------------*/
172/* ---------------------------------------------------------------------------*/
174 cpl_size filter_size_x,
175 cpl_size filter_size_y,
176 hdrl_flat_method method)
177{
178 hdrl_flat_parameter * p = (hdrl_flat_parameter *)
179 hdrl_parameter_new(&hdrl_flat_parameter_type);
180 p->filter_size_x = filter_size_x ;
181 p->filter_size_y = filter_size_y ;
182 p->method = method ;
183 if (hdrl_flat_parameter_verify((hdrl_parameter *)p) != CPL_ERROR_NONE) {
184 hdrl_parameter_delete((hdrl_parameter *)p);
185 return NULL;
186 }
187 return (hdrl_parameter *)p;
188}
189
190/*----------------------------------------------------------------------------*/
196/*----------------------------------------------------------------------------*/
197cpl_boolean hdrl_flat_parameter_check(const hdrl_parameter * self)
198{
199 return hdrl_parameter_check_type(self, &hdrl_flat_parameter_type);
200}
201
202/*----------------------------------------------------------------------------*/
208/*----------------------------------------------------------------------------*/
210 const hdrl_parameter * p)
211{
212 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
213 return ((const hdrl_flat_parameter *)p)->filter_size_x;
214}
215
216/*----------------------------------------------------------------------------*/
222/*----------------------------------------------------------------------------*/
224 const hdrl_parameter * p)
225{
226 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
227 return ((const hdrl_flat_parameter *)p)->filter_size_y;
228}
229
230/*----------------------------------------------------------------------------*/
236/*----------------------------------------------------------------------------*/
238 const hdrl_parameter * p)
239{
240 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
241 return ((const hdrl_flat_parameter *)p)->method;
242}
243
244/*----------------------------------------------------------------------------*/
257/*----------------------------------------------------------------------------*/
259 const char * base_context,
260 const char * prefix,
261 const hdrl_parameter * defaults)
262{
263 cpl_ensure(prefix && base_context && defaults, CPL_ERROR_NULL_INPUT, NULL);
264 char * name ;
265 cpl_parameterlist * parlist = cpl_parameterlist_new();
266 cpl_parameter * par ;
267 char * context =
268 hdrl_join_string(".", 2, base_context, prefix);
269
270 cpl_size filter_size_x_def = hdrl_flat_parameter_get_filter_size_x(defaults) ;
271 cpl_size filter_size_y_def = hdrl_flat_parameter_get_filter_size_y(defaults) ;
272
273 hdrl_flat_method method_def =hdrl_flat_parameter_get_method(defaults);
274 cpl_ensure( method_def == HDRL_FLAT_FREQ_LOW || method_def == HDRL_FLAT_FREQ_HIGH,
275 CPL_ERROR_ILLEGAL_INPUT, NULL) ;
276
277 const char *method_str;
278 if (method_def == HDRL_FLAT_FREQ_LOW) {
279 method_str = "low";
280 } else if (method_def == HDRL_FLAT_FREQ_HIGH) {
281 method_str = "high";
282 } else {
283 method_str = "";
284 }
285
286 /* --prefix.filter_size_x */
287 hdrl_setup_vparameter(parlist, prefix, ".", "", "filter-size-x", base_context,
288 "Smoothing filter size in x-direction.", CPL_TYPE_INT,
289 (int)filter_size_x_def) ;
290
291 /* --prefix.filter_size_y */
292 hdrl_setup_vparameter(parlist, prefix, ".", "", "filter-size-y", base_context,
293 "Smoothing filter size in y-direction.", CPL_TYPE_INT,
294 (int)filter_size_y_def) ;
295
296 /* --prefix.method */
297 name = hdrl_join_string(".", 2, context, "method");
298 par = cpl_parameter_new_enum(name, CPL_TYPE_STRING,
299 "Method to use for the master flatfield calculation", context, method_str,
300 2, "low", "high");
301 cpl_free(name);
302 name = hdrl_join_string(".", 2, prefix, "method");
303 cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI, name);
304 cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
305 cpl_free(name);
306 cpl_parameterlist_append(parlist, par);
307
308 cpl_free(context);
309
310 if (cpl_error_get_code()) {
311 cpl_parameterlist_delete(parlist);
312 return NULL;
313 }
314 return parlist;
315}
316
317/*----------------------------------------------------------------------------*/
330/*----------------------------------------------------------------------------*/
332 const cpl_parameterlist * parlist,
333 const char * prefix)
334{
335 cpl_ensure(prefix && parlist, CPL_ERROR_NULL_INPUT, NULL);
336 char * name;
337 const cpl_parameter * par;
338 const char * tmp_str ;
339 cpl_size filter_size_x;
340 cpl_size filter_size_y;
341 hdrl_flat_method method;
342
343 /* --filter_size_x */
344 name = hdrl_join_string(".", 2, prefix, "filter-size-x");
345 par=cpl_parameterlist_find_const(parlist, name);
346 filter_size_x = cpl_parameter_get_int(par);
347 cpl_free(name) ;
348
349 /* --filter_size_y */
350 name = hdrl_join_string(".", 2, prefix, "filter-size-y");
351 par=cpl_parameterlist_find_const(parlist, name);
352 filter_size_y = cpl_parameter_get_int(par);
353 cpl_free(name) ;
354
355 /* --method */
356 name = hdrl_join_string(".", 2, prefix, "method");
357 par = cpl_parameterlist_find_const(parlist, name) ;
358 tmp_str = cpl_parameter_get_string(par);
359 if (tmp_str == NULL) {
360 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
361 "Parameter %s not found", name);
362 cpl_free(name);
363 return NULL;
364 }
365 cpl_free(name) ;
366 if(!strcmp(tmp_str, "low")) {
367 method = HDRL_FLAT_FREQ_LOW ;
368 } else if(!strcmp(tmp_str, "high")) {
369 method = HDRL_FLAT_FREQ_HIGH ;
370 } else {
371 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
372 "Invalid method: %s", tmp_str);
373 return NULL;
374 }
375
376 if (cpl_error_get_code()) {
377 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
378 "Error while parsing parameterlist with prefix %s", prefix);
379 return NULL;
380 } else {
381 return hdrl_flat_parameter_create(filter_size_x, filter_size_y, method) ;
382 }
383}
384
385/* ---------------------------------------------------------------------------*/
403/* ---------------------------------------------------------------------------*/
404
405cpl_error_code hdrl_flat_compute(
406 hdrl_imagelist * hdrl_data,
407 const cpl_mask * stat_mask,
408 const hdrl_parameter * collapse_params,
409 hdrl_parameter * flat_params,
410 hdrl_image ** master,
411 cpl_image ** contrib_map)
412{
413 hdrl_image * comb_img = NULL;
414 cpl_image * comb_ctr = NULL;
415 int lowf = 0;
416
417 /* Check Entries */
418 cpl_error_ensure(hdrl_data != NULL, CPL_ERROR_NULL_INPUT,
419 return CPL_ERROR_NULL_INPUT, "No flatfields found");
420 cpl_error_ensure(collapse_params != NULL, CPL_ERROR_NULL_INPUT,
421 return CPL_ERROR_NULL_INPUT, "No collapsing parameter");
422 cpl_error_ensure(flat_params != NULL, CPL_ERROR_NULL_INPUT,
423 return CPL_ERROR_NULL_INPUT, "No flatfield parameter");
424
425 if (hdrl_flat_parameter_verify(flat_params) != CPL_ERROR_NONE)
426 return cpl_error_get_code();
427
428 /* Local Usage Parameters */
429 const hdrl_flat_parameter * p_loc = (hdrl_flat_parameter *)flat_params ;
430 cpl_size filter_size_x = p_loc->filter_size_x;
431 cpl_size filter_size_y = p_loc->filter_size_y;
432
433 if (p_loc->method == HDRL_FLAT_FREQ_LOW) {
434 lowf = 1;
435 } else if (p_loc->method == HDRL_FLAT_FREQ_HIGH) {
436 lowf = 0;
437 }
438
439 cpl_mask * kernel = cpl_mask_new(filter_size_x, filter_size_y) ;
440 cpl_mask_not(kernel);
441
442 /* NOTE: The filtered image is supposed to be noiseless */
443
444 for (cpl_size i = 0; i < hdrl_imagelist_get_size(hdrl_data); i++) {
445
446 /* TODO Only extract the mask if there is a mask and only combine
447 * the masks if there are both masks */
448
449 cpl_image *img = hdrl_image_get_image(hdrl_imagelist_get(hdrl_data, i));
450 cpl_image *img_err = hdrl_image_get_error(hdrl_imagelist_get(hdrl_data, i));
451
452 cpl_mask *img_mask = cpl_mask_duplicate(cpl_image_get_bpm(img));
453 cpl_mask *img_mask_orig = cpl_mask_duplicate(cpl_image_get_bpm(img));
454
455 if (lowf == 1) {
456 double median;
457 /* no error propagation as the median error is small and also
458 * consistency with the high freq variant which can't propagate
459 * error */
460 if (stat_mask != NULL) {
461 cpl_mask_or(img_mask, stat_mask);
462 /* Apply combined mask */
463 cpl_image_reject_from_mask(img, img_mask);
464 median = cpl_image_get_median(img);
465 cpl_msg_debug(cpl_func, "Median of the flat: %g", median);
466 /* restore the original mask */
467 cpl_image_reject_from_mask(img, img_mask_orig);
468 }
469 else {
470 median = cpl_image_get_median(img);
471 cpl_msg_debug(cpl_func, "Median of the flat: %g", median);
472 }
473 cpl_image_divide_scalar(img, median);
474 cpl_image_divide_scalar(img_err, median);
475 }
476 else {
477 cpl_image * img_filtered;
478 if (stat_mask != NULL) {
479 cpl_image * img_filtered2;
480
481 /* Algorithm takes into account border effects introduced by the
482 * static mask, i.e it smoothes the good and bad region
483 * seperately in order to make sure that they are not
484 * correlated:
485 * 1) Smooth the part of the image declared to belong together
486 * by the static mask, e.g. the iluminated part of the image
487 * 2) Smooth the remaining part of the image, e.g. the not
488 * iluminated part of the image
489 * 3) combine 1) and 2) in a single image
490 * */
491
492 /*A) Filter the image declared as good by the static mask */
493
494 cpl_mask_or(img_mask, stat_mask);
495 cpl_image_reject_from_mask(img, img_mask);
496 img_filtered = hdrl_parallel_filter_image(img, NULL, kernel,
497 CPL_FILTER_MEDIAN);
498
499 /*The filtering extents the image into the bad pixel part, thus
500 * we must reapply the static mask to preserve the sharp
501 * cutoff */
502 cpl_mask_or(cpl_image_get_bpm(img_filtered), stat_mask);
503
504 /*B) Filter the image declared as bad by the static mask */
505
506 /* Create an inverted mask */
507 cpl_mask * stat_mask_inverted=cpl_mask_duplicate(stat_mask);
508 cpl_mask_not(stat_mask_inverted);
509 /* Restore the original bad pixel mask into img_mask */
510 cpl_mask_delete(img_mask);
511 img_mask = cpl_mask_duplicate(img_mask_orig);
512 /* Filter the image */
513 cpl_mask_or(img_mask, stat_mask_inverted);
514 cpl_image_reject_from_mask(img, img_mask);
515 img_filtered2 = hdrl_parallel_filter_image(img, NULL, kernel,
516 CPL_FILTER_MEDIAN);
517
518 /*The filtering extents the image into the bad pixel part, thus
519 * we must reapply the static mask to preserve the sharp
520 * cutoff */
521 cpl_mask_or(cpl_image_get_bpm(img_filtered2),
522 stat_mask_inverted);
523 cpl_mask_delete(stat_mask_inverted);
524
525 /*C) Combine the two images into one image */
526
527 cpl_image_fill_rejected(img_filtered, 0.);
528 cpl_image_fill_rejected(img_filtered2, 0.);
529 /* remove the static masks to join images */
530 cpl_mask * img_filtered1_mask =
531 cpl_image_unset_bpm(img_filtered);
532 cpl_mask * img_filtered2_mask =
533 cpl_image_unset_bpm(img_filtered2);
534
535 cpl_image_add(img_filtered, img_filtered2);
536 cpl_image_delete(img_filtered2);
537
538 /* & of static make should be input bpm */
539 cpl_mask_and(img_filtered1_mask, img_filtered2_mask);
540 assert(memcmp(cpl_mask_get_data(img_filtered1_mask),
541 cpl_mask_get_data(img_mask_orig),
542 hdrl_get_image_npix(img)) == 0);
543
544 /* apply original bpm back onto filtered image */
545 cpl_image_reject_from_mask(img_filtered, img_filtered1_mask);
546 cpl_mask_delete(img_filtered1_mask);
547 cpl_mask_delete(img_filtered2_mask);
548 }
549 else {
550 /* Filter the image */
551 cpl_image_reject_from_mask(img, img_mask);
552 /* currently only tested for CPL_BORDER_FILTER */
553 img_filtered = hdrl_parallel_filter_image(img, NULL, kernel,
554 CPL_FILTER_MEDIAN);
555 }
556
557 /* restore the original mask */
558 cpl_image_reject_from_mask(img, img_mask_orig);
559 cpl_image_reject_from_mask(img_err, img_mask_orig);
560
561 cpl_image_divide(img, img_filtered);
562 cpl_image_divide(img_err, img_filtered);
563 cpl_image_delete(img_filtered);
564 }
565
566 /* make sure that the error is positive */
567 /* TODO Check if this is following the error propagation law */
568 cpl_image_abs(img_err);
569
570 cpl_mask_delete(img_mask);
571 cpl_mask_delete(img_mask_orig);
572 }
573
574 cpl_msg_info(cpl_func, "Combining the normalized flatfields generating"
575 " the master-flatfield");
576
577 hdrl_imagelist_collapse(hdrl_data, collapse_params, &comb_img, &comb_ctr);
578
579 if (lowf == 1){
580 cpl_image *img_filtered = hdrl_parallel_filter_image(
581 hdrl_image_get_image_const(comb_img), NULL, kernel, CPL_FILTER_MEDIAN);
582 *master = hdrl_image_create(img_filtered, hdrl_image_get_error(comb_img));
583 *contrib_map = comb_ctr;
584 hdrl_image_delete(comb_img);
585 cpl_image_delete(img_filtered);
586 }
587 else {
588 *master = comb_img;
589 *contrib_map = comb_ctr;
590 }
591
592 cpl_mask_delete(kernel);
593 cpl_msg_indent_less();
594 return cpl_error_get_code();
595}
596
597
cpl_size hdrl_flat_parameter_get_filter_size_x(const hdrl_parameter *p)
Access the filter_size_x in the FLAT parameter.
Definition: hdrl_flat.c:209
hdrl_parameter * hdrl_flat_parameter_create(cpl_size filter_size_x, cpl_size filter_size_y, hdrl_flat_method method)
Creates FLAT Parameters object.
Definition: hdrl_flat.c:173
cpl_size hdrl_flat_parameter_get_filter_size_y(const hdrl_parameter *p)
Access the filter_size_y in the FLAT parameter.
Definition: hdrl_flat.c:223
cpl_error_code hdrl_flat_compute(hdrl_imagelist *hdrl_data, const cpl_mask *stat_mask, const hdrl_parameter *collapse_params, hdrl_parameter *flat_params, hdrl_image **master, cpl_image **contrib_map)
compute high or low frequency master flat with median filtering
Definition: hdrl_flat.c:405
hdrl_flat_method hdrl_flat_parameter_get_method(const hdrl_parameter *p)
Access the method in the FLAT parameter.
Definition: hdrl_flat.c:237
hdrl_parameter * hdrl_flat_parameter_parse_parlist(const cpl_parameterlist *parlist, const char *prefix)
Parse a parameterlist to create input parameters for the FLAT.
Definition: hdrl_flat.c:331
cpl_parameterlist * hdrl_flat_parameter_create_parlist(const char *base_context, const char *prefix, const hdrl_parameter *defaults)
Create a parameter list for the FLAT computation.
Definition: hdrl_flat.c:258
cpl_boolean hdrl_flat_parameter_check(const hdrl_parameter *self)
Check that the parameter is a FLAT parameter.
Definition: hdrl_flat.c:197
cpl_image * hdrl_image_get_error(hdrl_image *himg)
get error as cpl image
Definition: hdrl_image.c:131
hdrl_image * hdrl_image_create(const cpl_image *image, const cpl_image *error)
create a new hdrl_image from to existing images by copying them
Definition: hdrl_image.c:295
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:105
const cpl_image * hdrl_image_get_image_const(const hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:118
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
Definition: hdrl_image.c:379
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
cpl_error_code hdrl_imagelist_collapse(const hdrl_imagelist *himlist, const hdrl_parameter *param, hdrl_image **out, cpl_image **contrib)
collapsing of image list
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
void hdrl_parameter_delete(hdrl_parameter *obj)
shallow delete of a parameter
char * hdrl_join_string(const char *sep_, int n,...)
join strings together
Definition: hdrl_utils.c:812