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