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 #include "irplib_flat.h"
00040 #include "irplib_distortion.h"
00041
00042
00043
00044
00045
00046 #define ARC_NBSAMPLES 20
00047 #define ARC_MINGOODPIX 100
00048 #define ARC_MINARCLENFACT 2.0
00049 #define ARC_MINNBARCS 4
00050 #define ARC_RANGE_FACT 3.0
00051 #define ARC_WINDOWSIZE 32
00052
00053 #define TRESH_MEDIAN_MIN 0.0
00054 #define TRESH_SIGMA_MAX 200.0
00055
00056
00060
00061
00062
00063
00064
00065
00066 static cpl_apertures * irplib_distortion_detect_arcs(cpl_image *,
00067 cpl_image **, int, int, double, int, int, int, int) ;
00068 static int irplib_distortion_fill_badzones(cpl_image *, int, int, int, int,
00069 double) ;
00070 static int irplib_distortion_threshold1d(cpl_image *, double, cpl_image *,
00071 double) ;
00072 static int irplib_distortion_purge_arcs(cpl_image *, cpl_apertures **,
00073 cpl_image **, int, int, double) ;
00074 static cpl_bivector ** irplib_distortion_get_arc_positions(cpl_image *,
00075 cpl_image *, cpl_apertures *, int, double **) ;
00076 static double irplib_distortion_fine_pos(cpl_image *, cpl_image *, int, int) ;
00077 static int irplib_distortion_sub_hor_lowpass(cpl_image *, int) ;
00078 static cpl_image * irplib_distortion_remove_ramp(const cpl_image *) ;
00079
00080
00081
00082
00083
00086
00110
00111 cpl_polynomial * irplib_distortion_estimate(
00112 const cpl_image * org,
00113 int xmin,
00114 int ymin,
00115 int xmax,
00116 int ymax,
00117 int auto_ramp_sub,
00118 int arc_sat,
00119 int max_arc_width,
00120 double kappa,
00121 int degree,
00122 cpl_apertures ** arcs)
00123 {
00124 cpl_image * local_im ;
00125 cpl_image * label_image ;
00126 double rightmost, leftmost ;
00127 cpl_bivector ** arcs_pos ;
00128 double * parc_posx ;
00129 double * parc_posy ;
00130 double * lines_pos ;
00131 cpl_bivector * grid ;
00132 double * pgridx ;
00133 double * pgridy ;
00134 cpl_vector * values_to_fit ;
00135 double * pvalues_to_fit ;
00136 int min_arc_range ;
00137 int n_calib ;
00138 int n_arcs ;
00139 cpl_polynomial * poly2d ;
00140 int nx ;
00141 int i, j ;
00142
00143
00144 if (org == NULL) return NULL ;
00145 if (kappa < 0.0) return NULL ;
00146
00147
00148 n_calib = ARC_NBSAMPLES ;
00149 nx = cpl_image_get_size_x(org) ;
00150
00151 if (auto_ramp_sub) {
00152 local_im = irplib_distortion_remove_ramp(org) ;
00153 } else {
00154
00155 local_im = cpl_image_duplicate(org) ;
00156 }
00157 if (local_im == NULL) {
00158 cpl_msg_error(cpl_func, "Cannot clean the image") ;
00159 return NULL ;
00160 }
00161
00162
00163 cpl_msg_info(cpl_func, "Detect arcs") ;
00164 if ((*arcs = irplib_distortion_detect_arcs(local_im,
00165 &label_image,
00166 arc_sat, max_arc_width, kappa,
00167 xmin, ymin, xmax, ymax)) == NULL) {
00168 cpl_image_delete(local_im) ;
00169 cpl_msg_error(cpl_func, "Cannot detect the arcs") ;
00170 return NULL ;
00171 }
00172 n_arcs = cpl_apertures_get_size(*arcs) ;
00173 cpl_msg_info(cpl_func, "%d detected arcs", n_arcs) ;
00174
00175
00176 rightmost = leftmost = cpl_apertures_get_max_x(*arcs, 1) ;
00177 for (i=1 ; i<n_arcs ; i++) {
00178 if (cpl_apertures_get_max_x(*arcs, i+1) < leftmost)
00179 leftmost = cpl_apertures_get_max_x(*arcs, i+1) ;
00180 if (cpl_apertures_get_max_x(*arcs, i+1) > rightmost)
00181 rightmost = cpl_apertures_get_max_x(*arcs, i+1) ;
00182 }
00183 min_arc_range = (int)(nx / ARC_RANGE_FACT) ;
00184 if ((int)(rightmost-leftmost) < min_arc_range) {
00185 cpl_msg_error(cpl_func, "too narrow range (%g-%g)<%d",
00186 rightmost, leftmost, min_arc_range) ;
00187 cpl_apertures_delete(*arcs) ;
00188 cpl_image_delete(local_im) ;
00189 cpl_image_delete(label_image) ;
00190 return NULL ;
00191 }
00192
00193
00194 cpl_msg_info(cpl_func, "Create deformation grid") ;
00195 lines_pos = cpl_malloc(n_arcs * sizeof(double)) ;
00196 if ((arcs_pos = irplib_distortion_get_arc_positions(local_im,
00197 label_image, *arcs, n_calib, &lines_pos))==NULL){
00198 cpl_msg_error(cpl_func, "cannot get arcs positions") ;
00199 cpl_apertures_delete(*arcs) ;
00200 cpl_image_delete(local_im) ;
00201 cpl_free(lines_pos) ;
00202 cpl_image_delete(label_image) ;
00203 return NULL ;
00204 }
00205 cpl_image_delete(label_image) ;
00206 cpl_image_delete(local_im) ;
00207
00208
00209 cpl_msg_info(cpl_func, "Fit the 2d polynomial") ;
00210 grid = cpl_bivector_new(n_arcs * n_calib) ;
00211 pgridx = cpl_bivector_get_x_data(grid) ;
00212 pgridy = cpl_bivector_get_y_data(grid) ;
00213 values_to_fit = cpl_vector_new(n_arcs * n_calib) ;
00214 pvalues_to_fit = cpl_vector_get_data(values_to_fit) ;
00215 for (i=0 ; i<n_arcs ; i++) {
00216 parc_posx = cpl_bivector_get_x_data(arcs_pos[i]) ;
00217 parc_posy = cpl_bivector_get_y_data(arcs_pos[i]) ;
00218 for (j=0 ; j<n_calib ; j++) {
00219 pgridx[j+i*n_calib] = lines_pos[i] ;
00220 pgridy[j+i*n_calib] = parc_posy[j] ;
00221 pvalues_to_fit[j+i*n_calib] = parc_posx[j] ;
00222 }
00223 }
00224 for (i=0 ; i<n_arcs ; i++) cpl_bivector_delete(arcs_pos[i]) ;
00225 cpl_free(arcs_pos) ;
00226 cpl_free(lines_pos) ;
00227
00228
00229 if ((poly2d = cpl_polynomial_fit_2d_create(grid, values_to_fit,
00230 degree, NULL))==NULL) {
00231 cpl_msg_error(cpl_func, "cannot apply the 2d fit") ;
00232 cpl_bivector_delete(grid) ;
00233 cpl_vector_delete(values_to_fit) ;
00234 cpl_apertures_delete(*arcs) ;
00235 return NULL ;
00236 }
00237
00238
00239 cpl_bivector_delete(grid) ;
00240 cpl_vector_delete(values_to_fit) ;
00241 return poly2d ;
00242 }
00243
00246
00262
00263 static cpl_apertures * irplib_distortion_detect_arcs(
00264 cpl_image * im,
00265 cpl_image ** label_im,
00266 int arc_sat,
00267 int max_arc_width,
00268 double kappa,
00269 int xmin,
00270 int ymin,
00271 int xmax,
00272 int ymax)
00273 {
00274 cpl_image * filt_im ;
00275 cpl_matrix * filter ;
00276 cpl_image * collapsed ;
00277 cpl_mask * bin_im ;
00278 double threshold, fillval, median_val, sigma ;
00279 int min_arclen = 0 ;
00280 cpl_apertures * det ;
00281 int nobj ;
00282 int ngoodpix ;
00283 int ny ;
00284
00285 ny = cpl_image_get_size_y(im) ;
00286
00287
00288 *label_im = NULL ;
00289
00290
00291 median_val = cpl_image_get_median_dev(im, &sigma) ;
00292 fillval = median_val-sigma/2.0 ;
00293 if (irplib_distortion_fill_badzones(im, xmin, ymin, xmax, ymax,
00294 fillval) == -1) {
00295 cpl_msg_error(cpl_func, "cannot fill bad zones") ;
00296 return NULL ;
00297 }
00298
00299
00300 filter = cpl_matrix_new(3, 1) ;
00301 cpl_matrix_fill(filter, 1.0) ;
00302
00303 filt_im = cpl_image_duplicate(im) ;
00304 cpl_matrix_delete(filter) ;
00305
00306
00307 if (irplib_distortion_sub_hor_lowpass(filt_im, ARC_WINDOWSIZE) == -1) {
00308 cpl_image_delete(filt_im) ;
00309 return NULL ;
00310 }
00311
00312
00313 median_val = cpl_image_get_median_dev(filt_im, &sigma) ;
00314
00315
00316 if (median_val < TRESH_MEDIAN_MIN) median_val = TRESH_MEDIAN_MIN ;
00317 if (sigma > TRESH_SIGMA_MAX) sigma = TRESH_SIGMA_MAX ;
00318
00319
00320 threshold = median_val + sigma * kappa ;
00321
00322
00323 collapsed = cpl_image_collapse_median_create(filt_im, 0, 0, 0) ;
00324
00325
00326 if (irplib_distortion_threshold1d(filt_im, median_val, collapsed, 0.0)==-1) {
00327 cpl_msg_error(cpl_func, "cannot threshold the filtered image") ;
00328 cpl_image_delete(filt_im) ;
00329 cpl_image_delete(collapsed) ;
00330 return NULL ;
00331 }
00332 cpl_image_delete(collapsed) ;
00333
00334
00335 bin_im = cpl_mask_threshold_image_create(filt_im, threshold,
00336 CPL_PIXEL_MAXVAL);
00337 cpl_image_delete(filt_im) ;
00338 if (bin_im == NULL) {
00339 cpl_msg_error(cpl_func, "cannot binarise the image") ;
00340 return NULL ;
00341 }
00342
00343
00344 ngoodpix = cpl_mask_count(bin_im) ;
00345 if (ngoodpix < ARC_MINGOODPIX) {
00346 cpl_msg_error(cpl_func, "Too few (%d) white pixels", ngoodpix) ;
00347 cpl_mask_delete(bin_im) ;
00348 return NULL ;
00349 }
00350
00351
00352 filter = cpl_matrix_new(3, 3) ;
00353 cpl_matrix_fill(filter, 1.0) ;
00354 cpl_mask_erosion(bin_im, filter) ;
00355 cpl_mask_dilation(bin_im, filter) ;
00356 cpl_matrix_delete(filter) ;
00357
00358
00359 *label_im = cpl_image_labelise_mask_create(bin_im, &nobj) ;
00360 cpl_mask_delete(bin_im) ;
00361
00362
00363 if ((det = cpl_apertures_new_from_image(im, *label_im)) == NULL) {
00364 cpl_msg_error(cpl_func, "Cannot compute arcs stats") ;
00365 cpl_image_delete(*label_im) ;
00366 *label_im = NULL ;
00367 return NULL ;
00368 }
00369
00370
00371 min_arclen = (int)(ny / ARC_MINARCLENFACT) ;
00372
00373
00374 if (irplib_distortion_purge_arcs(im, &det, label_im, min_arclen,
00375 max_arc_width, arc_sat) == -1) {
00376 cpl_msg_error(cpl_func, "Cannot purge the arcs") ;
00377 cpl_image_delete(*label_im) ;
00378 *label_im = NULL ;
00379 cpl_apertures_delete(det) ;
00380 return NULL ;
00381 }
00382 if (cpl_apertures_get_size(det) < ARC_MINNBARCS) {
00383 cpl_msg_error(cpl_func, "Not enough valid arcs (%d < %d)",
00384 cpl_apertures_get_size(det), ARC_MINNBARCS) ;
00385 cpl_image_delete(*label_im) ;
00386 *label_im = NULL ;
00387 cpl_apertures_delete(det) ;
00388 return NULL ;
00389 }
00390
00391
00392 return det ;
00393 }
00394
00395 static int irplib_distortion_fill_badzones(
00396 cpl_image * im,
00397 int xmin,
00398 int ymin,
00399 int xmax,
00400 int ymax,
00401 double fillval)
00402 {
00403 float * pfi ;
00404 int nx, ny ;
00405 int i, j ;
00406
00407
00408 if (im == NULL) return -1 ;
00409 if (cpl_image_get_type(im) != CPL_TYPE_FLOAT) return -1 ;
00410
00411
00412 pfi = cpl_image_get_data_float(im) ;
00413 nx = cpl_image_get_size_x(im) ;
00414 ny = cpl_image_get_size_y(im) ;
00415
00416
00417 for (i=0 ; i<nx ; i++) {
00418 for (j=0 ; j<ny ; j++) {
00419 if ((i<xmin-1) || (i>xmax-1) || (j<ymin-1) || (j>ymax-1)) {
00420 pfi[i+j*nx] = (float)fillval ;
00421 }
00422 }
00423 }
00424 return 0 ;
00425 }
00426
00427 static int irplib_distortion_threshold1d(
00428 cpl_image * im,
00429 double threshold,
00430 cpl_image * im1d,
00431 double newval)
00432 {
00433 float * pim ;
00434 float * pim1d ;
00435 int nx, ny ;
00436 int i, j ;
00437
00438
00439 if (im == NULL) return -1 ;
00440 if (im1d == NULL) return -1 ;
00441 if (cpl_image_get_type(im) != CPL_TYPE_FLOAT) return -1 ;
00442 if (cpl_image_get_type(im1d) != CPL_TYPE_FLOAT) return -1 ;
00443
00444
00445 pim = cpl_image_get_data_float(im) ;
00446 pim1d = cpl_image_get_data_float(im1d) ;
00447 nx = cpl_image_get_size_x(im) ;
00448 ny = cpl_image_get_size_y(im) ;
00449
00450
00451 for (i=0 ; i<nx ; i++)
00452 if (pim1d[i] < threshold) {
00453 for (j=0 ; j<ny ; j++) pim[i+j*nx] = (float)newval ;
00454 }
00455
00456
00457 return 0 ;
00458 }
00459
00460 static int irplib_distortion_sub_hor_lowpass(
00461 cpl_image * im,
00462 int filt_size)
00463 {
00464 cpl_vector * linehi ;
00465 cpl_vector * linelo ;
00466 cpl_vector * avglinehi ;
00467 cpl_vector * avglinelo ;
00468 double * pavglinehi ;
00469 float * pim ;
00470 int lopos, hipos, nx, ny ;
00471 int i, j ;
00472
00473
00474 if (im == NULL) return -1 ;
00475 if (filt_size <= 0) return -1 ;
00476
00477
00478 nx = cpl_image_get_size_x(im) ;
00479 ny = cpl_image_get_size_y(im) ;
00480 lopos = (int)(ny/4) ;
00481 hipos = (int)(3*ny/4) ;
00482
00483
00484 if ((linehi = cpl_vector_new_from_image_row(im, hipos)) == NULL) {
00485 return -1 ;
00486 }
00487 if ((linelo = cpl_vector_new_from_image_row(im, lopos)) == NULL) {
00488 cpl_vector_delete(linehi) ;
00489 return -1 ;
00490 }
00491
00492
00493 if ((avglinehi = cpl_vector_filter_median_create(linehi,
00494 filt_size)) == NULL) {
00495 cpl_vector_delete(linehi) ;
00496 cpl_vector_delete(linelo) ;
00497 return -1 ;
00498 }
00499 cpl_vector_delete(linehi) ;
00500
00501 if ((avglinelo = cpl_vector_filter_median_create(linelo,
00502 filt_size)) == NULL) {
00503 cpl_vector_delete(linelo) ;
00504 cpl_vector_delete(avglinehi) ;
00505 return -1 ;
00506 }
00507 cpl_vector_delete(linelo) ;
00508
00509
00510 cpl_vector_add(avglinehi, avglinelo) ;
00511 cpl_vector_delete(avglinelo) ;
00512 cpl_vector_divide_scalar(avglinehi, 2.0) ;
00513
00514
00515 pavglinehi = cpl_vector_get_data(avglinehi) ;
00516 pim = cpl_image_get_data_float(im) ;
00517 for (i=0 ; i<nx ; i++) {
00518 for (j=0 ; j<ny ; j++) {
00519 pim[i+j*nx] -= pavglinehi[i] ;
00520 }
00521 }
00522 cpl_vector_delete(avglinehi) ;
00523
00524 return 0 ;
00525 }
00526
00527 static int irplib_distortion_purge_arcs(
00528 cpl_image * im,
00529 cpl_apertures ** arcs,
00530 cpl_image ** lab_im,
00531 int min_arclen,
00532 int max_arcwidth,
00533 double arc_sat)
00534 {
00535 int nb_arcs ;
00536 int * selection ;
00537 int arclen, arcwidth, edge ;
00538 double mean ;
00539 int * plabim ;
00540 cpl_mask * bin_im ;
00541 int nx, ny ;
00542 int i, j ;
00543
00544
00545 if (arcs == NULL) return -1 ;
00546 if (*arcs == NULL) return -1 ;
00547 if (*lab_im == NULL) return -1 ;
00548
00549
00550 nb_arcs = cpl_apertures_get_size(*arcs) ;
00551 nx = cpl_image_get_size_x(*lab_im) ;
00552 ny = cpl_image_get_size_y(*lab_im) ;
00553
00554
00555 selection = cpl_malloc(nb_arcs * sizeof(int)) ;
00556
00557
00558 for (i=0 ; i<nb_arcs ; i++) {
00559 arclen = cpl_apertures_get_top(*arcs, i+1) -
00560 cpl_apertures_get_bottom(*arcs, i+1) + 1 ;
00561 arcwidth = cpl_apertures_get_right(*arcs, i+1) -
00562 cpl_apertures_get_left(*arcs, i+1) + 1 ;
00563 edge = cpl_apertures_get_left_y(*arcs, i+1) ;
00564 mean = cpl_apertures_get_mean(*arcs, i+1) ;
00565
00566
00567 if ((arclen>min_arclen) && (arcwidth<max_arcwidth)
00568 && (edge>0) && (mean < arc_sat)) {
00569 selection[i] = 1 ;
00570 } else {
00571 selection[i] = 0 ;
00572 }
00573 }
00574
00575
00576 for (i=0 ; i<nb_arcs ; i++) {
00577 if (selection[i] == 0) {
00578 plabim = cpl_image_get_data_int(*lab_im) ;
00579 for (j=0 ; j<nx*ny ; j++) {
00580 if (plabim[j] == i+1) plabim[j] = 0 ;
00581 }
00582 }
00583 }
00584 cpl_free(selection) ;
00585
00586
00587 bin_im = cpl_mask_threshold_image_create(*lab_im, 0.5, CPL_PIXEL_MAXVAL) ;
00588 cpl_image_delete(*lab_im) ;
00589 *lab_im = cpl_image_labelise_mask_create(bin_im, NULL) ;
00590 cpl_mask_delete(bin_im) ;
00591
00592
00593 cpl_apertures_delete(*arcs) ;
00594 *arcs = cpl_apertures_new_from_image(im, *lab_im) ;
00595
00596
00597 if (cpl_apertures_get_size(*arcs) <= 0) {
00598 cpl_msg_error(cpl_func, "No valid arc found") ;
00599 return -1 ;
00600 }
00601
00602 return 0 ;
00603 }
00604
00605 static cpl_bivector ** irplib_distortion_get_arc_positions(
00606 cpl_image * in,
00607 cpl_image * label_im,
00608 cpl_apertures * det,
00609 int nb_samples,
00610 double ** lines_pos)
00611 {
00612 int n_arcs ;
00613 cpl_image * filt_img ;
00614 cpl_matrix * kernel ;
00615 cpl_bivector ** pos ;
00616 double * biv_x ;
00617 double * biv_y ;
00618 double x_finepos ;
00619 int * plabel_im ;
00620 int * arcs_samples_y ;
00621 int * computed ;
00622 double arclen ;
00623 int use_this_arc ;
00624 int obj ;
00625 int nx, ny ;
00626 int i, j, k ;
00627
00628
00629
00630
00631 n_arcs = cpl_apertures_get_size(det) ;
00632 nx = cpl_image_get_size_x(label_im) ;
00633 ny = cpl_image_get_size_y(label_im) ;
00634
00635
00636 pos = cpl_calloc(n_arcs, sizeof(cpl_bivector*)) ;
00637 for (i=0 ; i<n_arcs ; i++) pos[i] = cpl_bivector_new(nb_samples) ;
00638
00639
00640 kernel = cpl_matrix_new(3, 3) ;
00641 cpl_matrix_fill(kernel, 1.0) ;
00642 filt_img = cpl_image_filter_median(in, kernel) ;
00643 cpl_matrix_delete(kernel) ;
00644
00645
00646 arcs_samples_y = cpl_malloc(n_arcs * nb_samples * sizeof(int)) ;
00647 computed = cpl_calloc(n_arcs*nb_samples, sizeof(int)) ;
00648
00649
00650 for (j=0 ; j<n_arcs ; j++) {
00651 arclen = cpl_apertures_get_top(det,j+1) -
00652 cpl_apertures_get_bottom(det,j+1) + 1 ;
00653 for (i=0 ; i<nb_samples ; i++) {
00654 arcs_samples_y[i+j*nb_samples] =
00655 (int)(cpl_apertures_get_bottom(det, j+1) +
00656 (arclen * (i + 0.5)) / (double)nb_samples) ;
00657 }
00658 }
00659
00660
00661 plabel_im = cpl_image_get_data_int(label_im) ;
00662 for (i=0 ; i<nx ; i++) {
00663 for (j=0 ; j<ny ; j++) {
00664
00665
00666 obj = plabel_im[i + j * nx] ;
00667
00668 if (obj==0) continue ;
00669
00670 else obj-- ;
00671
00672 use_this_arc = 0 ;
00673 for (k=0 ; k<nb_samples ; k++) {
00674 if (arcs_samples_y[k+obj*nb_samples] == j) {
00675 use_this_arc = 1 ;
00676 break ;
00677 }
00678 }
00679 if ((use_this_arc) && (computed[k+obj*nb_samples] == 0)) {
00680
00681 if ((x_finepos = irplib_distortion_fine_pos(filt_img,
00682 label_im, i, j)) < 0.0) {
00683 cpl_msg_error(cpl_func, "cannot find fine arc position") ;
00684 cpl_image_delete(filt_img) ;
00685 cpl_free(arcs_samples_y);
00686 cpl_free(computed) ;
00687 for (i=0 ; i<n_arcs ; i++) cpl_bivector_delete(pos[i]);
00688 cpl_free(pos) ;
00689 return NULL ;
00690 } else {
00691 biv_x = cpl_bivector_get_x_data(pos[obj]) ;
00692 biv_y = cpl_bivector_get_y_data(pos[obj]) ;
00693 biv_x[k] = x_finepos ;
00694 biv_y[k] = j ;
00695 (*lines_pos)[obj] = cpl_apertures_get_centroid_x(det,obj+1);
00696 computed[k+obj*nb_samples] = 1 ;
00697 }
00698 }
00699 }
00700 }
00701
00702
00703 cpl_image_delete(filt_img) ;
00704 cpl_free(arcs_samples_y) ;
00705 cpl_free(computed) ;
00706 return pos ;
00707 }
00708
00709 static double irplib_distortion_fine_pos(
00710 cpl_image * im,
00711 cpl_image * label_im,
00712 int x,
00713 int y)
00714 {
00715 float * pim ;
00716 int * plabel_im ;
00717 int objnum ;
00718 int curr_obj ;
00719 int start_pos ;
00720 double grav_c ;
00721 double sum ;
00722 double max ;
00723 double val ;
00724 int maxpos ;
00725 int im_extrem ;
00726 double arc_pos ;
00727 int nx ;
00728
00729
00730 nx = cpl_image_get_size_x(im) ;
00731 grav_c = 0.0 ;
00732 sum = 0.0 ;
00733 start_pos = x ;
00734 maxpos = start_pos ;
00735 pim = cpl_image_get_data_float(im) ;
00736 max = (double)pim[start_pos + y * nx] ;
00737 plabel_im = cpl_image_get_data_int(label_im) ;
00738 objnum = plabel_im[start_pos + y * nx] ;
00739 im_extrem = nx ;
00740
00741
00742 do {
00743 val = (double)pim[start_pos + y * nx] ;
00744 if (start_pos == 0) grav_c = 0.0 ;
00745 else grav_c += start_pos * val ;
00746 sum += val ;
00747 if (val > max) {
00748 max = val ;
00749 maxpos = start_pos ;
00750 }
00751
00752
00753 start_pos++ ;
00754
00755 curr_obj = plabel_im[start_pos + y * nx] ;
00756 } while (curr_obj == objnum) ;
00757
00758
00759 if ((fabs(grav_c) < 1.0e-40) || (fabs(sum) < 1.0e-40)) {
00760 arc_pos = maxpos ;
00761 } else {
00762 arc_pos = grav_c / sum ;
00763 if (fabs(arc_pos) >= start_pos) arc_pos = maxpos ;
00764 }
00765
00766
00767 return arc_pos ;
00768 }
00769
00770
00776
00777 #define IS_NB_TESTPOINTS 8
00778 #define IS_MIN_SLOPE 0.01
00779 #define IS_MAX_SLOPE_DIF 0.075
00780 #define IS_MAX_FIT_EDGE_DIF 0.05
00781 #define IS_MIN_RAMP 10.0
00782 #define IS_MAX_MNERR 13.0
00783 #define IS_MAX_MNERR_DIF 8.0
00784 #define IS_MAX_INTER_DIF 20.0
00785 #define IS_SKIPZONE 2.5
00786 #define SQR(x) ((x)*(x))
00787 static cpl_image * irplib_distortion_remove_ramp(const cpl_image * in)
00788 {
00789 int ramp_present ;
00790 int nx, ny ;
00791 int y, yhi, ylo;
00792 cpl_vector * tmp_vector ;
00793 cpl_bivector * testpointlo ;
00794 double * testpointlo_x ;
00795 double * testpointlo_y ;
00796 cpl_bivector * testpointhi ;
00797 double * testpointhi_x ;
00798 double * testpointhi_y ;
00799 int spacing;
00800 double rampdif, fitslope;
00801 double * pol_coefhi,
00802 * pol_coeflo ;
00803 cpl_vector * median ;
00804 double * median_data ;
00805 double medianerrlo, medianerrhi;
00806 double slope ;
00807 cpl_image * out ;
00808 float * pout ;
00809 float val ;
00810 int i, j ;
00811
00812
00813 nx = cpl_image_get_size_x(in) ;
00814 ny = cpl_image_get_size_y(in) ;
00815
00816
00817 if (in==NULL) return NULL ;
00818
00819 if (ny<IS_SKIPZONE*IS_NB_TESTPOINTS){
00820 cpl_msg_error(cpl_func, "image has %d lines, min=%d ",
00821 ny, (int)(IS_SKIPZONE*IS_NB_TESTPOINTS*2));
00822 return NULL ;
00823 }
00824
00825 slope=0.0 ;
00826 spacing= ny / (IS_SKIPZONE*IS_NB_TESTPOINTS) ;
00827 yhi = (int)(ny/2) ;
00828 ylo = yhi - 1 ;
00829
00830 testpointhi = cpl_bivector_new(IS_NB_TESTPOINTS) ;
00831 testpointhi_x = cpl_bivector_get_x_data(testpointhi) ;
00832 testpointhi_y = cpl_bivector_get_y_data(testpointhi) ;
00833 testpointlo = cpl_bivector_new(IS_NB_TESTPOINTS) ;
00834 testpointlo_x = cpl_bivector_get_x_data(testpointlo) ;
00835 testpointlo_y = cpl_bivector_get_y_data(testpointlo) ;
00836 for (i=0 ; i<IS_NB_TESTPOINTS ; i++) {
00837 y = yhi + i * spacing;
00838 tmp_vector = cpl_vector_new_from_image_row(in, y+1) ;
00839 testpointhi_x[i] = y - ny / 2;
00840 testpointhi_y[i] = cpl_vector_get_median(tmp_vector) ;
00841 cpl_vector_delete(tmp_vector) ;
00842 y = ylo - i * spacing;
00843 tmp_vector = cpl_vector_new_from_image_row(in, y+1) ;
00844 testpointlo_x[IS_NB_TESTPOINTS-i-1] = y ;
00845 testpointlo_y[IS_NB_TESTPOINTS-i-1]=cpl_vector_get_median(tmp_vector) ;
00846 cpl_vector_delete(tmp_vector) ;
00847 }
00848
00849
00850 pol_coefhi = irplib_flat_fit_slope_robust(testpointhi_x,
00851 testpointhi_y, IS_NB_TESTPOINTS) ;
00852 pol_coeflo = irplib_flat_fit_slope_robust(testpointlo_x,
00853 testpointlo_y, IS_NB_TESTPOINTS) ;
00854
00855
00856 median = cpl_vector_new(IS_NB_TESTPOINTS) ;
00857 median_data = cpl_vector_get_data(median) ;
00858 for (i=0 ; i<IS_NB_TESTPOINTS ; i++) {
00859 median_data[i]=SQR(testpointhi_y[i]
00860 - pol_coefhi[0] - pol_coefhi[1] * testpointhi_x[i]);
00861 }
00862 medianerrhi = cpl_vector_get_median(median) ;
00863 for (i=0; i<IS_NB_TESTPOINTS; i++) {
00864 median_data[i]=SQR(testpointlo_y[i]
00865 - pol_coeflo[0] - pol_coeflo[1] * testpointlo_x[i]);
00866 }
00867 medianerrlo = cpl_vector_get_median(median) ;
00868 cpl_vector_delete(median) ;
00869 rampdif = testpointlo_y[IS_NB_TESTPOINTS-1] - testpointhi_y[0];
00870 slope = rampdif / (ny/2.0) ;
00871 fitslope = (pol_coefhi[1] + pol_coeflo[1]) / 2.0 ;
00872
00873 cpl_bivector_delete(testpointlo);
00874 cpl_bivector_delete(testpointhi);
00875
00876
00877 if (fabs(rampdif)<IS_MIN_RAMP ||
00878 fabs(pol_coefhi[1]) < IS_MIN_SLOPE ||
00879 fabs(pol_coeflo[1]) < IS_MIN_SLOPE ||
00880 pol_coefhi[1]/pol_coeflo[1]<0.5 ||
00881 pol_coefhi[1]/pol_coeflo[1]>2.0 ||
00882 fabs(pol_coefhi[1]-pol_coeflo[1])>IS_MAX_SLOPE_DIF ||
00883 fabs(pol_coefhi[0]-pol_coeflo[0]) > IS_MAX_INTER_DIF ||
00884 medianerrlo> IS_MAX_MNERR ||
00885 medianerrhi> IS_MAX_MNERR ||
00886 fabs(medianerrlo-medianerrhi) >IS_MAX_MNERR_DIF ||
00887 fabs(slope-fitslope) > IS_MAX_FIT_EDGE_DIF ||
00888 slope/fitslope<0.5 ||
00889 slope/fitslope>2.0) ramp_present = 0 ;
00890 else ramp_present = 1 ;
00891
00892 cpl_free(pol_coeflo) ;
00893 cpl_free(pol_coefhi) ;
00894
00895
00896 out = cpl_image_duplicate(in) ;
00897 pout = cpl_image_get_data_float(out) ;
00898 if (ramp_present == 1) {
00899 for (j=0 ; j<ny/2 ; j++) {
00900 val = slope * (j-ny/2) ;
00901 for (i=0 ; i<nx ; i++)
00902 pout[i+j*nx] -= val ;
00903 }
00904 for (j=ny/2 ; j<ny ; j++) {
00905 val = slope * (j-ny) ;
00906 for (i=0 ; i<nx ; i++)
00907 pout[i+j*nx] -= val ;
00908 }
00909
00910 }
00911
00912 return out ;
00913 }
00914