00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include <cpl.h>
00037 #include <math.h>
00038
00039
00040 #include "sinfo_distortion.h"
00041 #include "sinfo_functions.h"
00042 #include "sinfo_msg.h"
00043 #include "sinfo_error.h"
00044 #include "sinfo_utils_wrappers.h"
00045 #include "sinfo_irplib_cpl_wrp.h"
00046 #include "sinfo_utilities.h"
00047
00048
00049
00050
00051 #define ARC_NBSAMPLES 20
00052 #define ARC_THRESHFACT (1.0/3.0)
00053 #define ARC_MINGOODPIX 100
00054 #define ARC_MINARCLENFACT 1.19
00055 #define ARC_MINNBARCS 32
00056 #define ARC_RANGE_FACT 3.0
00057 #define ARC_WINDOWSIZE 10
00058
00059 #define TRESH_MEDIAN_MIN 0.0
00060 #define TRESH_SIGMA_MAX 200.0
00061
00062
00066
00067
00068
00069
00070
00071 static cpl_apertures *
00072 sinfo_distortion_detect_arcs_new(cpl_image* ,cpl_image **,
00073 int,int,double,int,int,int,int,double,int);
00074
00075 static
00076 cpl_apertures * sinfo_distortion_detect_arcs(cpl_image *,
00077 cpl_image **, int, int, int, int, int, int) ;
00078 static int
00079 sinfo_distortion_fill_badzones(cpl_image *, int, int, int, int, double) ;
00080 static int
00081 sinfo_distortion_threshold1d(cpl_image *, double, cpl_image *, double) ;
00082 static int
00083 sinfo_distortion_purge_arcs(cpl_image *, cpl_apertures **,
00084 cpl_image **, int, int, double) ;
00085 static cpl_bivector **
00086 sinfo_distortion_get_arc_positions(cpl_image *,
00087 cpl_image *,
00088 cpl_apertures *, int, double **) ;
00089 static double sinfo_distortion_fine_pos(cpl_image *, cpl_image *, int, int) ;
00090 static int sinfo_distortion_sub_hor_lowpass(cpl_image *, int) ;
00091 static cpl_image * sinfo_distortion_remove_ramp(const cpl_image *) ;
00092 static cpl_image *
00093 sinfo_distortion_smooth(cpl_image* inp,const int r,const int d);
00094
00095
00096
00097
00098
00099
00100
00101
00104
00114 static cpl_image *
00115 sinfo_distortion_smooth(cpl_image* inp,const int r,const int d)
00116 {
00117
00118 int sx=0;
00119 int sy=0;
00120 int i=0;
00121 int j=0;
00122 int z=0;
00123
00124 float sum;
00125 cpl_image* out=NULL;
00126 float* pi=NULL;
00127 float* po=NULL;
00128 int min=0;
00129
00130 cknull(inp,"Null input image!");
00131 check_nomsg(sx=cpl_image_get_size_x(inp));
00132 check_nomsg(sy=cpl_image_get_size_y(inp));
00133 check_nomsg(out=cpl_image_duplicate(inp));
00134 check_nomsg(pi=cpl_image_get_data_float(inp));
00135 check_nomsg(po=cpl_image_get_data_float(out));
00136 min = r/2;
00137 switch (d) {
00138 case 0:
00139 for(j=0;j<sy;j++) {
00140 for(i=min;i<sx-min;i++) {
00141 sum=0;
00142 for(z=i-min;z<i+min+1;z++) {
00143 sum+=pi[z+j*sx];
00144 }
00145 po[i+j*sx]=sum/r;
00146 }
00147 }
00148 break;
00149
00150 case 1:
00151 for(i=0;i<sx;i++) {
00152 for(j=min;j<sy-min;j++) {
00153 sum=0;
00154 for(z=j-min;z<j+min+1;z++) {
00155 sum+=pi[i+z*sx];
00156 }
00157 po[i+j*sx]=sum;
00158 }
00159 }
00160 break;
00161
00162 default:
00163 sinfo_msg_error("case not supported");
00164 goto cleanup;
00165
00166 }
00167 check_nomsg(cpl_image_delete(inp));
00168 return out;
00169 cleanup:
00170 return NULL;
00171 }
00172
00173
00186 cpl_image *
00187 sinfo_distortion_image_restore(const cpl_image* inp,
00188 const int r,
00189 const int d,
00190 const double kappa,
00191 const int ks_method,
00192 const int n)
00193 {
00194
00195 int sx=0;
00196 int sy=0;
00197 int i=0;
00198 int j=0;
00199 int z=0;
00200 int k=0;
00201
00202
00203 cpl_image* out=NULL;
00204 const float* pi=NULL;
00205 float* po=NULL;
00206 int min=0;
00207 cpl_vector* vec=NULL;
00208 double* pv=NULL;
00209 double mean=0;
00210 double median=0;
00211
00212 cknull(inp,"Null input image!");
00213 check_nomsg(sx=cpl_image_get_size_x(inp));
00214 check_nomsg(sy=cpl_image_get_size_y(inp));
00215 check_nomsg(out=cpl_image_duplicate(inp));
00216 check_nomsg(pi=cpl_image_get_data_float_const(inp));
00217 check_nomsg(po=cpl_image_get_data_float(out));
00218 min = r/2;
00219 check_nomsg(vec=cpl_vector_new(r));
00220 check_nomsg(pv=cpl_vector_get_data(vec));
00221 switch (d) {
00222 case 0:
00223 for(j=0;j<sy;j++) {
00224 for(i=min;i<sx-min;i++) {
00225 k=0;
00226 for(z=i-min;z<i+min+1;z++) {
00227 pv[k]=(double)pi[z+j*sx];
00228 k++;
00229 }
00230 cknull_nomsg(vec=sinfo_vector_clip(vec,kappa,n,ks_method));
00231 check_nomsg(mean=cpl_vector_get_mean(vec));
00232 check_nomsg(median=cpl_vector_get_mean(vec));
00233 po[i+j*sx]+=(mean-median);
00234 }
00235 }
00236 break;
00237
00238 case 1:
00239 for(i=0;i<sx;i++) {
00240 for(j=min;j<sy-min;j++) {
00241 k=0;
00242 for(z=j-min;z<j+min+1;z++) {
00243 pv[k]=(double)pi[i+z*sx];
00244 k++;
00245 }
00246 cknull_nomsg(vec=sinfo_vector_clip(vec,kappa,n,ks_method));
00247 check_nomsg(mean=cpl_vector_get_mean(vec));
00248 check_nomsg(median=cpl_vector_get_mean(vec));
00249 po[i+j*sx]+=(mean-median);
00250 }
00251 }
00252 break;
00253
00254 default:
00255 sinfo_msg_error("case not supported");
00256 goto cleanup;
00257
00258 }
00259 check_nomsg(cpl_image_delete((cpl_image*)inp));
00260 return out;
00261 cleanup:
00262 return NULL;
00263 }
00264
00265
00289
00290 cpl_polynomial * sinfo_distortion_estimate_new(
00291 const cpl_image * org,
00292 int xmin,
00293 int ymin,
00294 int xmax,
00295 int ymax,
00296 int auto_ramp_sub,
00297 int arc_sat,
00298 int max_arc_width,
00299 double kappa,
00300 double arcs_min_arclen_factor,
00301 int arcs_window_size,
00302 int smooth_rad,
00303 int degree,
00304 double offset,
00305 cpl_apertures ** arcs)
00306 {
00307 cpl_image * local_im ;
00308 cpl_image * label_image ;
00309 double rightmost, leftmost ;
00310 cpl_bivector ** arcs_pos ;
00311 double * parc_posx ;
00312 double * parc_posy ;
00313 double * lines_pos ;
00314 cpl_bivector * grid ;
00315 double * pgridx ;
00316 double * pgridy ;
00317 cpl_vector * values_to_fit ;
00318 double * pvalues_to_fit ;
00319 int min_arc_range ;
00320 int n_calib ;
00321 int n_arcs ;
00322 cpl_polynomial * poly2d ;
00323 int nx ;
00324 int i, j ;
00325
00326
00327 cpl_vector * lines_pos_tmp ;
00328 cpl_bivector * grid_tmp ;
00329 cpl_vector* grid_tot=0;
00330 double* pgrid_tmp_x=NULL;
00331 double* pgrid_tmp_y=NULL;
00332 double* pgrid_tot=NULL;
00333 double* plines_pos_tmp=NULL;
00334 int n_lines=0;
00335 int k=0;
00336
00337
00338
00339 if (org == NULL) return NULL ;
00340 if (kappa < 0.0) return NULL ;
00341
00342
00343 n_calib = ARC_NBSAMPLES ;
00344 nx = cpl_image_get_size_x(org) ;
00345
00346 if (auto_ramp_sub) {
00347 local_im = sinfo_distortion_remove_ramp(org) ;
00348 } else {
00349
00350 local_im = cpl_image_duplicate(org) ;
00351 }
00352 if (local_im == NULL) {
00353 cpl_msg_error(cpl_func, "Cannot clean the image") ;
00354 return NULL ;
00355 }
00356 if(smooth_rad > 1) {
00357 local_im=sinfo_distortion_smooth(local_im,smooth_rad,1);
00358
00359
00360
00361
00362
00363
00364 }
00365
00366 cpl_msg_info(cpl_func, "Detect arcs") ;
00367 if ((*arcs = sinfo_distortion_detect_arcs_new(local_im,
00368 &label_image,
00369 arc_sat, max_arc_width, kappa,
00370 xmin, ymin, xmax, ymax,
00371 arcs_min_arclen_factor,arcs_window_size)) == NULL) {
00372 cpl_image_delete(local_im) ;
00373 cpl_msg_error(cpl_func, "Cannot detect the arcs") ;
00374 return NULL ;
00375 }
00376 n_arcs = cpl_apertures_get_size(*arcs) ;
00377 cpl_msg_info(cpl_func, "%d detected arcs", n_arcs) ;
00378
00379
00380 rightmost = leftmost = cpl_apertures_get_max_x(*arcs, 1) ;
00381 for (i=1 ; i<n_arcs ; i++) {
00382 if (cpl_apertures_get_max_x(*arcs, i+1) < leftmost)
00383 leftmost = cpl_apertures_get_max_x(*arcs, i+1) ;
00384 if (cpl_apertures_get_max_x(*arcs, i+1) > rightmost)
00385 rightmost = cpl_apertures_get_max_x(*arcs, i+1) ;
00386 }
00387 min_arc_range = (int)(nx / ARC_RANGE_FACT) ;
00388 if ((int)(rightmost-leftmost) < min_arc_range) {
00389 cpl_msg_error(cpl_func, "too narrow range (%g-%g)<%d",
00390 rightmost, leftmost, min_arc_range) ;
00391 cpl_apertures_delete(*arcs) ;
00392 cpl_image_delete(local_im) ;
00393 cpl_image_delete(label_image) ;
00394 return NULL ;
00395 }
00396
00397
00398 cpl_msg_info(cpl_func, "Create deformation grid") ;
00399 lines_pos = cpl_malloc(n_arcs * sizeof(double)) ;
00400 if ((arcs_pos = sinfo_distortion_get_arc_positions(local_im,
00401 label_image, *arcs, n_calib, &lines_pos))==NULL){
00402 cpl_msg_error(cpl_func, "cannot get arcs positions") ;
00403 cpl_apertures_delete(*arcs) ;
00404 cpl_image_delete(local_im) ;
00405 cpl_free(lines_pos) ;
00406 cpl_image_delete(label_image) ;
00407 return NULL ;
00408 }
00409 cpl_image_delete(label_image) ;
00410 cpl_image_delete(local_im) ;
00411
00412
00413 lines_pos_tmp=cpl_vector_new(n_arcs);
00414 plines_pos_tmp=cpl_vector_get_data(lines_pos_tmp);
00415
00416
00417 sinfo_msg("Fit the 2d polynomial") ;
00418 grid = cpl_bivector_new(n_arcs * n_calib) ;
00419 pgridx = cpl_bivector_get_x_data(grid) ;
00420 pgridy = cpl_bivector_get_y_data(grid) ;
00421 values_to_fit = cpl_vector_new(n_arcs * n_calib) ;
00422 pvalues_to_fit = cpl_vector_get_data(values_to_fit) ;
00423
00424 for (i=0 ; i<n_arcs ; i++) {
00425 parc_posx = cpl_bivector_get_x_data(arcs_pos[i]) ;
00426 parc_posy = cpl_bivector_get_y_data(arcs_pos[i]) ;
00427 for (j=0 ; j<n_calib ; j++) {
00428 plines_pos_tmp[i]=lines_pos[i] ;
00429 pgridx[j+i*n_calib] = lines_pos[i] ;
00430 pgridy[j+i*n_calib] = parc_posy[j] ;
00431 pvalues_to_fit[j+i*n_calib] = parc_posx[j] ;
00432 }
00433 }
00434
00435 n_lines= n_arcs/32.0;
00436 if(n_lines < 1) {
00437 n_lines=1;
00438 }
00439 cpl_vector_sort(lines_pos_tmp,1);
00440 plines_pos_tmp=cpl_vector_get_data(lines_pos_tmp);
00441 grid_tmp=cpl_bivector_duplicate(grid);
00442 grid_tot=cpl_vector_new(n_calib);
00443 pgrid_tmp_x = cpl_bivector_get_x_data(grid_tmp) ;
00444 pgrid_tmp_y = cpl_bivector_get_y_data(grid_tmp) ;
00445 pgrid_tot = cpl_vector_get_data(grid_tot);
00446 for(j=0;j<n_calib;j++) {
00447 pgrid_tot[j]=0;
00448 for(i=n_lines ;i<n_arcs;i=i+n_lines)
00449 {
00450 for(k=0;k<n_lines;k++) {
00451 pgrid_tot[j] += (plines_pos_tmp[i+k]-
00452 plines_pos_tmp[k]);
00453
00454
00455
00456
00457 }
00458 }
00459
00460
00461
00462 }
00463
00464 for(j=0;j<n_calib;j++) {
00465 for (i=0 ; i<n_arcs ; i++) {
00466 pgridx[j+i*n_calib]=pgridx[j+i*n_calib]*
00467 ((nx/32.0)*n_lines*(31*32/2))/pgrid_tot[j]-offset;
00468
00469
00470
00471
00472 pgrid_tmp_x[j+i*n_calib]=pgrid_tmp_x[j+i*n_calib]*
00473 ((nx/32.0)*n_lines*(31*32/2))/pgrid_tot[j]-
00474 offset;
00475
00476 }
00477 }
00478 cpl_vector_delete(lines_pos_tmp);
00479 cpl_bivector_delete(grid_tmp);
00480 cpl_vector_delete(grid_tot);
00481
00482
00483
00484 for (i=0 ; i<n_arcs ; i++) cpl_bivector_delete(arcs_pos[i]) ;
00485 cpl_free(arcs_pos) ;
00486 cpl_free(lines_pos) ;
00487
00488
00489 if ((poly2d = sinfo_polynomial_fit_2d_create(grid, values_to_fit,
00490 degree, NULL))==NULL) {
00491 cpl_msg_error(cpl_func, "cannot apply the 2d fit") ;
00492 cpl_bivector_delete(grid) ;
00493 cpl_vector_delete(values_to_fit) ;
00494 cpl_apertures_delete(*arcs) ;
00495 return NULL ;
00496 }
00497
00498
00499 cpl_bivector_delete(grid) ;
00500 cpl_vector_delete(values_to_fit) ;
00501 return poly2d ;
00502 }
00503
00504
00505
00506
00522
00523 static cpl_apertures * sinfo_distortion_detect_arcs_new(
00524 cpl_image * im,
00525 cpl_image ** label_im,
00526 int arc_sat,
00527 int max_arc_width,
00528 double kappa,
00529 int xmin,
00530 int ymin,
00531 int xmax,
00532 int ymax,
00533 double arcs_min_arclen_factor,
00534 int arcs_window_size)
00535 {
00536 cpl_image * filt_im ;
00537 cpl_matrix * filter ;
00538 cpl_image * collapsed ;
00539 cpl_mask * bin_im ;
00540 double threshold, fillval, median_val, sigma ;
00541 int min_arclen = 0 ;
00542 cpl_apertures * det ;
00543 int nobj ;
00544 int ngoodpix ;
00545 int ny ;
00546
00547 ny = cpl_image_get_size_y(im) ;
00548
00549 *label_im = NULL ;
00550
00551
00552 median_val = cpl_image_get_median_dev(im, &sigma) ;
00553 fillval = median_val-sigma/2.0 ;
00554 if (sinfo_distortion_fill_badzones(im, xmin, ymin, xmax, ymax,
00555 fillval) == -1) {
00556 cpl_msg_error(cpl_func, "cannot fill bad zones") ;
00557 return NULL ;
00558 }
00559
00560 filter = cpl_matrix_new(3, 1) ;
00561 cpl_matrix_fill(filter, 1.0) ;
00562
00563 filt_im = cpl_image_duplicate(im) ;
00564 cpl_matrix_delete(filter) ;
00565
00566
00567
00568 if (sinfo_distortion_sub_hor_lowpass(filt_im, arcs_window_size) == -1) {
00569 cpl_image_delete(filt_im) ;
00570 return NULL ;
00571 }
00572
00573
00574
00575
00576 median_val = cpl_image_get_median_dev(filt_im, &sigma) ;
00577
00578
00579 if (median_val < TRESH_MEDIAN_MIN) median_val = TRESH_MEDIAN_MIN ;
00580 if (sigma > TRESH_SIGMA_MAX) sigma = TRESH_SIGMA_MAX ;
00581
00582
00583 threshold = median_val + sigma * kappa ;
00584
00585
00586 collapsed = cpl_image_collapse_median_create(filt_im, 0, 0, 0) ;
00587
00588
00589 if (sinfo_distortion_threshold1d(filt_im, median_val,
00590 collapsed, 0.0)==-1) {
00591 cpl_msg_error(cpl_func, "cannot threshold the filtered image") ;
00592 cpl_image_delete(filt_im) ;
00593 cpl_image_delete(collapsed) ;
00594 return NULL ;
00595 }
00596 cpl_image_delete(collapsed) ;
00597
00598
00599 bin_im = cpl_mask_threshold_image_create(filt_im, threshold,
00600 SINFO_DBL_MAX);
00601 cpl_image_delete(filt_im) ;
00602 if (bin_im == NULL) {
00603 cpl_msg_error(cpl_func, "cannot binarise the image") ;
00604 return NULL ;
00605 }
00606
00607
00608 ngoodpix = cpl_mask_count(bin_im) ;
00609 if (ngoodpix < ARC_MINGOODPIX) {
00610 cpl_msg_error(cpl_func, "Too few (%d) white pixels", ngoodpix) ;
00611 cpl_mask_delete(bin_im) ;
00612 return NULL ;
00613 }
00614
00615
00616 filter = cpl_matrix_new(3, 3) ;
00617 cpl_matrix_fill(filter, 1.0) ;
00618 cpl_mask_closing(bin_im, filter) ;
00619 cpl_matrix_delete(filter) ;
00620
00621
00622 *label_im = cpl_image_labelise_mask_create(bin_im, &nobj) ;
00623 cpl_mask_delete(bin_im) ;
00624
00625
00626
00627
00628 if ((det = cpl_apertures_new_from_image(im, *label_im)) == NULL) {
00629 cpl_msg_error(cpl_func, "Cannot compute arcs stats") ;
00630 cpl_image_delete(*label_im) ;
00631 *label_im = NULL ;
00632 return NULL ;
00633 }
00634
00635 min_arclen = (int)(ny /arcs_min_arclen_factor) ;
00636
00637
00638
00639
00640 if (sinfo_distortion_purge_arcs(im, &det, label_im, min_arclen,
00641 max_arc_width, arc_sat) == -1) {
00642 cpl_msg_error(cpl_func, "Cannot purge the arcs") ;
00643 cpl_image_delete(*label_im) ;
00644 *label_im = NULL ;
00645 cpl_apertures_delete(det) ;
00646 return NULL ;
00647 }
00648
00649 if (cpl_apertures_get_size(det) < ARC_MINNBARCS) {
00650 cpl_msg_error(cpl_func, "Not enough valid arcs (%d < %d)",
00651 cpl_apertures_get_size(det), ARC_MINNBARCS) ;
00652 cpl_image_delete(*label_im) ;
00653 *label_im = NULL ;
00654 cpl_apertures_delete(det) ;
00655 return NULL ;
00656 }
00657
00658
00659 return det ;
00660 }
00661
00662
00663
00664
00688
00689 cpl_polynomial * sinfo_distortion_estimate(
00690 const cpl_image * org,
00691 int xmin,
00692 int ymin,
00693 int xmax,
00694 int ymax,
00695 int auto_ramp_sub,
00696 int arc_sat,
00697 int max_arc_width,
00698 int degree,
00699 double offset,
00700 cpl_apertures ** arcs)
00701 {
00702 const char * fctid = "sinfo_distortion_estimate" ;
00703 cpl_image * local_im ;
00704 cpl_image * label_image ;
00705 double rightmost, leftmost ;
00706 cpl_bivector ** arcs_pos ;
00707 double * parc_posx ;
00708 double * parc_posy ;
00709 double * lines_pos ;
00710 cpl_bivector * grid ;
00711 double * pgridx ;
00712 double * pgridy ;
00713 cpl_vector * values_to_fit ;
00714 double * pvalues_to_fit ;
00715 int min_arc_range ;
00716 int n_calib ;
00717 int n_arcs ;
00718 cpl_polynomial * poly2d ;
00719 int nx ;
00720 int i, j ;
00721
00722
00723 cpl_vector * lines_pos_tmp ;
00724 cpl_bivector * grid_tmp ;
00725 int n_lines=0;
00726 int k=0;
00727 cpl_vector* grid_tot=0;
00728 double* pgrid_tmp_x=NULL;
00729 double* pgrid_tmp_y=NULL;
00730 double* pgrid_tot=NULL;
00731 double* plines_pos_tmp=NULL;
00732
00733
00734 if (org == NULL) return NULL ;
00735
00736
00737 n_calib = ARC_NBSAMPLES ;
00738 nx = cpl_image_get_size_x(org) ;
00739
00740 if (auto_ramp_sub) {
00741 local_im = sinfo_distortion_remove_ramp(org) ;
00742 } else {
00743
00744 local_im = cpl_image_duplicate(org) ;
00745 }
00746 if (local_im == NULL) {
00747 cpl_msg_error(fctid, "Cannot clean the image") ;
00748 return NULL ;
00749 }
00750
00751
00752 cpl_msg_info(fctid, "Detect arcs") ;
00753 if ((*arcs = sinfo_distortion_detect_arcs(local_im,
00754 &label_image,
00755 arc_sat, max_arc_width,
00756 xmin, ymin, xmax, ymax)) == NULL) {
00757 cpl_image_delete(local_im) ;
00758 cpl_msg_error(fctid, "Cannot detect the arcs") ;
00759 return NULL ;
00760 }
00761 n_arcs = cpl_apertures_get_size(*arcs) ;
00762 cpl_msg_info(fctid, "%d detected arcs", n_arcs) ;
00763
00764
00765 rightmost = leftmost = cpl_apertures_get_max_x(*arcs, 1) ;
00766 for (i=1 ; i<n_arcs ; i++) {
00767 if (cpl_apertures_get_max_x(*arcs, i+1) < leftmost)
00768 leftmost = cpl_apertures_get_max_x(*arcs, i+1) ;
00769 if (cpl_apertures_get_max_x(*arcs, i+1) > rightmost)
00770 rightmost = cpl_apertures_get_max_x(*arcs, i+1) ;
00771 }
00772 min_arc_range = (int)(nx / ARC_RANGE_FACT) ;
00773 if ((int)(rightmost-leftmost) < min_arc_range) {
00774 cpl_msg_error(fctid, "too narrow range (%g-%g)<%d",
00775 rightmost, leftmost, min_arc_range) ;
00776 cpl_apertures_delete(*arcs) ;
00777 cpl_image_delete(local_im) ;
00778 cpl_image_delete(label_image) ;
00779 return NULL ;
00780 }
00781
00782
00783 cpl_msg_info(fctid, "Create deformation grid") ;
00784 lines_pos = cpl_malloc(n_arcs * sizeof(double)) ;
00785 if ((arcs_pos = sinfo_distortion_get_arc_positions(local_im,
00786 label_image, *arcs, n_calib, &lines_pos))==NULL){
00787 cpl_msg_error(fctid, "cannot get arcs positions") ;
00788 cpl_apertures_delete(*arcs) ;
00789 cpl_image_delete(local_im) ;
00790 cpl_free(lines_pos) ;
00791 cpl_image_delete(label_image) ;
00792 return NULL ;
00793 }
00794 cpl_image_delete(label_image) ;
00795 cpl_image_delete(local_im) ;
00796
00797
00798 lines_pos_tmp=cpl_vector_new(n_arcs);
00799 plines_pos_tmp=cpl_vector_get_data(lines_pos_tmp);
00800
00801 cpl_msg_info(fctid, "Fit the 2d polynomial") ;
00802 grid = cpl_bivector_new(n_arcs * n_calib) ;
00803 pgridx = cpl_bivector_get_x_data(grid) ;
00804 pgridy = cpl_bivector_get_y_data(grid) ;
00805 values_to_fit = cpl_vector_new(n_arcs * n_calib) ;
00806 pvalues_to_fit = cpl_vector_get_data(values_to_fit) ;
00807 for (i=0 ; i<n_arcs ; i++) {
00808 parc_posx = cpl_bivector_get_x_data(arcs_pos[i]) ;
00809 parc_posy = cpl_bivector_get_y_data(arcs_pos[i]) ;
00810 for (j=0 ; j<n_calib ; j++) {
00811 plines_pos_tmp[i]=lines_pos[i] ;
00812 pgridx[j+i*n_calib] = lines_pos[i] ;
00813 pgridy[j+i*n_calib] = parc_posy[j] ;
00814 pvalues_to_fit[j+i*n_calib] = parc_posx[j];
00815
00816
00817
00818
00819
00820 }
00821 }
00822
00823
00824
00825 n_lines= n_arcs/32.0;
00826 if(n_lines < 1) {
00827 n_lines=1;
00828 }
00829 cpl_vector_sort(lines_pos_tmp,1);
00830 plines_pos_tmp=cpl_vector_get_data(lines_pos_tmp);
00831
00832 grid_tmp=cpl_bivector_duplicate(grid);
00833 grid_tot=cpl_vector_new(n_calib);
00834 pgrid_tmp_x = cpl_bivector_get_x_data(grid_tmp) ;
00835 pgrid_tmp_y = cpl_bivector_get_y_data(grid_tmp) ;
00836 pgrid_tot = cpl_vector_get_data(grid_tot);
00837 for(j=0;j<n_calib;j++) {
00838 pgrid_tot[j]=0;
00839 for(i=n_lines ;i<n_arcs;i=i+n_lines)
00840 {
00841 for(k=0;k<n_lines;k++) {
00842 pgrid_tot[j] += (plines_pos_tmp[i+k]-
00843 plines_pos_tmp[k]);
00844
00845
00846
00847
00848 }
00849 }
00850
00851
00852
00853 }
00854
00855 for(j=0;j<n_calib;j++) {
00856 for (i=0 ; i<n_arcs ; i++) {
00857 pgridx[j+i*n_calib]=pgridx[j+i*n_calib]*
00858 ((nx/32.0)*n_lines*(31*32/2))/pgrid_tot[j]-offset;
00859
00860
00861
00862
00863 pgrid_tmp_x[j+i*n_calib]=pgrid_tmp_x[j+i*n_calib]*
00864 ((nx/32.0)*n_lines*(31*32/2))/pgrid_tot[j]-
00865 offset;
00866
00867 }
00868 }
00869
00870
00871
00872 for (i=0 ; i<n_arcs ; i++) cpl_bivector_delete(arcs_pos[i]) ;
00873 cpl_free(arcs_pos) ;
00874 cpl_free(lines_pos) ;
00875
00876
00877 if ((poly2d = sinfo_polynomial_fit_2d_create(grid, values_to_fit,
00878 degree, NULL))==NULL) {
00879 cpl_msg_error(fctid, "cannot apply the 2d fit") ;
00880 cpl_bivector_delete(grid) ;
00881 cpl_vector_delete(values_to_fit) ;
00882 cpl_apertures_delete(*arcs) ;
00883 return NULL ;
00884 }
00885
00886
00887 cpl_bivector_delete(grid) ;
00888 cpl_vector_delete(values_to_fit) ;
00889 return poly2d ;
00890 }
00891
00894
00909
00910 static cpl_apertures * sinfo_distortion_detect_arcs(
00911 cpl_image * im,
00912 cpl_image ** label_im,
00913 int arc_sat,
00914 int max_arc_width,
00915 int xmin,
00916 int ymin,
00917 int xmax,
00918 int ymax)
00919 {
00920 const char * fctid = "sinfo_distortion_detect_arcs" ;
00921 cpl_image * filt_im ;
00922 cpl_matrix * filter ;
00923 cpl_image * collapsed ;
00924 cpl_mask * bin_im ;
00925 double threshold, fillval, median_val, sigma ;
00926 int min_arclen = 0 ;
00927 cpl_apertures * det ;
00928 int nobj ;
00929 int ngoodpix ;
00930 int ny ;
00931
00932 ny = cpl_image_get_size_y(im) ;
00933
00934
00935 *label_im = NULL ;
00936
00937
00938 median_val = cpl_image_get_median_dev(im, &sigma) ;
00939 fillval = median_val-sigma/2.0 ;
00940 if (sinfo_distortion_fill_badzones(im, xmin, ymin, xmax, ymax,
00941 fillval) == -1) {
00942 cpl_msg_error(fctid, "cannot fill bad zones") ;
00943 return NULL ;
00944 }
00945
00946
00947 filter = cpl_matrix_new(3, 1) ;
00948 cpl_matrix_fill(filter, 1.0) ;
00949
00950 filt_im = cpl_image_duplicate(im) ;
00951 cpl_matrix_delete(filter) ;
00952
00953
00954 if (sinfo_distortion_sub_hor_lowpass(filt_im, ARC_WINDOWSIZE) == -1) {
00955 cpl_image_delete(filt_im) ;
00956 return NULL ;
00957 }
00958
00959
00960 median_val = cpl_image_get_median_dev(filt_im, &sigma) ;
00961
00962
00963 if (median_val < TRESH_MEDIAN_MIN) median_val = TRESH_MEDIAN_MIN ;
00964 if (sigma > TRESH_SIGMA_MAX) sigma = TRESH_SIGMA_MAX ;
00965
00966
00967 threshold = median_val + sigma * ARC_THRESHFACT ;
00968
00969
00970 collapsed = cpl_image_collapse_median_create(filt_im, 0, 0, 0) ;
00971
00972
00973 if (sinfo_distortion_threshold1d(filt_im, median_val,
00974 collapsed, 0.0)==-1) {
00975 cpl_msg_error(fctid, "cannot threshold the filtered image") ;
00976 cpl_image_delete(filt_im) ;
00977 cpl_image_delete(collapsed) ;
00978 return NULL ;
00979 }
00980 cpl_image_delete(collapsed) ;
00981
00982
00983 bin_im = cpl_mask_threshold_image_create(filt_im, threshold,
00984 SINFO_DBL_MAX);
00985 cpl_image_delete(filt_im) ;
00986 if (bin_im == NULL) {
00987 cpl_msg_error(fctid, "cannot binarise the image") ;
00988 return NULL ;
00989 }
00990
00991
00992 ngoodpix = cpl_mask_count(bin_im) ;
00993 if (ngoodpix < ARC_MINGOODPIX) {
00994 cpl_msg_error(fctid, "Too few (%d) white pixels", ngoodpix) ;
00995 cpl_mask_delete(bin_im) ;
00996 return NULL ;
00997 }
00998
00999
01000 filter = cpl_matrix_new(3, 3) ;
01001 cpl_matrix_fill(filter, 1.0) ;
01002 cpl_mask_closing(bin_im, filter) ;
01003 cpl_matrix_delete(filter) ;
01004
01005
01006 *label_im = cpl_image_labelise_mask_create(bin_im, &nobj) ;
01007 cpl_mask_delete(bin_im) ;
01008
01009
01010 if ((det = cpl_apertures_new_from_image(im, *label_im)) == NULL) {
01011 cpl_msg_error(fctid, "Cannot compute arcs stats") ;
01012 cpl_image_delete(*label_im) ;
01013 *label_im = NULL ;
01014 return NULL ;
01015 }
01016
01017
01018 min_arclen = (int)(ny / ARC_MINARCLENFACT) ;
01019
01020
01021 if (sinfo_distortion_purge_arcs(im, &det, label_im, min_arclen,
01022 max_arc_width, arc_sat) == -1) {
01023 cpl_msg_error(fctid, "Cannot purge the arcs") ;
01024 cpl_image_delete(*label_im) ;
01025 *label_im = NULL ;
01026 cpl_apertures_delete(det) ;
01027 return NULL ;
01028 }
01029 if (cpl_apertures_get_size(det) < ARC_MINNBARCS) {
01030 cpl_msg_error(fctid, "Not enough valid arcs (%d < %d)",
01031 cpl_apertures_get_size(det), ARC_MINNBARCS) ;
01032 cpl_image_delete(*label_im) ;
01033 *label_im = NULL ;
01034 cpl_apertures_delete(det) ;
01035 return NULL ;
01036 }
01037
01038
01039 return det ;
01040 }
01041
01042 static int sinfo_distortion_fill_badzones(
01043 cpl_image * im,
01044 int xmin,
01045 int ymin,
01046 int xmax,
01047 int ymax,
01048 double fillval)
01049 {
01050 float * pfi ;
01051 int nx, ny ;
01052 int i, j ;
01053
01054
01055 if (im == NULL) return -1 ;
01056 if (cpl_image_get_type(im) != CPL_TYPE_FLOAT) return -1 ;
01057
01058
01059 pfi = cpl_image_get_data_float(im) ;
01060 nx = cpl_image_get_size_x(im) ;
01061 ny = cpl_image_get_size_y(im) ;
01062
01063
01064 for (i=0 ; i<nx ; i++) {
01065 for (j=0 ; j<ny ; j++) {
01066 if ((i<xmin-1) || (i>xmax-1) || (j<ymin-1) || (j>ymax-1)) {
01067 pfi[i+j*nx] = (float)fillval ;
01068 }
01069 }
01070 }
01071 return 0 ;
01072 }
01073
01074 static int sinfo_distortion_threshold1d(
01075 cpl_image * im,
01076 double threshold,
01077 cpl_image * im1d,
01078 double newval)
01079 {
01080 float * pim ;
01081 float * pim1d ;
01082 int nx, ny ;
01083 int i, j ;
01084
01085
01086 if (im == NULL) return -1 ;
01087 if (im1d == NULL) return -1 ;
01088 if (cpl_image_get_type(im) != CPL_TYPE_FLOAT) return -1 ;
01089 if (cpl_image_get_type(im1d) != CPL_TYPE_FLOAT) return -1 ;
01090
01091
01092 pim = cpl_image_get_data_float(im) ;
01093 pim1d = cpl_image_get_data_float(im1d) ;
01094 nx = cpl_image_get_size_x(im) ;
01095 ny = cpl_image_get_size_y(im) ;
01096
01097
01098 for (i=0 ; i<nx ; i++)
01099 if (pim1d[i] < threshold) {
01100 for (j=0 ; j<ny ; j++) pim[i+j*nx] = (float)newval ;
01101 }
01102
01103
01104 return 0 ;
01105 }
01106
01107 static int sinfo_distortion_sub_hor_lowpass(
01108 cpl_image * im,
01109 int filt_size)
01110 {
01111 cpl_vector * linehi ;
01112 cpl_vector * linelo ;
01113 cpl_vector * avglinehi ;
01114 cpl_vector * avglinelo ;
01115 double * pavglinehi ;
01116 float * pim ;
01117 int lopos, hipos, nx, ny ;
01118 int i, j ;
01119
01120
01121 if (im == NULL) return -1 ;
01122 if (filt_size <= 0) return -1 ;
01123
01124
01125 nx = cpl_image_get_size_x(im) ;
01126 ny = cpl_image_get_size_y(im) ;
01127 lopos = (int)(ny/4) ;
01128 hipos = (int)(3*ny/4) ;
01129
01130
01131 if ((linehi = cpl_vector_new_from_image_row(im, hipos)) == NULL) {
01132 return -1 ;
01133 }
01134 if ((linelo = cpl_vector_new_from_image_row(im, lopos)) == NULL) {
01135 cpl_vector_delete(linehi) ;
01136 return -1 ;
01137 }
01138
01139
01140 if ((avglinehi = cpl_vector_filter_median_create(linehi,
01141 filt_size)) == NULL) {
01142 cpl_vector_delete(linehi) ;
01143 cpl_vector_delete(linelo) ;
01144 return -1 ;
01145 }
01146 cpl_vector_delete(linehi) ;
01147
01148 if ((avglinelo = cpl_vector_filter_median_create(linelo,
01149 filt_size)) == NULL) {
01150 cpl_vector_delete(linelo) ;
01151 cpl_vector_delete(avglinehi) ;
01152 return -1 ;
01153 }
01154 cpl_vector_delete(linelo) ;
01155
01156
01157 cpl_vector_add(avglinehi, avglinelo) ;
01158 cpl_vector_delete(avglinelo) ;
01159 cpl_vector_divide_scalar(avglinehi, 2.0) ;
01160
01161
01162 pavglinehi = cpl_vector_get_data(avglinehi) ;
01163 pim = cpl_image_get_data_float(im) ;
01164 for (i=0 ; i<nx ; i++) {
01165 for (j=0 ; j<ny ; j++) {
01166 pim[i+j*nx] -= pavglinehi[i] ;
01167 }
01168 }
01169 cpl_vector_delete(avglinehi) ;
01170
01171 return 0 ;
01172 }
01173
01174
01175
01176
01177
01178
01179
01180
01181 static int sinfo_distortion_purge_arcs(
01182 cpl_image * im,
01183 cpl_apertures ** arcs,
01184 cpl_image ** lab_im,
01185 int min_arclen,
01186 int max_arcwidth,
01187 double arc_sat)
01188 {
01189 const char * fctid = "sinfo_distortion_purge_arcs" ;
01190 int nb_arcs ;
01191 int * selection ;
01192 int arclen, arcwidth, edge ;
01193 double mean ;
01194 int * plabim ;
01195 cpl_mask * bin_im ;
01196 int nx, ny ;
01197 int i, j ;
01198
01199
01200 if (arcs == NULL) return -1 ;
01201 if (*arcs == NULL) return -1 ;
01202 if (*lab_im == NULL) return -1 ;
01203
01204
01205 nb_arcs = cpl_apertures_get_size(*arcs) ;
01206 nx = cpl_image_get_size_x(*lab_im) ;
01207 ny = cpl_image_get_size_y(*lab_im) ;
01208
01209
01210 selection = cpl_malloc(nb_arcs * sizeof(int)) ;
01211
01212
01213 for (i=0 ; i<nb_arcs ; i++) {
01214 arclen = cpl_apertures_get_top(*arcs, i+1) -
01215 cpl_apertures_get_bottom(*arcs, i+1) + 1 ;
01216 arcwidth = cpl_apertures_get_right(*arcs, i+1) -
01217 cpl_apertures_get_left(*arcs, i+1) + 1 ;
01218 edge = cpl_apertures_get_left_y(*arcs, i+1) ;
01219 mean = cpl_apertures_get_mean(*arcs, i+1) ;
01220
01221
01222
01223 if (
01224 (arclen>min_arclen) &&
01225 (arcwidth<max_arcwidth) &&
01226 (edge>0) &&
01227 (mean < arc_sat)) {
01228
01229
01230
01231
01232
01233 selection[i] = 1 ;
01234 } else {
01235
01236
01237
01238
01239
01240 selection[i] = 0 ;
01241 }
01242 }
01243
01244
01245 for (i=0 ; i<nb_arcs ; i++) {
01246 if (selection[i] == 0) {
01247 plabim = cpl_image_get_data_int(*lab_im) ;
01248 for (j=0 ; j<nx*ny ; j++) {
01249 if (plabim[j] == i+1) plabim[j] = 0 ;
01250 }
01251 }
01252 }
01253 cpl_free(selection) ;
01254
01255
01256 bin_im = cpl_mask_threshold_image_create(*lab_im, 0.5, SINFO_DBL_MAX) ;
01257 cpl_image_delete(*lab_im) ;
01258 *lab_im = cpl_image_labelise_mask_create(bin_im, NULL) ;
01259 cpl_mask_delete(bin_im) ;
01260
01261
01262 cpl_apertures_delete(*arcs) ;
01263 *arcs = cpl_apertures_new_from_image(im, *lab_im) ;
01264
01265
01266 if (cpl_apertures_get_size(*arcs) <= 0) {
01267 cpl_msg_error(fctid, "No valid arc found") ;
01268 return -1 ;
01269 }
01270
01271 return 0 ;
01272 }
01273
01274 static cpl_bivector **
01275 sinfo_distortion_get_arc_positions(
01276 cpl_image * in,
01277 cpl_image * label_im,
01278 cpl_apertures * det,
01279 int nb_samples,
01280 double ** lines_pos)
01281 {
01282 const char * fctid = "sinfo_distortion_get_arc_positions" ;
01283 int n_arcs ;
01284 cpl_image * filt_img ;
01285 cpl_matrix * kernel ;
01286 cpl_bivector ** pos ;
01287 double * biv_x ;
01288 double * biv_y ;
01289 double x_finepos ;
01290 int * plabel_im ;
01291 int * arcs_samples_y ;
01292 int * computed ;
01293 double arclen ;
01294 int use_this_arc ;
01295 int obj ;
01296 int nx, ny ;
01297 int i, j, k ;
01298 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
01299 cpl_mask* mask=NULL;
01300 #endif
01301
01302
01303
01304
01305 n_arcs = cpl_apertures_get_size(det) ;
01306 nx = cpl_image_get_size_x(label_im) ;
01307 ny = cpl_image_get_size_y(label_im) ;
01308
01309
01310 pos = cpl_calloc(n_arcs, sizeof(cpl_bivector*)) ;
01311 for (i=0 ; i<n_arcs ; i++) pos[i] = cpl_bivector_new(nb_samples) ;
01312
01313
01314 kernel = cpl_matrix_new(3, 3) ;
01315 cpl_matrix_fill(kernel, 1.0) ;
01316 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
01317 filt_img=cpl_image_duplicate(in);
01318 mask=cpl_mask_new(3,3);
01319 cpl_mask_not(mask);
01320 cpl_image_filter_mask(filt_img,in,mask,CPL_FILTER_MEDIAN,CPL_BORDER_FILTER);
01321 cpl_mask_delete(mask);
01322 #else
01323 filt_img = cpl_image_filter_median(in, kernel) ;
01324 #endif
01325 cpl_matrix_delete(kernel) ;
01326
01327
01328 arcs_samples_y = cpl_malloc(n_arcs * nb_samples * sizeof(int)) ;
01329 computed = cpl_calloc(n_arcs*nb_samples, sizeof(int)) ;
01330
01331
01332 for (j=0 ; j<n_arcs ; j++) {
01333 arclen = cpl_apertures_get_top(det,j+1) -
01334 cpl_apertures_get_bottom(det,j+1) + 1 ;
01335 for (i=0 ; i<nb_samples ; i++) {
01336 arcs_samples_y[i+j*nb_samples] =
01337 (int)(cpl_apertures_get_bottom(det, j+1) +
01338 (arclen * (i + 0.5)) / (double)nb_samples) ;
01339 }
01340 }
01341
01342
01343 plabel_im = cpl_image_get_data_int(label_im) ;
01344 for (i=0 ; i<nx ; i++) {
01345 for (j=0 ; j<ny ; j++) {
01346
01347
01348 obj = plabel_im[i + j * nx] ;
01349
01350 if (obj==0) continue ;
01351
01352 else obj-- ;
01353
01354 use_this_arc = 0 ;
01355 for (k=0 ; k<nb_samples ; k++) {
01356 if (arcs_samples_y[k+obj*nb_samples] == j) {
01357 use_this_arc = 1 ;
01358 break ;
01359 }
01360 }
01361 if ((use_this_arc) && (computed[k+obj*nb_samples] == 0)) {
01362
01363 if ((x_finepos = sinfo_distortion_fine_pos(filt_img,
01364 label_im, i, j)) < 0.0) {
01365 cpl_msg_error(fctid, "cannot find fine arc position") ;
01366 cpl_image_delete(filt_img) ;
01367 cpl_free(arcs_samples_y);
01368 cpl_free(computed) ;
01369 for (i=0 ; i<n_arcs ; i++) cpl_bivector_delete(pos[i]);
01370 cpl_free(pos) ;
01371 return NULL ;
01372 } else {
01373 biv_x = cpl_bivector_get_x_data(pos[obj]) ;
01374 biv_y = cpl_bivector_get_y_data(pos[obj]) ;
01375 biv_x[k] = x_finepos ;
01376 biv_y[k] = j ;
01377 (*lines_pos)[obj] = cpl_apertures_get_centroid_x(det,obj+1);
01378 computed[k+obj*nb_samples] = 1 ;
01379 }
01380 }
01381 }
01382 }
01383
01384
01385 cpl_image_delete(filt_img) ;
01386 cpl_free(arcs_samples_y) ;
01387 cpl_free(computed) ;
01388 return pos ;
01389 }
01390
01391 static double
01392 sinfo_distortion_fine_pos(
01393 cpl_image * im,
01394 cpl_image * label_im,
01395 int x,
01396 int y)
01397 {
01398 float * pim ;
01399 int * plabel_im ;
01400 int objnum ;
01401 int curr_obj ;
01402 int start_pos ;
01403 double grav_c ;
01404 double sum ;
01405 double max ;
01406 double val ;
01407 int maxpos ;
01408 int im_extrem ;
01409 double arc_pos ;
01410 int nx ;
01411
01412
01413 nx = cpl_image_get_size_x(im) ;
01414 grav_c = 0.0 ;
01415 sum = 0.0 ;
01416 start_pos = x ;
01417 maxpos = start_pos ;
01418 pim = cpl_image_get_data_float(im) ;
01419 max = (double)pim[start_pos + y * nx] ;
01420 plabel_im = cpl_image_get_data_int(label_im) ;
01421 objnum = plabel_im[start_pos + y * nx] ;
01422 im_extrem = nx ;
01423
01424
01425 do {
01426 val = (double)pim[start_pos + y * nx] ;
01427 if (start_pos == 0) grav_c = 0.0 ;
01428 else grav_c += start_pos * val ;
01429 sum += val ;
01430 if (val > max) {
01431 max = val ;
01432 maxpos = start_pos ;
01433 }
01434
01435
01436 start_pos++ ;
01437
01438 curr_obj = plabel_im[start_pos + y * nx] ;
01439 } while (curr_obj == objnum) ;
01440
01441
01442 if ((fabs(grav_c) < 1.0e-40) || (fabs(sum) < 1.0e-40)) {
01443 arc_pos = maxpos ;
01444 } else {
01445 arc_pos = grav_c / sum ;
01446 if (fabs(arc_pos) >= start_pos) arc_pos = maxpos ;
01447 }
01448
01449
01450 return arc_pos ;
01451 }
01452
01453
01459
01460 #define IS_NB_TESTPOINTS 8
01461 #define IS_MIN_SLOPE 0.01
01462 #define IS_MAX_SLOPE_DIF 0.075
01463 #define IS_MAX_FIT_EDGE_DIF 0.05
01464 #define IS_MIN_RAMP 10.0
01465 #define IS_MAX_MNERR 13.0
01466 #define IS_MAX_MNERR_DIF 8.0
01467 #define IS_MAX_INTER_DIF 20.0
01468 #define IS_SKIPZONE 2.5
01469 #define SQR(x) ((x)*(x))
01470 static cpl_image * sinfo_distortion_remove_ramp(const cpl_image * in)
01471 {
01472 const char * fctid = "sinfo_distortion_remove_ramp" ;
01473 int ramp_present ;
01474 int nx, ny ;
01475 int y, yhi, ylo;
01476 cpl_vector * tmp_vector ;
01477 cpl_bivector * testpointlo ;
01478 double * testpointlo_x ;
01479 double * testpointlo_y ;
01480 cpl_bivector * testpointhi ;
01481 double * testpointhi_x ;
01482 double * testpointhi_y ;
01483 int spacing;
01484 double rampdif, fitslope;
01485 double * pol_coefhi,
01486 * pol_coeflo ;
01487 cpl_vector * median ;
01488 double * median_data ;
01489 double medianerrlo, medianerrhi;
01490 double slope ;
01491 cpl_image * out ;
01492 float * pout ;
01493 float val ;
01494 int i, j ;
01495
01496
01497 nx = cpl_image_get_size_x(in) ;
01498 ny = cpl_image_get_size_y(in) ;
01499
01500
01501 if (in==NULL) return NULL ;
01502
01503 if (ny<IS_SKIPZONE*IS_NB_TESTPOINTS){
01504 cpl_msg_error(fctid, "image has %d lines, min=%d ",
01505 ny, (int)(IS_SKIPZONE*IS_NB_TESTPOINTS*2));
01506 return NULL ;
01507 }
01508
01509 slope=0.0 ;
01510 spacing= ny / (IS_SKIPZONE*IS_NB_TESTPOINTS) ;
01511 yhi = (int)(ny/2) ;
01512 ylo = yhi - 1 ;
01513
01514 testpointhi = cpl_bivector_new(IS_NB_TESTPOINTS) ;
01515 testpointhi_x = cpl_bivector_get_x_data(testpointhi) ;
01516 testpointhi_y = cpl_bivector_get_y_data(testpointhi) ;
01517 testpointlo = cpl_bivector_new(IS_NB_TESTPOINTS) ;
01518 testpointlo_x = cpl_bivector_get_x_data(testpointlo) ;
01519 testpointlo_y = cpl_bivector_get_y_data(testpointlo) ;
01520 for (i=0 ; i<IS_NB_TESTPOINTS ; i++) {
01521 y = yhi + i * spacing;
01522 tmp_vector = cpl_vector_new_from_image_row(in, y+1) ;
01523 testpointhi_x[i] = y - ny / 2;
01524 testpointhi_y[i] = cpl_vector_get_median_const(tmp_vector) ;
01525 cpl_vector_delete(tmp_vector) ;
01526 y = ylo - i * spacing;
01527 tmp_vector = cpl_vector_new_from_image_row(in, y+1) ;
01528 testpointlo_x[IS_NB_TESTPOINTS-i-1] = y ;
01529 testpointlo_y[IS_NB_TESTPOINTS-i-1]=
01530 cpl_vector_get_median_const(tmp_vector);
01531 cpl_vector_delete(tmp_vector) ;
01532 }
01533
01534
01535 pol_coefhi = irplib_flat_fit_slope_robust(testpointhi_x,
01536 testpointhi_y, IS_NB_TESTPOINTS) ;
01537 pol_coeflo = irplib_flat_fit_slope_robust(testpointlo_x,
01538 testpointlo_y, IS_NB_TESTPOINTS) ;
01539
01540
01541 median = cpl_vector_new(IS_NB_TESTPOINTS) ;
01542 median_data = cpl_vector_get_data(median) ;
01543 for (i=0 ; i<IS_NB_TESTPOINTS ; i++) {
01544 median_data[i]=SQR(testpointhi_y[i]
01545 - pol_coefhi[0] - pol_coefhi[1] * testpointhi_x[i]);
01546 }
01547 medianerrhi = cpl_vector_get_median_const(median) ;
01548 for (i=0; i<IS_NB_TESTPOINTS; i++) {
01549 median_data[i]=SQR(testpointlo_y[i]
01550 - pol_coeflo[0] - pol_coeflo[1] * testpointlo_x[i]);
01551 }
01552 medianerrlo = cpl_vector_get_median_const(median) ;
01553 cpl_vector_delete(median) ;
01554 rampdif = testpointlo_y[IS_NB_TESTPOINTS-1] - testpointhi_y[0];
01555 slope = rampdif / (ny/2.0) ;
01556 fitslope = (pol_coefhi[1] + pol_coeflo[1]) / 2.0 ;
01557
01558 cpl_bivector_delete(testpointlo);
01559 cpl_bivector_delete(testpointhi);
01560
01561
01562 if (fabs(rampdif)<IS_MIN_RAMP ||
01563 fabs(pol_coefhi[1]) < IS_MIN_SLOPE ||
01564 fabs(pol_coeflo[1]) < IS_MIN_SLOPE ||
01565 pol_coefhi[1]/pol_coeflo[1]<0.5 ||
01566 pol_coefhi[1]/pol_coeflo[1]>2.0 ||
01567 fabs(pol_coefhi[1]-pol_coeflo[1])>IS_MAX_SLOPE_DIF ||
01568 fabs(pol_coefhi[0]-pol_coeflo[0]) > IS_MAX_INTER_DIF ||
01569 medianerrlo> IS_MAX_MNERR ||
01570 medianerrhi> IS_MAX_MNERR ||
01571 fabs(medianerrlo-medianerrhi) >IS_MAX_MNERR_DIF ||
01572 fabs(slope-fitslope) > IS_MAX_FIT_EDGE_DIF ||
01573 slope/fitslope<0.5 ||
01574 slope/fitslope>2.0) ramp_present = 0 ;
01575 else ramp_present = 1 ;
01576
01577 cpl_free(pol_coeflo) ;
01578 cpl_free(pol_coefhi) ;
01579
01580
01581 out = cpl_image_duplicate(in) ;
01582 pout = cpl_image_get_data_float(out) ;
01583 if (ramp_present == 1) {
01584 for (j=0 ; j<ny/2 ; j++) {
01585 val = slope * (j-ny/2) ;
01586 for (i=0 ; i<nx ; i++)
01587 pout[i+j*nx] -= val ;
01588 }
01589 for (j=ny/2 ; j<ny ; j++) {
01590 val = slope * (j-ny) ;
01591 for (i=0 ; i<nx ; i++)
01592 pout[i+j*nx] -= val ;
01593 }
01594
01595 }
01596
01597 return out ;
01598 }
01599