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