31 #include <sinfo_cpl_size.h>
38 #include <sinfo_cpl_size.h>
42 #include "sinfo_distortion.h"
43 #include "sinfo_functions.h"
44 #include "sinfo_msg.h"
45 #include "sinfo_error.h"
46 #include "irplib_flat.h"
47 #include "sinfo_utils_wrappers.h"
49 #include "sinfo_utilities.h"
54 #define ARC_NBSAMPLES 20
55 #define ARC_THRESHFACT (1.0/3.0)
56 #define ARC_MINGOODPIX 100
57 #define ARC_MINARCLENFACT 1.19
58 #define ARC_MINNBARCS 32
59 #define ARC_RANGE_FACT 3.0
60 #define ARC_WINDOWSIZE 10
62 #define TRESH_MEDIAN_MIN 0.0
63 #define TRESH_SIGMA_MAX 200.0
75 static cpl_apertures *
76 sinfo_distortion_detect_arcs_new(cpl_image* ,cpl_image **,
77 int,
int,
double,
int,
int,
int,
int,
double,
int);
80 cpl_apertures * sinfo_distortion_detect_arcs(cpl_image *,
81 cpl_image **,
int,
int,
int,
int,
int,
int) ;
83 sinfo_distortion_fill_badzones(cpl_image *,
int,
int,
int,
int,
double) ;
85 sinfo_distortion_threshold1d(cpl_image *,
double, cpl_image *,
double) ;
87 sinfo_distortion_purge_arcs(cpl_image *, cpl_apertures **,
88 cpl_image **,
int,
int,
double) ;
89 static cpl_bivector **
90 sinfo_distortion_get_arc_positions(cpl_image *,
92 cpl_apertures *,
int,
double **) ;
93 static double sinfo_distortion_fine_pos(cpl_image *, cpl_image *,
int,
int) ;
94 static int sinfo_distortion_sub_hor_lowpass(cpl_image *,
int) ;
95 static cpl_image * sinfo_distortion_remove_ramp(
const cpl_image *) ;
97 sinfo_distortion_smooth(cpl_image* inp,
const int r,
const int d);
118 sinfo_distortion_smooth(cpl_image* inp,
const int r,
const int d)
133 cknull(inp,
"Null input image!");
134 check_nomsg(sx=cpl_image_get_size_x(inp));
135 check_nomsg(sy=cpl_image_get_size_y(inp));
136 check_nomsg(out=cpl_image_duplicate(inp));
137 check_nomsg(pi=cpl_image_get_data_float(inp));
138 check_nomsg(po=cpl_image_get_data_float(out));
143 for(i=min;i<sx-min;i++) {
145 for(z=i-min;z<i+min+1;z++) {
155 for(j=min;j<sy-min;j++) {
157 for(z=j-min;z<j+min+1;z++) {
170 check_nomsg(cpl_image_delete(inp));
190 sinfo_distortion_image_restore(
const cpl_image* inp,
207 const float* pi=NULL;
210 cpl_vector* vec=NULL;
215 cknull(inp,
"Null input image!");
216 check_nomsg(sx=cpl_image_get_size_x(inp));
217 check_nomsg(sy=cpl_image_get_size_y(inp));
218 check_nomsg(out=cpl_image_duplicate(inp));
219 check_nomsg(pi=cpl_image_get_data_float_const(inp));
220 check_nomsg(po=cpl_image_get_data_float(out));
222 check_nomsg(vec=cpl_vector_new(r));
223 check_nomsg(pv=cpl_vector_get_data(vec));
227 for(i=min;i<sx-min;i++) {
229 for(z=i-min;z<i+min+1;z++) {
230 pv[k]=(double)pi[z+j*sx];
233 cknull_nomsg(vec=sinfo_vector_clip(vec,kappa,n,ks_method));
234 check_nomsg(mean=cpl_vector_get_mean(vec));
235 check_nomsg(median=cpl_vector_get_mean(vec));
236 po[i+j*sx]+=(mean-median);
243 for(j=min;j<sy-min;j++) {
245 for(z=j-min;z<j+min+1;z++) {
246 pv[k]=(double)pi[i+z*sx];
249 cknull_nomsg(vec=sinfo_vector_clip(vec,kappa,n,ks_method));
250 check_nomsg(mean=cpl_vector_get_mean(vec));
251 check_nomsg(median=cpl_vector_get_mean(vec));
252 po[i+j*sx]+=(mean-median);
262 check_nomsg(cpl_image_delete((cpl_image*)inp));
293 cpl_polynomial * sinfo_distortion_estimate_new(
294 const cpl_image * org,
303 double arcs_min_arclen_factor,
304 int arcs_window_size,
308 cpl_apertures ** arcs)
310 cpl_image * local_im ;
311 cpl_image * label_image ;
312 double rightmost, leftmost ;
313 cpl_bivector ** arcs_pos ;
317 cpl_bivector * grid ;
320 cpl_vector * values_to_fit ;
321 double * pvalues_to_fit ;
325 cpl_polynomial * poly2d ;
330 cpl_vector * lines_pos_tmp ;
331 cpl_bivector * grid_tmp ;
332 cpl_vector* grid_tot=0;
333 double* pgrid_tmp_x=NULL;
335 double* pgrid_tot=NULL;
336 double* plines_pos_tmp=NULL;
342 if (org == NULL)
return NULL ;
343 if (kappa < 0.0)
return NULL ;
346 n_calib = ARC_NBSAMPLES ;
347 nx = cpl_image_get_size_x(org) ;
350 local_im = sinfo_distortion_remove_ramp(org) ;
353 local_im = cpl_image_duplicate(org) ;
355 if (local_im == NULL) {
356 cpl_msg_error(cpl_func,
"Cannot clean the image") ;
360 local_im=sinfo_distortion_smooth(local_im,smooth_rad,1);
369 cpl_msg_info(cpl_func,
"Detect arcs") ;
370 if ((*arcs = sinfo_distortion_detect_arcs_new(local_im,
372 arc_sat, max_arc_width, kappa,
373 xmin, ymin, xmax, ymax,
374 arcs_min_arclen_factor,arcs_window_size)) == NULL) {
375 cpl_image_delete(local_im) ;
376 cpl_msg_error(cpl_func,
"Cannot detect the arcs") ;
379 n_arcs = cpl_apertures_get_size(*arcs) ;
380 cpl_msg_info(cpl_func,
"%d detected arcs", n_arcs) ;
383 rightmost = leftmost = cpl_apertures_get_pos_x(*arcs, 1) ;
384 for (i=1 ; i<n_arcs ; i++) {
385 if (cpl_apertures_get_pos_x(*arcs, i+1) < leftmost)
386 leftmost = cpl_apertures_get_pos_x(*arcs, i+1) ;
387 if (cpl_apertures_get_pos_x(*arcs, i+1) > rightmost)
388 rightmost = cpl_apertures_get_pos_x(*arcs, i+1) ;
390 min_arc_range = (int)(nx / ARC_RANGE_FACT) ;
391 if ((
int)(rightmost-leftmost) < min_arc_range) {
392 cpl_msg_error(cpl_func,
"too narrow range (%g-%g)<%d",
393 rightmost, leftmost, min_arc_range) ;
394 cpl_apertures_delete(*arcs) ;
395 cpl_image_delete(local_im) ;
396 cpl_image_delete(label_image) ;
401 cpl_msg_info(cpl_func,
"Create deformation grid") ;
402 lines_pos = cpl_malloc(n_arcs *
sizeof(
double)) ;
403 if ((arcs_pos = sinfo_distortion_get_arc_positions(local_im,
404 label_image, *arcs, n_calib, &lines_pos))==NULL){
405 cpl_msg_error(cpl_func,
"cannot get arcs positions") ;
406 cpl_apertures_delete(*arcs) ;
407 cpl_image_delete(local_im) ;
408 cpl_free(lines_pos) ;
409 cpl_image_delete(label_image) ;
412 cpl_image_delete(label_image) ;
413 cpl_image_delete(local_im) ;
416 lines_pos_tmp=cpl_vector_new(n_arcs);
417 plines_pos_tmp=cpl_vector_get_data(lines_pos_tmp);
420 sinfo_msg(
"Fit the 2d polynomial") ;
421 grid = cpl_bivector_new(n_arcs * n_calib) ;
422 pgridx = cpl_bivector_get_x_data(grid) ;
423 pgridy = cpl_bivector_get_y_data(grid) ;
424 values_to_fit = cpl_vector_new(n_arcs * n_calib) ;
425 pvalues_to_fit = cpl_vector_get_data(values_to_fit) ;
427 for (i=0 ; i<n_arcs ; i++) {
428 parc_posx = cpl_bivector_get_x_data(arcs_pos[i]) ;
429 parc_posy = cpl_bivector_get_y_data(arcs_pos[i]) ;
430 for (j=0 ; j<n_calib ; j++) {
431 plines_pos_tmp[i]=lines_pos[i] ;
432 pgridx[j+i*n_calib] = lines_pos[i] ;
433 pgridy[j+i*n_calib] = parc_posy[j] ;
434 pvalues_to_fit[j+i*n_calib] = parc_posx[j] ;
438 n_lines= n_arcs/32.0;
442 cpl_vector_sort(lines_pos_tmp,1);
443 plines_pos_tmp=cpl_vector_get_data(lines_pos_tmp);
444 grid_tmp=cpl_bivector_duplicate(grid);
445 grid_tot=cpl_vector_new(n_calib);
446 pgrid_tmp_x = cpl_bivector_get_x_data(grid_tmp) ;
448 pgrid_tot = cpl_vector_get_data(grid_tot);
449 for(j=0;j<n_calib;j++) {
451 for(i=n_lines ;i<n_arcs;i=i+n_lines)
453 for(k=0;k<n_lines;k++) {
454 pgrid_tot[j] += (plines_pos_tmp[i+k]-
467 for(j=0;j<n_calib;j++) {
468 for (i=0 ; i<n_arcs ; i++) {
469 pgridx[j+i*n_calib]=pgridx[j+i*n_calib]*
470 ((nx/32.0)*n_lines*(31*32/2))/pgrid_tot[j]-offset;
475 pgrid_tmp_x[j+i*n_calib]=pgrid_tmp_x[j+i*n_calib]*
476 ((nx/32.0)*n_lines*(31*32/2))/pgrid_tot[j]-
481 cpl_vector_delete(lines_pos_tmp);
482 cpl_bivector_delete(grid_tmp);
483 cpl_vector_delete(grid_tot);
487 for (i=0 ; i<n_arcs ; i++) cpl_bivector_delete(arcs_pos[i]) ;
489 cpl_free(lines_pos) ;
492 if ((poly2d = sinfo_polynomial_fit_2d_create(grid, values_to_fit,
493 degree, NULL))==NULL) {
494 cpl_msg_error(cpl_func,
"cannot apply the 2d fit") ;
495 cpl_bivector_delete(grid) ;
496 cpl_vector_delete(values_to_fit) ;
497 cpl_apertures_delete(*arcs) ;
502 cpl_bivector_delete(grid) ;
503 cpl_vector_delete(values_to_fit) ;
526 static cpl_apertures * sinfo_distortion_detect_arcs_new(
528 cpl_image ** label_im,
536 double arcs_min_arclen_factor,
537 int arcs_window_size)
539 cpl_image * filt_im ;
540 cpl_matrix * filter ;
541 cpl_image * collapsed ;
543 double threshold, fillval, median_val, sigma ;
545 cpl_apertures * det ;
550 ny = cpl_image_get_size_y(im) ;
555 median_val = cpl_image_get_median_dev(im, &sigma) ;
556 fillval = median_val-sigma/2.0 ;
557 if (sinfo_distortion_fill_badzones(im, xmin, ymin, xmax, ymax,
559 cpl_msg_error(cpl_func,
"cannot fill bad zones") ;
563 filter = cpl_matrix_new(3, 1) ;
564 cpl_matrix_fill(filter, 1.0) ;
566 filt_im = cpl_image_duplicate(im) ;
567 cpl_matrix_delete(filter) ;
571 if (sinfo_distortion_sub_hor_lowpass(filt_im, arcs_window_size) == -1) {
572 cpl_image_delete(filt_im) ;
579 median_val = cpl_image_get_median_dev(filt_im, &sigma) ;
582 if (median_val < TRESH_MEDIAN_MIN) median_val = TRESH_MEDIAN_MIN ;
583 if (sigma > TRESH_SIGMA_MAX) sigma = TRESH_SIGMA_MAX ;
586 threshold = median_val + sigma * kappa ;
589 collapsed = cpl_image_collapse_median_create(filt_im, 0, 0, 0) ;
592 if (sinfo_distortion_threshold1d(filt_im, median_val,
593 collapsed, 0.0)==-1) {
594 cpl_msg_error(cpl_func,
"cannot threshold the filtered image") ;
595 cpl_image_delete(filt_im) ;
596 cpl_image_delete(collapsed) ;
599 cpl_image_delete(collapsed) ;
602 bin_im = cpl_mask_threshold_image_create(filt_im, threshold,
604 cpl_image_delete(filt_im) ;
605 if (bin_im == NULL) {
606 cpl_msg_error(cpl_func,
"cannot binarise the image") ;
611 ngoodpix = cpl_mask_count(bin_im) ;
612 if (ngoodpix < ARC_MINGOODPIX) {
613 cpl_msg_error(cpl_func,
"Too few (%d) white pixels", ngoodpix) ;
614 cpl_mask_delete(bin_im) ;
619 filter = cpl_matrix_new(3, 3) ;
620 cpl_matrix_fill(filter, 1.0) ;
621 cpl_mask_closing(bin_im, filter) ;
622 cpl_matrix_delete(filter) ;
625 *label_im = cpl_image_labelise_mask_create(bin_im, &nobj) ;
626 cpl_mask_delete(bin_im) ;
631 if ((det = cpl_apertures_new_from_image(im, *label_im)) == NULL) {
632 cpl_msg_error(cpl_func,
"Cannot compute arcs stats") ;
633 cpl_image_delete(*label_im) ;
638 min_arclen = (int)(ny /arcs_min_arclen_factor) ;
643 if (sinfo_distortion_purge_arcs(im, &det, label_im, min_arclen,
644 max_arc_width, arc_sat) == -1) {
645 cpl_msg_error(cpl_func,
"Cannot purge the arcs") ;
646 cpl_image_delete(*label_im) ;
648 cpl_apertures_delete(det) ;
652 if (cpl_apertures_get_size(det) < ARC_MINNBARCS) {
653 cpl_msg_error(cpl_func,
"Not enough valid arcs (%"
654 CPL_SIZE_FORMAT
" < %d)",
655 cpl_apertures_get_size(det), ARC_MINNBARCS) ;
656 cpl_image_delete(*label_im) ;
658 cpl_apertures_delete(det) ;
693 cpl_polynomial * sinfo_distortion_estimate(
694 const cpl_image * org,
704 cpl_apertures ** arcs)
707 cpl_image * local_im ;
708 cpl_image * label_image ;
709 double rightmost, leftmost ;
710 cpl_bivector ** arcs_pos ;
714 cpl_bivector * grid ;
717 cpl_vector * values_to_fit ;
718 double * pvalues_to_fit ;
722 cpl_polynomial * poly2d ;
727 cpl_vector * lines_pos_tmp ;
728 cpl_bivector * grid_tmp ;
731 cpl_vector* grid_tot=0;
732 double* pgrid_tmp_x=NULL;
734 double* pgrid_tot=NULL;
735 double* plines_pos_tmp=NULL;
738 if (org == NULL)
return NULL ;
741 n_calib = ARC_NBSAMPLES ;
742 nx = cpl_image_get_size_x(org) ;
745 local_im = sinfo_distortion_remove_ramp(org) ;
748 local_im = cpl_image_duplicate(org) ;
750 if (local_im == NULL) {
751 cpl_msg_error(cpl_func,
"Cannot clean the image") ;
756 cpl_msg_info(cpl_func,
"Detect arcs") ;
757 if ((*arcs = sinfo_distortion_detect_arcs(local_im,
759 arc_sat, max_arc_width,
760 xmin, ymin, xmax, ymax)) == NULL) {
761 cpl_image_delete(local_im) ;
762 cpl_msg_error(cpl_func,
"Cannot detect the arcs") ;
765 n_arcs = cpl_apertures_get_size(*arcs) ;
766 cpl_msg_info(cpl_func,
"%d detected arcs", n_arcs) ;
769 rightmost = leftmost = cpl_apertures_get_pos_x(*arcs, 1) ;
770 for (i=1 ; i<n_arcs ; i++) {
771 if (cpl_apertures_get_pos_x(*arcs, i+1) < leftmost)
772 leftmost = cpl_apertures_get_pos_x(*arcs, i+1) ;
773 if (cpl_apertures_get_pos_x(*arcs, i+1) > rightmost)
774 rightmost = cpl_apertures_get_pos_x(*arcs, i+1) ;
776 min_arc_range = (int)(nx / ARC_RANGE_FACT) ;
777 if ((
int)(rightmost-leftmost) < min_arc_range) {
778 cpl_msg_error(cpl_func,
"too narrow range (%g-%g)<%d",
779 rightmost, leftmost, min_arc_range) ;
780 cpl_apertures_delete(*arcs) ;
781 cpl_image_delete(local_im) ;
782 cpl_image_delete(label_image) ;
787 cpl_msg_info(cpl_func,
"Create deformation grid") ;
788 lines_pos = cpl_malloc(n_arcs *
sizeof(
double)) ;
789 if ((arcs_pos = sinfo_distortion_get_arc_positions(local_im,
790 label_image, *arcs, n_calib, &lines_pos))==NULL){
791 cpl_msg_error(cpl_func,
"cannot get arcs positions") ;
792 cpl_apertures_delete(*arcs) ;
793 cpl_image_delete(local_im) ;
794 cpl_free(lines_pos) ;
795 cpl_image_delete(label_image) ;
798 cpl_image_delete(label_image) ;
799 cpl_image_delete(local_im) ;
802 lines_pos_tmp=cpl_vector_new(n_arcs);
803 plines_pos_tmp=cpl_vector_get_data(lines_pos_tmp);
805 cpl_msg_info(cpl_func,
"Fit the 2d polynomial") ;
806 grid = cpl_bivector_new(n_arcs * n_calib) ;
807 pgridx = cpl_bivector_get_x_data(grid) ;
808 pgridy = cpl_bivector_get_y_data(grid) ;
809 values_to_fit = cpl_vector_new(n_arcs * n_calib) ;
810 pvalues_to_fit = cpl_vector_get_data(values_to_fit) ;
811 for (i=0 ; i<n_arcs ; i++) {
812 parc_posx = cpl_bivector_get_x_data(arcs_pos[i]) ;
813 parc_posy = cpl_bivector_get_y_data(arcs_pos[i]) ;
814 for (j=0 ; j<n_calib ; j++) {
815 plines_pos_tmp[i]=lines_pos[i] ;
816 pgridx[j+i*n_calib] = lines_pos[i] ;
817 pgridy[j+i*n_calib] = parc_posy[j] ;
818 pvalues_to_fit[j+i*n_calib] = parc_posx[j];
829 n_lines= n_arcs/32.0;
833 cpl_vector_sort(lines_pos_tmp,1);
834 plines_pos_tmp=cpl_vector_get_data(lines_pos_tmp);
836 grid_tmp=cpl_bivector_duplicate(grid);
837 grid_tot=cpl_vector_new(n_calib);
838 pgrid_tmp_x = cpl_bivector_get_x_data(grid_tmp) ;
840 pgrid_tot = cpl_vector_get_data(grid_tot);
841 for(j=0;j<n_calib;j++) {
843 for(i=n_lines ;i<n_arcs;i=i+n_lines)
845 for(k=0;k<n_lines;k++) {
846 pgrid_tot[j] += (plines_pos_tmp[i+k]-
859 for(j=0;j<n_calib;j++) {
860 for (i=0 ; i<n_arcs ; i++) {
861 pgridx[j+i*n_calib]=pgridx[j+i*n_calib]*
862 ((nx/32.0)*n_lines*(31*32/2))/pgrid_tot[j]-offset;
867 pgrid_tmp_x[j+i*n_calib]=pgrid_tmp_x[j+i*n_calib]*
868 ((nx/32.0)*n_lines*(31*32/2))/pgrid_tot[j]-
876 for (i=0 ; i<n_arcs ; i++) cpl_bivector_delete(arcs_pos[i]) ;
878 cpl_free(lines_pos) ;
881 if ((poly2d = sinfo_polynomial_fit_2d_create(grid, values_to_fit,
882 degree, NULL))==NULL) {
883 cpl_msg_error(cpl_func,
"cannot apply the 2d fit") ;
884 cpl_bivector_delete(grid) ;
885 cpl_vector_delete(values_to_fit) ;
886 cpl_apertures_delete(*arcs) ;
891 cpl_bivector_delete(grid) ;
892 cpl_vector_delete(values_to_fit) ;
914 static cpl_apertures * sinfo_distortion_detect_arcs(
916 cpl_image ** label_im,
925 cpl_image * filt_im ;
926 cpl_matrix * filter ;
927 cpl_image * collapsed ;
929 double threshold, fillval, median_val, sigma ;
931 cpl_apertures * det ;
936 ny = cpl_image_get_size_y(im) ;
942 median_val = cpl_image_get_median_dev(im, &sigma) ;
943 fillval = median_val-sigma/2.0 ;
944 if (sinfo_distortion_fill_badzones(im, xmin, ymin, xmax, ymax,
946 cpl_msg_error(cpl_func,
"cannot fill bad zones") ;
951 filter = cpl_matrix_new(3, 1) ;
952 cpl_matrix_fill(filter, 1.0) ;
954 filt_im = cpl_image_duplicate(im) ;
955 cpl_matrix_delete(filter) ;
958 if (sinfo_distortion_sub_hor_lowpass(filt_im, ARC_WINDOWSIZE) == -1) {
959 cpl_image_delete(filt_im) ;
964 median_val = cpl_image_get_median_dev(filt_im, &sigma) ;
967 if (median_val < TRESH_MEDIAN_MIN) median_val = TRESH_MEDIAN_MIN ;
968 if (sigma > TRESH_SIGMA_MAX) sigma = TRESH_SIGMA_MAX ;
971 threshold = median_val + sigma * ARC_THRESHFACT ;
974 collapsed = cpl_image_collapse_median_create(filt_im, 0, 0, 0) ;
977 if (sinfo_distortion_threshold1d(filt_im, median_val,
978 collapsed, 0.0)==-1) {
979 cpl_msg_error(cpl_func,
"cannot threshold the filtered image") ;
980 cpl_image_delete(filt_im) ;
981 cpl_image_delete(collapsed) ;
984 cpl_image_delete(collapsed) ;
987 bin_im = cpl_mask_threshold_image_create(filt_im, threshold,
989 cpl_image_delete(filt_im) ;
990 if (bin_im == NULL) {
991 cpl_msg_error(cpl_func,
"cannot binarise the image") ;
996 ngoodpix = cpl_mask_count(bin_im) ;
997 if (ngoodpix < ARC_MINGOODPIX) {
998 cpl_msg_error(cpl_func,
"Too few (%d) white pixels", ngoodpix) ;
999 cpl_mask_delete(bin_im) ;
1004 filter = cpl_matrix_new(3, 3) ;
1005 cpl_matrix_fill(filter, 1.0) ;
1006 cpl_mask_closing(bin_im, filter) ;
1007 cpl_matrix_delete(filter) ;
1010 *label_im = cpl_image_labelise_mask_create(bin_im, &nobj) ;
1011 cpl_mask_delete(bin_im) ;
1014 if ((det = cpl_apertures_new_from_image(im, *label_im)) == NULL) {
1015 cpl_msg_error(cpl_func,
"Cannot compute arcs stats") ;
1016 cpl_image_delete(*label_im) ;
1022 min_arclen = (int)(ny / ARC_MINARCLENFACT) ;
1025 if (sinfo_distortion_purge_arcs(im, &det, label_im, min_arclen,
1026 max_arc_width, arc_sat) == -1) {
1027 cpl_msg_error(cpl_func,
"Cannot purge the arcs") ;
1028 cpl_image_delete(*label_im) ;
1030 cpl_apertures_delete(det) ;
1033 if (cpl_apertures_get_size(det) < ARC_MINNBARCS) {
1034 cpl_msg_error(cpl_func,
"Not enough valid arcs (%"
1035 CPL_SIZE_FORMAT
" < %d)",
1036 cpl_apertures_get_size(det), ARC_MINNBARCS) ;
1037 cpl_image_delete(*label_im) ;
1039 cpl_apertures_delete(det) ;
1047 static int sinfo_distortion_fill_badzones(
1060 if (im == NULL)
return -1 ;
1061 if (cpl_image_get_type(im) != CPL_TYPE_FLOAT)
return -1 ;
1064 pfi = cpl_image_get_data_float(im) ;
1065 nx = cpl_image_get_size_x(im) ;
1066 ny = cpl_image_get_size_y(im) ;
1069 for (i=0 ; i<nx ; i++) {
1070 for (j=0 ; j<ny ; j++) {
1071 if ((i<xmin-1) || (i>xmax-1) || (j<ymin-1) || (j>ymax-1)) {
1072 pfi[i+j*nx] = (float)fillval ;
1079 static int sinfo_distortion_threshold1d(
1091 if (im == NULL)
return -1 ;
1092 if (im1d == NULL)
return -1 ;
1093 if (cpl_image_get_type(im) != CPL_TYPE_FLOAT)
return -1 ;
1094 if (cpl_image_get_type(im1d) != CPL_TYPE_FLOAT)
return -1 ;
1097 pim = cpl_image_get_data_float(im) ;
1098 pim1d = cpl_image_get_data_float(im1d) ;
1099 nx = cpl_image_get_size_x(im) ;
1100 ny = cpl_image_get_size_y(im) ;
1103 for (i=0 ; i<nx ; i++)
1104 if (pim1d[i] < threshold) {
1105 for (j=0 ; j<ny ; j++) pim[i+j*nx] = (
float)newval ;
1112 static int sinfo_distortion_sub_hor_lowpass(
1116 cpl_vector * linehi ;
1117 cpl_vector * linelo ;
1118 cpl_vector * avglinehi ;
1119 cpl_vector * avglinelo ;
1120 double * pavglinehi ;
1122 int lopos, hipos, nx, ny ;
1126 if (im == NULL)
return -1 ;
1127 if (filt_size <= 0)
return -1 ;
1130 nx = cpl_image_get_size_x(im) ;
1131 ny = cpl_image_get_size_y(im) ;
1132 lopos = (int)(ny/4) ;
1133 hipos = (int)(3*ny/4) ;
1136 if ((linehi = cpl_vector_new_from_image_row(im, hipos)) == NULL) {
1139 if ((linelo = cpl_vector_new_from_image_row(im, lopos)) == NULL) {
1140 cpl_vector_delete(linehi) ;
1145 if ((avglinehi = cpl_vector_filter_median_create(linehi,
1146 filt_size)) == NULL) {
1147 cpl_vector_delete(linehi) ;
1148 cpl_vector_delete(linelo) ;
1151 cpl_vector_delete(linehi) ;
1153 if ((avglinelo = cpl_vector_filter_median_create(linelo,
1154 filt_size)) == NULL) {
1155 cpl_vector_delete(linelo) ;
1156 cpl_vector_delete(avglinehi) ;
1159 cpl_vector_delete(linelo) ;
1162 cpl_vector_add(avglinehi, avglinelo) ;
1163 cpl_vector_delete(avglinelo) ;
1164 cpl_vector_divide_scalar(avglinehi, 2.0) ;
1167 pavglinehi = cpl_vector_get_data(avglinehi) ;
1168 pim = cpl_image_get_data_float(im) ;
1169 for (i=0 ; i<nx ; i++) {
1170 for (j=0 ; j<ny ; j++) {
1171 pim[i+j*nx] -= pavglinehi[i] ;
1174 cpl_vector_delete(avglinehi) ;
1186 static int sinfo_distortion_purge_arcs(
1188 cpl_apertures ** arcs,
1189 cpl_image ** lab_im,
1205 if (arcs == NULL)
return -1 ;
1206 if (*arcs == NULL)
return -1 ;
1207 if (*lab_im == NULL)
return -1 ;
1210 nb_arcs = cpl_apertures_get_size(*arcs) ;
1211 nx = cpl_image_get_size_x(*lab_im) ;
1212 ny = cpl_image_get_size_y(*lab_im) ;
1215 int* selection = cpl_malloc(nb_arcs *
sizeof(
int)) ;
1218 for (i=0 ; i<nb_arcs ; i++) {
1219 int arclen = cpl_apertures_get_top(*arcs, i+1) -
1220 cpl_apertures_get_bottom(*arcs, i+1) + 1 ;
1221 int arcwidth = cpl_apertures_get_right(*arcs, i+1) -
1222 cpl_apertures_get_left(*arcs, i+1) + 1 ;
1223 int edge = cpl_apertures_get_left_y(*arcs, i+1) ;
1224 double mean = cpl_apertures_get_mean(*arcs, i+1) ;
1229 (arclen>min_arclen) &&
1230 (arcwidth<max_arcwidth) &&
1250 for (i=0 ; i<nb_arcs ; i++) {
1251 if (selection[i] == 0) {
1252 plabim = cpl_image_get_data_int(*lab_im) ;
1253 for (j=0 ; j<nx*ny ; j++) {
1254 if (plabim[j] == i+1) plabim[j] = 0 ;
1258 cpl_free(selection) ;
1261 bin_im = cpl_mask_threshold_image_create(*lab_im, 0.5, SINFO_DBL_MAX) ;
1262 cpl_image_delete(*lab_im) ;
1263 *lab_im = cpl_image_labelise_mask_create(bin_im, NULL) ;
1264 cpl_mask_delete(bin_im) ;
1267 cpl_apertures_delete(*arcs) ;
1268 *arcs = cpl_apertures_new_from_image(im, *lab_im) ;
1271 if (cpl_apertures_get_size(*arcs) <= 0) {
1272 cpl_msg_error(cpl_func,
"No valid arc found") ;
1279 static cpl_bivector **
1280 sinfo_distortion_get_arc_positions(
1282 cpl_image * label_im,
1283 cpl_apertures * det,
1285 double ** lines_pos)
1289 cpl_image * filt_img ;
1290 cpl_matrix * kernel ;
1291 cpl_bivector ** pos ;
1296 int * arcs_samples_y ;
1303 cpl_mask* mask=NULL;
1308 n_arcs = cpl_apertures_get_size(det) ;
1309 nx = cpl_image_get_size_x(label_im) ;
1310 ny = cpl_image_get_size_y(label_im) ;
1313 pos = cpl_calloc(n_arcs,
sizeof(cpl_bivector*)) ;
1314 for (i=0 ; i<n_arcs ; i++) pos[i] = cpl_bivector_new(nb_samples) ;
1317 kernel = cpl_matrix_new(3, 3) ;
1318 cpl_matrix_fill(kernel, 1.0) ;
1319 filt_img=cpl_image_duplicate(in);
1320 mask=cpl_mask_new(3,3);
1322 cpl_image_filter_mask(filt_img,in,mask,CPL_FILTER_MEDIAN,CPL_BORDER_FILTER);
1323 cpl_mask_delete(mask);
1325 cpl_matrix_delete(kernel) ;
1328 arcs_samples_y = cpl_malloc(n_arcs * nb_samples *
sizeof(
int)) ;
1329 computed = cpl_calloc(n_arcs*nb_samples,
sizeof(
int)) ;
1332 for (j=0 ; j<n_arcs ; j++) {
1333 double arclen = cpl_apertures_get_top(det,j+1) -
1334 cpl_apertures_get_bottom(det,j+1) + 1 ;
1335 for (i=0 ; i<nb_samples ; i++) {
1336 arcs_samples_y[i+j*nb_samples] =
1337 (int)(cpl_apertures_get_bottom(det, j+1) +
1338 (arclen * (i + 0.5)) / (
double)nb_samples) ;
1343 plabel_im = cpl_image_get_data_int(label_im) ;
1344 for (i=0 ; i<nx ; i++) {
1345 for (j=0 ; j<ny ; j++) {
1348 obj = plabel_im[i + j * nx] ;
1350 if (obj==0) continue ;
1355 for (k=0 ; k<nb_samples ; k++) {
1356 if (arcs_samples_y[k+obj*nb_samples] == j) {
1361 if ((use_this_arc) && (computed[k+obj*nb_samples] == 0)) {
1363 if ((x_finepos = sinfo_distortion_fine_pos(filt_img,
1364 label_im, i, j)) < 0.0) {
1365 cpl_msg_error(cpl_func,
"cannot find fine arc position") ;
1366 cpl_image_delete(filt_img) ;
1367 cpl_free(arcs_samples_y);
1368 cpl_free(computed) ;
1369 for (i=0 ; i<n_arcs ; i++) cpl_bivector_delete(pos[i]);
1373 biv_x = cpl_bivector_get_x_data(pos[obj]) ;
1374 biv_y = cpl_bivector_get_y_data(pos[obj]) ;
1375 biv_x[k] = x_finepos ;
1377 (*lines_pos)[obj] = cpl_apertures_get_centroid_x(det,obj+1);
1378 computed[k+obj*nb_samples] = 1 ;
1385 cpl_image_delete(filt_img) ;
1386 cpl_free(arcs_samples_y) ;
1387 cpl_free(computed) ;
1392 sinfo_distortion_fine_pos(
1394 cpl_image * label_im,
1413 nx = cpl_image_get_size_x(im) ;
1417 maxpos = start_pos ;
1418 pim = cpl_image_get_data_float(im) ;
1419 max = (double)pim[start_pos + y * nx] ;
1420 plabel_im = cpl_image_get_data_int(label_im) ;
1421 objnum = plabel_im[start_pos + y * nx] ;
1426 double val = (double)pim[start_pos + y * nx] ;
1427 if (start_pos == 0) grav_c = 0.0 ;
1428 else grav_c += start_pos * val ;
1432 maxpos = start_pos ;
1438 curr_obj = plabel_im[start_pos + y * nx] ;
1439 }
while (curr_obj == objnum) ;
1442 if ((fabs(grav_c) < 1.0e-40) || (fabs(sum) < 1.0e-40)) {
1445 arc_pos = grav_c / sum ;
1446 if (fabs(arc_pos) >= start_pos) arc_pos = maxpos ;
1460 #define IS_NB_TESTPOINTS 8
1461 #define IS_MIN_SLOPE 0.01
1462 #define IS_MAX_SLOPE_DIF 0.075
1463 #define IS_MAX_FIT_EDGE_DIF 0.05
1464 #define IS_MIN_RAMP 10.0
1465 #define IS_MAX_MNERR 13.0
1466 #define IS_MAX_MNERR_DIF 8.0
1467 #define IS_MAX_INTER_DIF 20.0
1468 #define IS_SKIPZONE 2.5
1469 #define SQR(x) ((x)*(x))
1470 static cpl_image * sinfo_distortion_remove_ramp(
const cpl_image * in)
1477 cpl_bivector * testpointlo ;
1478 double * testpointlo_x ;
1479 double * testpointlo_y ;
1480 cpl_bivector * testpointhi ;
1481 double * testpointhi_x ;
1482 double * testpointhi_y ;
1484 double rampdif, fitslope;
1485 double * pol_coefhi,
1487 cpl_vector * median ;
1488 double * median_data ;
1489 double medianerrlo, medianerrhi;
1497 nx = cpl_image_get_size_x(in) ;
1498 ny = cpl_image_get_size_y(in) ;
1501 if (in==NULL)
return NULL ;
1503 if (ny<IS_SKIPZONE*IS_NB_TESTPOINTS){
1504 cpl_msg_error(cpl_func,
"image has %d lines, min=%d ",
1505 ny, (
int)(IS_SKIPZONE*IS_NB_TESTPOINTS*2));
1510 spacing= ny / (IS_SKIPZONE*IS_NB_TESTPOINTS) ;
1514 testpointhi = cpl_bivector_new(IS_NB_TESTPOINTS) ;
1515 testpointhi_x = cpl_bivector_get_x_data(testpointhi) ;
1516 testpointhi_y = cpl_bivector_get_y_data(testpointhi) ;
1517 testpointlo = cpl_bivector_new(IS_NB_TESTPOINTS) ;
1518 testpointlo_x = cpl_bivector_get_x_data(testpointlo) ;
1519 testpointlo_y = cpl_bivector_get_y_data(testpointlo) ;
1521 for (i=0 ; i<IS_NB_TESTPOINTS ; i++) {
1522 int y = yhi + i * spacing;
1523 cpl_vector* tmp_vector = cpl_vector_new_from_image_row(in, y+1) ;
1524 testpointhi_x[i] = y - ny / 2;
1525 testpointhi_y[i] = cpl_vector_get_median_const(tmp_vector) ;
1526 cpl_vector_delete(tmp_vector) ;
1527 y = ylo - i * spacing;
1528 tmp_vector = cpl_vector_new_from_image_row(in, y+1) ;
1529 testpointlo_x[IS_NB_TESTPOINTS-i-1] = y ;
1530 testpointlo_y[IS_NB_TESTPOINTS-i-1]=
1531 cpl_vector_get_median_const(tmp_vector);
1532 cpl_vector_delete(tmp_vector) ;
1537 testpointhi_y, IS_NB_TESTPOINTS) ;
1539 testpointlo_y, IS_NB_TESTPOINTS) ;
1542 median = cpl_vector_new(IS_NB_TESTPOINTS) ;
1543 median_data = cpl_vector_get_data(median) ;
1544 for (i=0 ; i<IS_NB_TESTPOINTS ; i++) {
1545 median_data[i]=SQR(testpointhi_y[i]
1546 - pol_coefhi[0] - pol_coefhi[1] * testpointhi_x[i]);
1548 medianerrhi = cpl_vector_get_median_const(median) ;
1549 for (i=0; i<IS_NB_TESTPOINTS; i++) {
1550 median_data[i]=SQR(testpointlo_y[i]
1551 - pol_coeflo[0] - pol_coeflo[1] * testpointlo_x[i]);
1553 medianerrlo = cpl_vector_get_median_const(median) ;
1554 cpl_vector_delete(median) ;
1555 rampdif = testpointlo_y[IS_NB_TESTPOINTS-1] - testpointhi_y[0];
1556 slope = rampdif / (ny/2.0) ;
1557 fitslope = (pol_coefhi[1] + pol_coeflo[1]) / 2.0 ;
1559 cpl_bivector_delete(testpointlo);
1560 cpl_bivector_delete(testpointhi);
1563 if (fabs(rampdif)<IS_MIN_RAMP ||
1564 fabs(pol_coefhi[1]) < IS_MIN_SLOPE ||
1565 fabs(pol_coeflo[1]) < IS_MIN_SLOPE ||
1566 pol_coefhi[1]/pol_coeflo[1]<0.5 ||
1567 pol_coefhi[1]/pol_coeflo[1]>2.0 ||
1568 fabs(pol_coefhi[1]-pol_coeflo[1])>IS_MAX_SLOPE_DIF ||
1569 fabs(pol_coefhi[0]-pol_coeflo[0]) > IS_MAX_INTER_DIF ||
1570 medianerrlo> IS_MAX_MNERR ||
1571 medianerrhi> IS_MAX_MNERR ||
1572 fabs(medianerrlo-medianerrhi) >IS_MAX_MNERR_DIF ||
1573 fabs(slope-fitslope) > IS_MAX_FIT_EDGE_DIF ||
1574 slope/fitslope<0.5 ||
1575 slope/fitslope>2.0) ramp_present = 0 ;
1576 else ramp_present = 1 ;
1578 cpl_free(pol_coeflo) ;
1579 cpl_free(pol_coefhi) ;
1582 out = cpl_image_duplicate(in) ;
1583 pout = cpl_image_get_data_float(out) ;
1584 if (ramp_present == 1) {
1587 for (j=0 ; j<ny/2 ; j++) {
1588 val = slope * (j-ny/2) ;
1589 for (i=0 ; i<nx ; i++)
1590 pout[i+j*nx] -= val ;
1592 for (j=ny/2 ; j<ny ; j++) {
1593 val = slope * (j-ny) ;
1594 for (i=0 ; i<nx ; i++)
1595 pout[i+j*nx] -= val ;
double * irplib_flat_fit_slope_robust(double *x, double *y, int np)
Fit a slope to a list of points (robust fit).
#define sinfo_msg_error(...)
Print an error message.