CR2RE Pipeline Reference Manual 1.6.7
hdrl_bpm_3d.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_3d.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/*----------------------------------------------------------------------------*/
67/*----------------------------------------------------------------------------*/
68
74/*-----------------------------------------------------------------------------
75 BPM Parameters Definition
76 -----------------------------------------------------------------------------*/
77typedef struct {
78 HDRL_PARAMETER_HEAD;
79 double kappa_low ;
80 double kappa_high ;
81 hdrl_bpm_3d_method method ;
82} hdrl_bpm_3d_parameter;
83
84/* Parameter type */
85static hdrl_parameter_typeobj hdrl_bpm_3d_parameter_type = {
86 HDRL_PARAMETER_BPM_3D, /* type */
87 (hdrl_alloc *)&cpl_malloc, /* fp_alloc */
88 (hdrl_free *)&cpl_free, /* fp_free */
89 NULL, /* fp_destroy */
90 sizeof(hdrl_bpm_3d_parameter), /* obj_size */
91};
94/* ---------------------------------------------------------------------------*/
107/* ---------------------------------------------------------------------------*/
109 double kappa_low,
110 double kappa_high,
111 hdrl_bpm_3d_method method)
112{
113 hdrl_bpm_3d_parameter * p = (hdrl_bpm_3d_parameter *)
114 hdrl_parameter_new(&hdrl_bpm_3d_parameter_type);
115 p->kappa_low = kappa_low ;
116 p->kappa_high = kappa_high ;
117 p->method = method ;
118 return (hdrl_parameter *)p;
119}
120
121/*----------------------------------------------------------------------------*/
127/*----------------------------------------------------------------------------*/
129 const hdrl_parameter * param)
130{
131 const hdrl_bpm_3d_parameter * param_loc = (const hdrl_bpm_3d_parameter *)param ;
132
133 cpl_error_ensure(param != NULL, CPL_ERROR_NULL_INPUT,
134 return CPL_ERROR_NULL_INPUT, "NULL Input Parameters");
135 cpl_error_ensure(hdrl_bpm_3d_parameter_check(param),
136 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
137 "Expected BPM image parameter") ;
138
139 cpl_error_ensure(param_loc->method == HDRL_BPM_3D_THRESHOLD_ABSOLUTE ||
140 param_loc->method == HDRL_BPM_3D_THRESHOLD_RELATIVE ||
141 param_loc->method == HDRL_BPM_3D_THRESHOLD_ERROR,
142 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
143 "Unsupported method");
144 switch (param_loc->method) {
145 case HDRL_BPM_3D_THRESHOLD_ABSOLUTE:
146 cpl_error_ensure(param_loc->kappa_high >= param_loc->kappa_low,
147 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
148 "kappa_high must be larger than kappa_low");
149 break;
150 case HDRL_BPM_3D_THRESHOLD_RELATIVE:
151 case HDRL_BPM_3D_THRESHOLD_ERROR:
152 cpl_error_ensure(param_loc->kappa_low >= 0,
153 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
154 "kappa_low must be >=0");
155 cpl_error_ensure(param_loc->kappa_high >= 0,
156 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
157 "kappa_high must be >=0");
158 break;
159 }
160 return CPL_ERROR_NONE ;
161}
162
163/*----------------------------------------------------------------------------*/
169/*----------------------------------------------------------------------------*/
170cpl_boolean hdrl_bpm_3d_parameter_check(const hdrl_parameter * self)
171{
172 return hdrl_parameter_check_type(self, &hdrl_bpm_3d_parameter_type);
173}
174
175/*----------------------------------------------------------------------------*/
181/*----------------------------------------------------------------------------*/
183 const hdrl_parameter * p)
184{
185 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1.0);
186 return ((const hdrl_bpm_3d_parameter *)p)->kappa_low;
187}
188
189/*----------------------------------------------------------------------------*/
195/*----------------------------------------------------------------------------*/
197 const hdrl_parameter * p)
198{
199 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1.0);
200 return ((const hdrl_bpm_3d_parameter *)p)->kappa_high;
201}
202
203/*----------------------------------------------------------------------------*/
209/*----------------------------------------------------------------------------*/
211 const hdrl_parameter * p)
212{
213 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
214 return ((const hdrl_bpm_3d_parameter *)p)->method;
215}
216
217/*----------------------------------------------------------------------------*/
230/*----------------------------------------------------------------------------*/
232 const char *base_context,
233 const char *prefix,
234 const hdrl_parameter *defaults)
235{
236 cpl_ensure(prefix && base_context && defaults,
237 CPL_ERROR_NULL_INPUT, NULL);
238
239 cpl_ensure(hdrl_bpm_3d_parameter_check(defaults),
240 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
241
242 char *name;
243 cpl_parameterlist *parlist = cpl_parameterlist_new();
244 cpl_parameter *par;
245 char *context =
246 hdrl_join_string(".", 2, base_context, prefix);
247
248 double kappa_low_def = hdrl_bpm_3d_parameter_get_kappa_low(defaults);
249 double kappa_high_def = hdrl_bpm_3d_parameter_get_kappa_high(defaults);
250
251 hdrl_bpm_3d_method method_def = hdrl_bpm_3d_parameter_get_method(defaults);
252 cpl_ensure( method_def == HDRL_BPM_3D_THRESHOLD_ABSOLUTE
253 || method_def == HDRL_BPM_3D_THRESHOLD_RELATIVE
254 || method_def == HDRL_BPM_3D_THRESHOLD_ERROR,
255 CPL_ERROR_ILLEGAL_INPUT, NULL) ;
256
257 const char *method_str;
258 if (method_def == HDRL_BPM_3D_THRESHOLD_ABSOLUTE) {
259 method_str = "absolute" ;
260 } else if (method_def == HDRL_BPM_3D_THRESHOLD_RELATIVE) {
261 method_str = "relative" ;
262 } else if (method_def == HDRL_BPM_3D_THRESHOLD_ERROR) {
263 method_str = "error" ;
264 } else {
265 method_str = "";
266 }
267
268 /* --prefix.kappa_low */
269 hdrl_setup_vparameter(parlist, prefix, ".", "", "kappa-low", base_context,
270 "Low RMS scaling factor for image thresholding.", CPL_TYPE_DOUBLE,
271 kappa_low_def) ;
272
273 /* --prefix.kappa_high */
274 hdrl_setup_vparameter(parlist, prefix, ".", "", "kappa-high", base_context,
275 "High RMS scaling factor for image thresholding.", CPL_TYPE_DOUBLE,
276 kappa_high_def) ;
277
278 /* --prefix.method */
279 name = hdrl_join_string(".", 2, context, "method");
280 par = cpl_parameter_new_enum(name, CPL_TYPE_STRING,
281 "Thresholdig method to use for bpm detection", context, method_str,
282 3, "absolute", "relative", "error");
283 cpl_free(name);
284 name = hdrl_join_string(".", 2, prefix, "method");
285 cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI, name);
286 cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
287 cpl_free(name);
288 cpl_parameterlist_append(parlist, par);
289
290 cpl_free(context);
291
292 if (cpl_error_get_code()) {
293 cpl_parameterlist_delete(parlist);
294 return NULL;
295 }
296
297 return parlist;
298}
299
300/*----------------------------------------------------------------------------*/
313/*----------------------------------------------------------------------------*/
315 const cpl_parameterlist * parlist,
316 const char * prefix)
317{
318 cpl_ensure(prefix && parlist, CPL_ERROR_NULL_INPUT, NULL);
319 char * name;
320 const cpl_parameter * par;
321 const char * tmp_str ;
322 double kappa_low;
323 double kappa_high;
324 hdrl_bpm_3d_method method;
325
326 /* --kappa_low */
327 name = hdrl_join_string(".", 2, prefix, "kappa-low");
328 par=cpl_parameterlist_find_const(parlist, name);
329 kappa_low = cpl_parameter_get_double(par);
330 cpl_free(name) ;
331
332 /* --kappa_high */
333 name = hdrl_join_string(".", 2, prefix, "kappa-high");
334 par=cpl_parameterlist_find_const(parlist, name);
335 kappa_high = cpl_parameter_get_double(par);
336 cpl_free(name) ;
337
338 /* --method */
339 name = hdrl_join_string(".", 2, prefix, "method");
340 par = cpl_parameterlist_find_const(parlist, name) ;
341 tmp_str = cpl_parameter_get_string(par);
342 if (tmp_str == NULL) {
343 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
344 "Parameter %s not found", name);
345 cpl_free(name);
346 return NULL;
347 }
348 cpl_free(name) ;
349 if(!strcmp(tmp_str, "absolute")) {
350 method = HDRL_BPM_3D_THRESHOLD_ABSOLUTE ;
351 } else if(!strcmp(tmp_str, "relative")) {
352 method = HDRL_BPM_3D_THRESHOLD_RELATIVE ;
353 } else if(!strcmp(tmp_str, "error")) {
354 method = HDRL_BPM_3D_THRESHOLD_ERROR ;
355 } else {
356 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
357 "Invalid method: %s", tmp_str);
358 return NULL;
359 }
360
361 if (cpl_error_get_code()) {
362 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
363 "Error while parsing parameterlist with prefix %s", prefix);
364 return NULL;
365 } else {
366 return hdrl_bpm_3d_parameter_create(kappa_low, kappa_high, method) ;
367 }
368}
369
370/*----------------------------------------------------------------------------*/
408/*----------------------------------------------------------------------------*/
409cpl_imagelist * hdrl_bpm_3d_compute(
410 const hdrl_imagelist * imglist,
411 const hdrl_parameter * params)
412{
413
414/* This routine assumes that the images are already scaled outside ! */
415
416 cpl_imagelist * imglist_out = NULL;
417 hdrl_imagelist * masterlist = NULL;
418 hdrl_parameter * collapse_params = NULL;
419
420 /* Check Entries */
421 cpl_error_ensure(imglist && params, CPL_ERROR_NULL_INPUT,
422 return NULL, "NULL input");
423 if (hdrl_bpm_3d_parameter_verify(params) != CPL_ERROR_NONE) return NULL;
424
425 /* Local Usage Parameters */
426 const hdrl_bpm_3d_parameter * p_loc = (const hdrl_bpm_3d_parameter *)params ;
427
428 collapse_params = hdrl_collapse_median_parameter_create();
429
430 imglist_out = cpl_imagelist_new();
431 masterlist = hdrl_imagelist_new();
432
433
434 /* Here we have correlated errors */
435 hdrl_image * master;
436 cpl_image * contrib_map;
437
438 /* Get the proper collapse function and perform frames combination */
439 hdrl_imagelist_collapse(imglist, collapse_params, &master,&contrib_map);
440 /* broadcasted same master over list */
441 for (int var = 0; var < hdrl_imagelist_get_size(imglist); ++var) {
442 hdrl_imagelist_set(masterlist, master,
443 hdrl_imagelist_get_size(masterlist));
444 }
445 cpl_image_delete(contrib_map);
446
447
448 for (int var = 0; var < hdrl_imagelist_get_size(imglist); ++var) {
449 /* subtract master */
450 hdrl_image * tmp_hdrlimg = hdrl_image_sub_image_create(
451 hdrl_imagelist_get_const(imglist, var),
452 hdrl_imagelist_get(masterlist, var));
453 cpl_mask * tmp_cplimg_mask = hdrl_image_get_mask(tmp_hdrlimg);
454 cpl_mask * mask_out = NULL;
455
456 if (p_loc->method == HDRL_BPM_3D_THRESHOLD_ABSOLUTE) {
457 /* Absolute values */
458 mask_out = cpl_mask_threshold_image_create(
459 hdrl_image_get_image(tmp_hdrlimg), p_loc->kappa_low,
460 p_loc->kappa_high);
461 cpl_mask_not(mask_out);
462 /*Here we use the bpm from the image after master frame subtraction
463 * - this is not 100 percent clean but a good approximation*/
464 cpl_mask_xor(mask_out, tmp_cplimg_mask);
465 } else if (p_loc->method == HDRL_BPM_3D_THRESHOLD_RELATIVE) {
466 /* Scaled residual from image using scaled mad*/
467 double mad, std_mad;
468 cpl_image_get_mad(hdrl_image_get_image(tmp_hdrlimg), &mad);
469 if (mad <= 0){
470 mad = nextafter(0, 1.0);
471 }
472 std_mad = CPL_MATH_STD_MAD * mad;
473 mask_out = cpl_mask_threshold_image_create(
474 hdrl_image_get_image(tmp_hdrlimg),
475 -(p_loc->kappa_low * std_mad),
476 (p_loc->kappa_high * std_mad));
477 cpl_mask_not(mask_out);
478 /*Here we use the bpm from the image after master frame subtraction
479 * - this is not 100 percent clean but a good approximation*/
480 cpl_mask_xor(mask_out, tmp_cplimg_mask);
481 } else if (p_loc->method == HDRL_BPM_3D_THRESHOLD_ERROR) {
482 /* Using scaled pixel error bars to detect bp -
483 * we use the propagated error */
484 cpl_size nx = hdrl_image_get_size_x(tmp_hdrlimg);
485 cpl_size ny = hdrl_image_get_size_y(tmp_hdrlimg);
486 mask_out = cpl_mask_new(nx, ny); /*All pixels are now good*/
487
488 for (cpl_size x = 1; x <= nx; ++x) {
489 for (cpl_size y = 1; y <= ny; ++y) {
490 int bad_data;
491 hdrl_value v = hdrl_image_get_pixel(tmp_hdrlimg, x, y,
492 &bad_data);
493
494 if (v.data < -(v.error * p_loc->kappa_low) ||
495 v.data > (v.error * p_loc->kappa_high) || bad_data) {
496 cpl_mask_set(mask_out, x, y, CPL_BINARY_1);
497 }
498 }
499 }
500 /*Here we use the bpm from the image after master frame subtraction
501 * - this is not 100 percent clean but a good approximation */
502 cpl_mask_xor(mask_out, tmp_cplimg_mask);
503 }
504 cpl_imagelist_set(imglist_out, cpl_image_new_from_mask(mask_out), var);
505 cpl_mask_delete(mask_out);
506 hdrl_image_delete(tmp_hdrlimg);
507 }
508
509 if (cpl_error_get_code() != CPL_ERROR_NONE) {
510 cpl_imagelist_delete(imglist_out);
511 imglist_out = NULL;
512 }
513
514 hdrl_parameter_delete(collapse_params);
515
516 /* single master broadcasted over list */
518 hdrl_imagelist_unwrap(masterlist);
519
520 return imglist_out;
521}
522
double hdrl_bpm_3d_parameter_get_kappa_high(const hdrl_parameter *p)
Access the kappa_high in the BPM_3D parameter.
Definition: hdrl_bpm_3d.c:196
double hdrl_bpm_3d_parameter_get_kappa_low(const hdrl_parameter *p)
Access the kappa_low in the BPM_3D parameter.
Definition: hdrl_bpm_3d.c:182
cpl_parameterlist * hdrl_bpm_3d_parameter_create_parlist(const char *base_context, const char *prefix, const hdrl_parameter *defaults)
Create a parameter list for the BPM_3D computation.
Definition: hdrl_bpm_3d.c:231
cpl_imagelist * hdrl_bpm_3d_compute(const hdrl_imagelist *imglist, const hdrl_parameter *params)
detect bad pixels on a stack of identical images
Definition: hdrl_bpm_3d.c:409
hdrl_parameter * hdrl_bpm_3d_parameter_parse_parlist(const cpl_parameterlist *parlist, const char *prefix)
Parse a parameterlist to create input parameters for the BPM_3D.
Definition: hdrl_bpm_3d.c:314
hdrl_bpm_3d_method hdrl_bpm_3d_parameter_get_method(const hdrl_parameter *p)
Access the method in the BPM_3D parameter.
Definition: hdrl_bpm_3d.c:210
cpl_error_code hdrl_bpm_3d_parameter_verify(const hdrl_parameter *param)
Verify basic correctness of the BPM_3D parameters.
Definition: hdrl_bpm_3d.c:128
hdrl_parameter * hdrl_bpm_3d_parameter_create(double kappa_low, double kappa_high, hdrl_bpm_3d_method method)
Creates BPM Parameters object for the imagelist method.
Definition: hdrl_bpm_3d.c:108
cpl_boolean hdrl_bpm_3d_parameter_check(const hdrl_parameter *self)
Check that the parameter is a BPM_3D parameter.
Definition: hdrl_bpm_3d.c:170
hdrl_parameter * hdrl_collapse_median_parameter_create(void)
create a parameter object for median
hdrl_value hdrl_image_get_pixel(const hdrl_image *self, cpl_size xpos, cpl_size ypos, int *pis_rejected)
get pixel values of hdrl_image
Definition: hdrl_image.c:559
hdrl_image * hdrl_image_sub_image_create(const hdrl_image *self, const hdrl_image *other)
Subtract two images.
cpl_mask * hdrl_image_get_mask(hdrl_image *himg)
get cpl bad pixel mask from image
Definition: hdrl_image.c:157
cpl_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
Definition: hdrl_image.c:540
cpl_size hdrl_image_get_size_x(const hdrl_image *self)
return size of X dimension of image
Definition: hdrl_image.c:525
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:105
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
Definition: hdrl_image.c:379
hdrl_image * hdrl_imagelist_unset(hdrl_imagelist *himlist, cpl_size pos)
Remove an image from an imagelist.
cpl_error_code hdrl_imagelist_set(hdrl_imagelist *himlist, hdrl_image *himg, cpl_size pos)
Insert an image into an imagelist.
const hdrl_image * hdrl_imagelist_get_const(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
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_imagelist * hdrl_imagelist_new(void)
Create an empty imagelist.
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