30#include "cr2res_bpm.h"
31#include "cr2res_utils.h"
38static cpl_mask * cr2res_bpm_compute_global_stats(
41static cpl_mask * cr2res_bpm_compute_local_stats(
45static cpl_mask * cr2res_bpm_compute_running_filter(
58cr2res_bpm_type bpm_types[CR2RES_NB_BPM_TYPES] = {
62 CR2RES_BPM_OUTOFORDER,
80 cr2res_bpm_method method,
86 cpl_binary * pmask_cur ;
90 if (in == NULL)
return NULL ;
93 if (method == CR2RES_BPM_GLOBAL_STATS) {
94 if ((bpm = cr2res_bpm_compute_global_stats(in, kappa)) == NULL) {
95 cpl_msg_error(__func__,
"Cannot create bad pixels map") ;
98 }
else if (method == CR2RES_BPM_LOCAL_STATS) {
99 if ((bpm = cr2res_bpm_compute_local_stats(in, kappa, 10)) == NULL) {
100 cpl_msg_error(__func__,
"Cannot create bad pixels map") ;
103 }
else if (method == CR2RES_BPM_RUNNING_FILTER) {
104 if ((bpm = cr2res_bpm_compute_running_filter(in, kappa, 10)) == NULL) {
105 cpl_msg_error(__func__,
"Cannot create bad pixels map") ;
117 nx = cpl_mask_get_size_x(bpm) ;
118 ny = cpl_mask_get_size_y(bpm) ;
119 pmask_cur = cpl_mask_get_data(bpm) ;
120 for (j=0 ; j<ny ; j++) {
122 cur_bp_nb = cpl_mask_count_window(bpm, 1, j+1, nx, j+1) ;
124 if (cur_bp_nb > lines_ratio * nx) {
126 for (k=0 ; k<nx ; k++) {
127 pmask_cur[k+j*nx] = CPL_BINARY_0 ;
134 cpl_image_reject_from_mask(in, bpm) ;
135 cpl_detector_interpolate_rejected(in) ;
150 cr2res_bpm_type type)
156 if (bpm == NULL)
return -1 ;
158 tmp = cpl_image_duplicate(bpm);
159 cpl_image_xor_scalar(tmp, NULL, type);
160 cpl_image_reject_value(tmp, CPL_VALUE_ZERO);
161 count = cpl_image_count_rejected(tmp);
162 cpl_image_delete(tmp);
177 cr2res_bpm_type type)
179 cpl_image * bpm_ima ;
182 if (mask == NULL)
return NULL ;
184 bpm_ima = cpl_image_new_from_mask(mask) ;
185 cpl_image_multiply_scalar(bpm_ima, type) ;
206 cpl_mask * bpm_im_bin ;
209 if (in == NULL || bpm == NULL)
return -1 ;
210 if (chip < 1 || chip > CR2RES_NB_DETECTORS)
return -1 ;
214 cpl_msg_error(__func__,
"Cannot load the bpm") ;
218 bpm_im_bin = cpl_mask_threshold_image_create(bpm_im, -0.5, 0.5) ;
219 cpl_mask_not(bpm_im_bin) ;
220 cpl_image_delete(bpm_im) ;
223 cpl_image_reject_from_mask(in, bpm_im_bin);
224 cpl_mask_delete(bpm_im_bin) ;
228 if (cpl_detector_interpolate_rejected(in) != CPL_ERROR_NONE) {
230 cpl_msg_error(__func__,
"Cannot clean the BPM") ;
248 const cpl_image * bpm_ima,
249 cr2res_bpm_type bpm_type)
251 const int * pbpm_ima ;
254 cpl_size i, j, nx, ny, idx ;
257 if (bpm_ima == NULL)
return NULL ;
260 pbpm_ima = cpl_image_get_data_int_const(bpm_ima) ;
261 nx = cpl_image_get_size_x(bpm_ima) ;
262 ny = cpl_image_get_size_y(bpm_ima) ;
265 bpm = cpl_mask_new(nx, ny) ;
266 pbpm = cpl_mask_get_data(bpm) ;
269 for (j=0 ; j<ny ; j++) {
270 for (i=0 ; i<nx ; i++) {
272 if (pbpm_ima[idx] & bpm_type) pbpm[idx] = CPL_BINARY_1 ;
294 cpl_size i, j, nx, ny, idx ;
297 if (bpm_ima == NULL || bpm == NULL)
return -1 ;
298 if (cpl_image_get_type(bpm_ima) != CPL_TYPE_INT)
return -1 ;
301 nx = cpl_image_get_size_x(bpm_ima) ;
302 ny = cpl_image_get_size_y(bpm_ima) ;
303 if (nx != cpl_mask_get_size_x(bpm) || ny != cpl_mask_get_size_y(bpm))
305 pbpm_ima = cpl_image_get_data_int(bpm_ima) ;
306 pbpm = cpl_mask_get_data(bpm) ;
309 for (j=0 ; j<ny ; j++) {
310 for (i=0 ; i<nx ; i++) {
312 if (pbpm[idx]) pbpm_ima[idx] = pbpm_ima[idx] | bpm_code ;
328static cpl_mask * cr2res_bpm_compute_global_stats(
333 double low, high, med, sigma ;
336 med = cpl_image_get_median_dev(img, &sigma) ;
337 if (cpl_error_get_code()) {
338 cpl_msg_error(__func__,
"Cannot compute statistics") ;
341 low = med - kappa * sigma ;
342 high = med + kappa * sigma ;
344 cpl_msg_debug(__func__,
345 "Median %.1f, Sigma %.1f" "BPM_low %.1f, BPM_hi %.1f",
346 med, sigma, low, high);
349 if ((out = cpl_mask_threshold_image_create(img, low, high)) == NULL) {
350 cpl_msg_error(__func__,
"Cannot create bad pixels map") ;
367static cpl_mask * cr2res_bpm_compute_local_stats(
374 double threshold, med, sigma ;
376 cpl_size i, j, nx, ny, llx, lly, urx, ury ;
379 if (img == NULL)
return NULL ;
380 nx = cpl_image_get_size_x(img) ;
381 ny = cpl_image_get_size_y(img) ;
384 out = cpl_mask_new(nx, ny) ;
385 pout = cpl_mask_get_data(out) ;
388 for (i = 0; i < nx ; i++) {
389 for (j = 0; j < ny ; j++) {
394 if (llx < 1) llx = 1 ;
395 if (lly < 1) lly = 1 ;
396 if (urx > nx) urx = nx ;
397 if (ury > ny) ury = ny ;
400 med = cpl_image_get_median_dev_window(img, llx, lly, urx,
404 threshold = med + kappa*sigma ;
407 if (fabs(cpl_image_get(img, i+1, j+1, &badpix)) > threshold)
408 pout[i + j*nx] = CPL_BINARY_1 ;
429static cpl_mask * cr2res_bpm_compute_running_filter(
441 cpl_size i, j, nx, ny ;
444 if (img == NULL)
return NULL ;
445 nx = cpl_image_get_size_x(img) ;
446 ny = cpl_image_get_size_y(img) ;
447 if (nx < size || ny < size)
return NULL ;
448 if (size % 2 != 1)
return NULL ;
451 copy = cpl_image_duplicate(img);
454 kernel = cpl_mask_new(size, 1);
455 cpl_mask_not(kernel);
458 cpl_image_filter_mask(copy, img, kernel, CPL_FILTER_MEDIAN,
460 cpl_mask_delete(kernel);
463 for (i = 1; i <= nx ; i++) {
464 for (j = 1; j <= ny ; j++) {
465 if (cpl_image_get(copy, i, j, &badpix) == 0)
466 cpl_image_reject(copy, i, j);
471 cpl_image_subtract(copy, img);
474 median = cpl_image_get_mad(copy, &mad);
475 mad *= CPL_MATH_STD_MAD;
476 cpl_image_subtract_scalar(copy, median);
479 threshold = kappa * mad;
480 out = cpl_mask_new(nx, ny) ;
481 pout = cpl_mask_get_data(out) ;
483 for (i = 0; i < nx ; i++) {
484 for (j = 0; j < ny ; j++) {
485 if (cpl_image_get(copy, i+1, j+1, &badpix) > threshold)
486 pout[i + j*nx] = CPL_BINARY_1 ;
489 cpl_image_delete(copy);
505cpl_image * cr2res_bpm_mask_edgepix(cpl_image * bpm){
508 out = cpl_image_duplicate(bpm);
510 sx = cpl_image_get_size_x(bpm);
511 sy = cpl_image_get_size_y(bpm);
514 if ((sx <= CR2RES_NB_BPM_EDGEPIX+1) | (sy <= CR2RES_NB_BPM_EDGEPIX+1))
517 for (i=1; i<=sx; i++){
518 for (j=1; j<=CR2RES_NB_BPM_EDGEPIX; j++){
519 cpl_image_set(out,i,j,CR2RES_BPM_EDGEPIX);
520 cpl_image_set(out,i,CR2RES_DETECTOR_SIZE-j+1,CR2RES_BPM_EDGEPIX);
521 cpl_image_set(out,CR2RES_DETECTOR_SIZE-j+1,i,CR2RES_BPM_EDGEPIX);
522 cpl_image_set(out,j,i,CR2RES_BPM_EDGEPIX);
int cr2res_bpm_add_mask(cpl_image *bpm_ima, cpl_mask *bpm, int bpm_code)
Add a mask to a BPM image with a dedicated code
cpl_image * cr2res_bpm_from_mask(cpl_mask *mask, cr2res_bpm_type type)
Create a BPM from a mask.
int cr2res_bpm_set_and_correct_image(cpl_image *in, const char *bpm, int chip, int correct)
Set the BPM and optionally apply the correction to an image.
cpl_mask * cr2res_bpm_compute(cpl_image *in, cr2res_bpm_method method, double kappa, double lines_ratio, int clean_flag)
The BPM computation with min/max threshold.
int cr2res_bpm_count(cpl_image *bpm, cr2res_bpm_type type)
Count BPM of a given type.
cpl_mask * cr2res_bpm_extract_mask(const cpl_image *bpm_ima, cr2res_bpm_type bpm_type)
Extract a mask from a BPM image.
cpl_image * cr2res_io_load_BPM(const char *filename, int detector, int data)
Load an image from a BPM.