Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
ashift_lsd.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2016-2020 darktable developers.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19
20/* For line detection we are using the LSD code as published below.
21 * Changes versus the original code:
22 * do not include "lsd.h" (not needed)
23 * make all interface functions static * comment out unused interface functions
24 * catch (unlikely) division by zero near line 2035
25 * rename rad1 and rad2 to radius1 and radius2 in reduce_region_radius()
26 * to avoid naming conflict in windows build
27 *
28 */
29
30/* TODO: LSD employs intensive sanity checks of input data and allocation
31 * results. In case of errors it will terminate the program. On the one side
32 * this is not optimal for a module within darktable - it should better
33 * report errors upstream where they should be handled properly. On the other
34 * hand the kind of error which could be triggered in LSD would make it very unlikely
35 * that the darktable process could survive anyhow.
36 */
37
38// clang-format off
39
40/*==================================================================================
41 * begin LSD code version 1.6. downloaded on January 30, 2016
42 *==================================================================================*/
43
44/*----------------------------------------------------------------------------
45
46 LSD - Line Segment Detector on digital images
47
48 This code is part of the following publication and was subject
49 to peer review:
50
51 "LSD: a Line Segment Detector" by Rafael Grompone von Gioi,
52 Jeremie Jakubowicz, Jean-Michel Morel, and Gregory Randall,
53 Image Processing On Line, 2012. DOI:10.5201/ipol.2012.gjmr-lsd
54 http://dx.doi.org/10.5201/ipol.2012.gjmr-lsd
55
56 Copyright (c) 2007-2011 rafael grompone von gioi <grompone@gmail.com>
57
58 This program is free software: you can redistribute it and/or modify
59 it under the terms of the GNU Affero General Public License as
60 published by the Free Software Foundation, either version 3 of the
61 License, or (at your option) any later version.
62
63 This program is distributed in the hope that it will be useful,
64 but WITHOUT ANY WARRANTY; without even the implied warranty of
65 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66 GNU Affero General Public License for more details.
67
68 You should have received a copy of the GNU Affero General Public License
69 along with this program. If not, see <http://www.gnu.org/licenses/>.
70
71 ----------------------------------------------------------------------------*/
72
73/*----------------------------------------------------------------------------*/
78/*----------------------------------------------------------------------------*/
79
80/*----------------------------------------------------------------------------*/
138/*----------------------------------------------------------------------------*/
139
140#include <stdio.h>
141#include <stdlib.h>
142#include <limits.h>
143#include <float.h>
144#include "common/math.h"
145
146#ifndef FALSE
147#define FALSE 0
148#endif /* !FALSE */
149
150#ifndef TRUE
151#define TRUE 1
152#endif /* !TRUE */
153
155#define NOTDEF -1024.0
156
158#define M_3_2_PI 4.71238898038
159
161#define M_2__PI 6.28318530718
162
164#define NOTUSED 0
165
167#define USED 1
168
169/*----------------------------------------------------------------------------*/
173{
174 int x,y;
175 struct coorlist * next;
176};
177
178/*----------------------------------------------------------------------------*/
181struct point {int x,y;};
182
183
184/*----------------------------------------------------------------------------*/
185/*------------------------- Miscellaneous functions --------------------------*/
186/*----------------------------------------------------------------------------*/
187
188/*----------------------------------------------------------------------------*/
191static void error(char * msg)
192{
193 fprintf(stderr,"LSD Error: %s\n",msg);
194 exit(EXIT_FAILURE);
195}
196
197/*----------------------------------------------------------------------------*/
200#define RELATIVE_ERROR_FACTOR 100.0
201
202/*----------------------------------------------------------------------------*/
213static int double_equal(double a, double b)
214{
215 double abs_diff,aa,bb,abs_max;
216
217 /* trivial case */
218 if( a == b ) return TRUE;
219
220 abs_diff = fabs(a-b);
221 aa = fabs(a);
222 bb = fabs(b);
223 abs_max = aa > bb ? aa : bb;
224
225 /* DBL_MIN is the smallest normalized number, thus, the smallest
226 number whose relative error is bounded by DBL_EPSILON. For
227 smaller numbers, the same quantization steps as for DBL_MIN
228 are used. Then, for smaller numbers, a meaningful "relative"
229 error should be computed by dividing the difference by DBL_MIN. */
230 if( abs_max < DBL_MIN ) abs_max = DBL_MIN;
231
232 /* equal if relative error <= factor x eps */
233 return (abs_diff / abs_max) <= (RELATIVE_ERROR_FACTOR * DBL_EPSILON);
234}
235
236/*----------------------------------------------------------------------------*/
239static double dist(double x1, double y1, double x2, double y2)
240{
241 return sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );
242}
243
244
245/*----------------------------------------------------------------------------*/
246/*----------------------- 'list of n-tuple' data type ------------------------*/
247/*----------------------------------------------------------------------------*/
248
249/*----------------------------------------------------------------------------*/
270typedef struct ntuple_list_s
271{
272 unsigned int size;
273 unsigned int max_size;
274 unsigned int dim;
275 double * values;
277
278/*----------------------------------------------------------------------------*/
282{
283 if( in == NULL || in->values == NULL )
284 error("free_ntuple_list: invalid n-tuple input.");
285 free( (void *) in->values );
286 free( (void *) in );
287}
288
289/*----------------------------------------------------------------------------*/
293static ntuple_list new_ntuple_list(unsigned int dim)
294{
295 ntuple_list n_tuple;
296
297 /* check parameters */
298 if( dim == 0 ) error("new_ntuple_list: 'dim' must be positive.");
299
300 /* get memory for list structure */
301 n_tuple = (ntuple_list) malloc( sizeof(struct ntuple_list_s) );
302 if( n_tuple == NULL ) error("not enough memory.");
303
304 /* initialize list */
305 n_tuple->size = 0;
306 n_tuple->max_size = 1;
307 n_tuple->dim = dim;
308
309 /* get memory for tuples */
310 n_tuple->values = (double *) malloc(sizeof(double) * dim * n_tuple->max_size);
311 if( n_tuple->values == NULL ) error("not enough memory.");
312
313 return n_tuple;
314}
315
316/*----------------------------------------------------------------------------*/
320{
321 /* check parameters */
322 if( n_tuple == NULL || n_tuple->values == NULL || n_tuple->max_size == 0 )
323 error("enlarge_ntuple_list: invalid n-tuple.");
324
325 /* duplicate number of tuples */
326 n_tuple->max_size *= 2;
327
328 /* realloc memory */
329 n_tuple->values = (double *) realloc( (void *) n_tuple->values,
330 sizeof(double) * n_tuple->dim * n_tuple->max_size );
331 if( n_tuple->values == NULL ) error("not enough memory.");
332}
333
334/*----------------------------------------------------------------------------*/
337static void add_7tuple( ntuple_list out, double v1, double v2, double v3,
338 double v4, double v5, double v6, double v7 )
339{
340 /* check parameters */
341 if( out == NULL ) error("add_7tuple: invalid n-tuple input.");
342 if( out->dim != 7 ) error("add_7tuple: the n-tuple must be a 7-tuple.");
343
344 /* if needed, alloc more tuples to 'out' */
345 if( out->size == out->max_size ) enlarge_ntuple_list(out);
346 if( out->values == NULL ) error("add_7tuple: invalid n-tuple input.");
347
348 /* add new 7-tuple */
349 out->values[ out->size * out->dim + 0 ] = v1;
350 out->values[ out->size * out->dim + 1 ] = v2;
351 out->values[ out->size * out->dim + 2 ] = v3;
352 out->values[ out->size * out->dim + 3 ] = v4;
353 out->values[ out->size * out->dim + 4 ] = v5;
354 out->values[ out->size * out->dim + 5 ] = v6;
355 out->values[ out->size * out->dim + 6 ] = v7;
356
357 /* update number of tuples counter */
358 out->size++;
359}
360
361
362/*----------------------------------------------------------------------------*/
363/*----------------------------- Image Data Types -----------------------------*/
364/*----------------------------------------------------------------------------*/
365
366/*----------------------------------------------------------------------------*/
375typedef struct image_char_s
376{
377 unsigned char * data;
378 unsigned int xsize,ysize;
380
381/*----------------------------------------------------------------------------*/
385{
386 if( i == NULL || i->data == NULL )
387 error("free_image_char: invalid input image.");
388 free( (void *) i->data );
389 free( (void *) i );
390}
391
392/*----------------------------------------------------------------------------*/
395static image_char new_image_char(unsigned int xsize, unsigned int ysize)
396{
397 image_char image;
398
399 /* check parameters */
400 if( xsize == 0 || ysize == 0 ) error("new_image_char: invalid image size.");
401
402 /* get memory */
403 image = (image_char) malloc( sizeof(struct image_char_s) );
404 if( image == NULL ) error("not enough memory.");
405 image->data = (unsigned char *) calloc( (size_t) (xsize*ysize),
406 sizeof(unsigned char) );
407 if( image->data == NULL ) error("not enough memory.");
408
409 /* set image size */
410 image->xsize = xsize;
411 image->ysize = ysize;
412
413 return image;
414}
415
416/*----------------------------------------------------------------------------*/
420static image_char new_image_char_ini( unsigned int xsize, unsigned int ysize,
421 unsigned char fill_value )
422{
423 image_char image = new_image_char(xsize,ysize); /* create image */
424 unsigned int N = xsize*ysize;
425 unsigned int i;
426
427 /* check parameters */
428 if( image == NULL || image->data == NULL )
429 error("new_image_char_ini: invalid image.");
430
431 /* initialize */
432 for(i=0; i<N; i++) image->data[i] = fill_value;
433
434 return image;
435}
436
437/*----------------------------------------------------------------------------*/
446typedef struct image_int_s
447{
448 int * data;
449 unsigned int xsize,ysize;
451
452/*----------------------------------------------------------------------------*/
455static image_int new_image_int(unsigned int xsize, unsigned int ysize)
456{
457 image_int image;
458
459 /* check parameters */
460 if( xsize == 0 || ysize == 0 ) error("new_image_int: invalid image size.");
461
462 /* get memory */
463 image = (image_int) malloc( sizeof(struct image_int_s) );
464 if( image == NULL ) error("not enough memory.");
465 image->data = (int *) calloc( (size_t) (xsize*ysize), sizeof(int) );
466 if( image->data == NULL ) error("not enough memory.");
467
468 /* set image size */
469 image->xsize = xsize;
470 image->ysize = ysize;
471
472 return image;
473}
474
475/*----------------------------------------------------------------------------*/
479static image_int new_image_int_ini( unsigned int xsize, unsigned int ysize,
480 int fill_value )
481{
482 image_int image = new_image_int(xsize,ysize); /* create image */
483 unsigned int N = xsize*ysize;
484 unsigned int i;
485
486 /* initialize */
487 for(i=0; i<N; i++) image->data[i] = fill_value;
488
489 return image;
490}
491
492/*----------------------------------------------------------------------------*/
501typedef struct image_double_s
502{
503 double * data;
504 unsigned int xsize,ysize;
506
507/*----------------------------------------------------------------------------*/
511{
512 if( i == NULL || i->data == NULL )
513 error("free_image_double: invalid input image.");
514 free( (void *) i->data );
515 free( (void *) i );
516}
517
518/*----------------------------------------------------------------------------*/
521static image_double new_image_double(unsigned int xsize, unsigned int ysize)
522{
523 image_double image;
524
525 /* check parameters */
526 if( xsize == 0 || ysize == 0 ) error("new_image_double: invalid image size.");
527
528 /* get memory */
529 image = (image_double) malloc( sizeof(struct image_double_s) );
530 if( image == NULL ) error("not enough memory.");
531 image->data = (double *) calloc( (size_t) (xsize*ysize), sizeof(double) );
532 if( image->data == NULL ) error("not enough memory.");
533
534 /* set image size */
535 image->xsize = xsize;
536 image->ysize = ysize;
537
538 return image;
539}
540
541/*----------------------------------------------------------------------------*/
545static image_double new_image_double_ptr( unsigned int xsize,
546 unsigned int ysize, double * data )
547{
548 image_double image;
549
550 /* check parameters */
551 if( xsize == 0 || ysize == 0 )
552 error("new_image_double_ptr: invalid image size.");
553 if( data == NULL ) error("new_image_double_ptr: NULL data pointer.");
554
555 /* get memory */
556 image = (image_double) malloc( sizeof(struct image_double_s) );
557 if( image == NULL ) error("not enough memory.");
558
559 /* set image */
560 image->xsize = xsize;
561 image->ysize = ysize;
562 image->data = data;
563
564 return image;
565}
566
567
568/*----------------------------------------------------------------------------*/
569/*----------------------------- Gaussian filter ------------------------------*/
570/*----------------------------------------------------------------------------*/
571
572/*----------------------------------------------------------------------------*/
580static void gaussian_kernel(ntuple_list kernel, double sigma, double mean)
581{
582 double sum = 0.0;
583 double val;
584 unsigned int i;
585
586 /* check parameters */
587 if( kernel == NULL || kernel->values == NULL )
588 error("gaussian_kernel: invalid n-tuple 'kernel'.");
589 if( sigma <= 0.0 ) error("gaussian_kernel: 'sigma' must be positive.");
590
591 /* compute Gaussian kernel */
592 if( kernel->max_size < 1 ) enlarge_ntuple_list(kernel);
593 kernel->size = 1;
594 for(i=0;i<kernel->dim;i++)
595 {
596 val = ( (double) i - mean ) / sigma;
597 kernel->values[i] = exp( -0.5 * val * val );
598 sum += kernel->values[i];
599 }
600
601 /* normalization */
602 if( sum >= 0.0 ) for(i=0;i<kernel->dim;i++) kernel->values[i] /= sum;
603}
604
605/*----------------------------------------------------------------------------*/
644 double sigma_scale )
645{
646 image_double aux,out;
648 unsigned int N,M,h,n,x,y,i;
649 int xc,yc,j,double_x_size,double_y_size;
650 double sigma,xx,yy,sum,prec;
651
652 /* check parameters */
653 if( in == NULL || in->data == NULL || in->xsize == 0 || in->ysize == 0 )
654 error("gaussian_sampler: invalid image.");
655 if( scale <= 0.0 ) error("gaussian_sampler: 'scale' must be positive.");
656 if( sigma_scale <= 0.0 )
657 error("gaussian_sampler: 'sigma_scale' must be positive.");
658
659 /* compute new image size and get memory for images */
660 if( in->xsize * scale > (double) UINT_MAX ||
661 in->ysize * scale > (double) UINT_MAX )
662 error("gaussian_sampler: the output image size exceeds the handled size.");
663 N = (unsigned int) ceil( in->xsize * scale );
664 M = (unsigned int) ceil( in->ysize * scale );
665 aux = new_image_double(N,in->ysize);
666 out = new_image_double(N,M);
667
668 /* sigma, kernel size and memory for the kernel */
669 sigma = scale < 1.0 ? sigma_scale / scale : sigma_scale;
670 /*
671 The size of the kernel is selected to guarantee that the
672 the first discarded term is at least 10^prec times smaller
673 than the central value. For that, h should be larger than x, with
674 e^(-x^2/2sigma^2) = 1/10^prec.
675 Then,
676 x = sigma * sqrt( 2 * prec * ln(10) ).
677 */
678 prec = 3.0;
679 h = (unsigned int) ceil( sigma * sqrt( 2.0 * prec * log(10.0) ) );
680 n = 1+2*h; /* kernel size */
682
683 /* auxiliary double image size variables */
684 double_x_size = (int) (2 * in->xsize);
685 double_y_size = (int) (2 * in->ysize);
686
687 /* First subsampling: x axis */
688 for(x=0;x<aux->xsize;x++)
689 {
690 /*
691 x is the coordinate in the new image.
692 xx is the corresponding x-value in the original size image.
693 xc is the integer value, the pixel coordinate of xx.
694 */
695 xx = (double) x / scale;
696 /* coordinate (0.0,0.0) is in the center of pixel (0,0),
697 so the pixel with xc=0 get the values of xx from -0.5 to 0.5 */
698 xc = (int) floor( xx + 0.5 );
699 gaussian_kernel( kernel, sigma, (double) h + xx - (double) xc );
700 /* the kernel must be computed for each x because the fine
701 offset xx-xc is different in each case */
702
703 for(y=0;y<aux->ysize;y++)
704 {
705 sum = 0.0;
706 for(i=0;i<kernel->dim;i++)
707 {
708 j = xc - h + i;
709
710 /* symmetry boundary condition */
711 while( j < 0 ) j += double_x_size;
712 while( j >= double_x_size ) j -= double_x_size;
713 if( j >= (int) in->xsize ) j = double_x_size-1-j;
714
715 sum += in->data[ j + y * in->xsize ] * kernel->values[i];
716 }
717 aux->data[ x + y * aux->xsize ] = sum;
718 }
719 }
720
721 /* Second subsampling: y axis */
722 for(y=0;y<out->ysize;y++)
723 {
724 /*
725 y is the coordinate in the new image.
726 yy is the corresponding x-value in the original size image.
727 yc is the integer value, the pixel coordinate of xx.
728 */
729 yy = (double) y / scale;
730 /* coordinate (0.0,0.0) is in the center of pixel (0,0),
731 so the pixel with yc=0 get the values of yy from -0.5 to 0.5 */
732 yc = (int) floor( yy + 0.5 );
733 gaussian_kernel( kernel, sigma, (double) h + yy - (double) yc );
734 /* the kernel must be computed for each y because the fine
735 offset yy-yc is different in each case */
736
737 for(x=0;x<out->xsize;x++)
738 {
739 sum = 0.0;
740 for(i=0;i<kernel->dim;i++)
741 {
742 j = yc - h + i;
743
744 /* symmetry boundary condition */
745 while( j < 0 ) j += double_y_size;
746 while( j >= double_y_size ) j -= double_y_size;
747 if( j >= (int) in->ysize ) j = double_y_size-1-j;
748
749 sum += aux->data[ x + j * aux->xsize ] * kernel->values[i];
750 }
751 out->data[ x + y * out->xsize ] = sum;
752 }
753 }
754
755 /* free memory */
758
759 return out;
760}
761
762
763/*----------------------------------------------------------------------------*/
764/*--------------------------------- Gradient ---------------------------------*/
765/*----------------------------------------------------------------------------*/
766
767/*----------------------------------------------------------------------------*/
784static image_double ll_angle( image_double in, double threshold,
785 struct coorlist ** list_p, void ** mem_p,
786 image_double * modgrad, unsigned int n_bins )
787{
788 image_double g;
789 unsigned int n,p,x,y,adr,i;
790 double com1,com2,gx,gy,norm,norm2;
791 /* the rest of the variables are used for pseudo-ordering
792 the gradient magnitude values */
793 int list_count = 0;
794 struct coorlist * list;
795 struct coorlist ** range_l_s; /* array of pointers to start of bin list */
796 struct coorlist ** range_l_e; /* array of pointers to end of bin list */
797 struct coorlist * start;
798 struct coorlist * end;
799 double max_grad = 0.0;
800
801 /* check parameters */
802 if( in == NULL || in->data == NULL || in->xsize == 0 || in->ysize == 0 )
803 error("ll_angle: invalid image.");
804 if( threshold < 0.0 ) error("ll_angle: 'threshold' must be positive.");
805 if( list_p == NULL ) error("ll_angle: NULL pointer 'list_p'.");
806 if( mem_p == NULL ) error("ll_angle: NULL pointer 'mem_p'.");
807 if( modgrad == NULL ) error("ll_angle: NULL pointer 'modgrad'.");
808 if( n_bins == 0 ) error("ll_angle: 'n_bins' must be positive.");
809
810 /* image size shortcuts */
811 n = in->ysize;
812 p = in->xsize;
813
814 /* allocate output image */
815 g = new_image_double(in->xsize,in->ysize);
816
817 /* get memory for the image of gradient modulus */
818 *modgrad = new_image_double(in->xsize,in->ysize);
819
820 /* get memory for "ordered" list of pixels */
821 list = (struct coorlist *) calloc( (size_t) (n*p), sizeof(struct coorlist) );
822 *mem_p = (void *) list;
823 range_l_s = (struct coorlist **) calloc( (size_t) n_bins,
824 sizeof(struct coorlist *) );
825 range_l_e = (struct coorlist **) calloc( (size_t) n_bins,
826 sizeof(struct coorlist *) );
827 if( list == NULL || range_l_s == NULL || range_l_e == NULL )
828 error("not enough memory.");
829 for(i=0;i<n_bins;i++) range_l_s[i] = range_l_e[i] = NULL;
830
831 /* 'undefined' on the down and right boundaries */
832 for(x=0;x<p;x++) g->data[(n-1)*p+x] = NOTDEF;
833 for(y=0;y<n;y++) g->data[p*y+p-1] = NOTDEF;
834
835 /* compute gradient on the remaining pixels */
836 for(x=0;x<p-1;x++)
837 for(y=0;y<n-1;y++)
838 {
839 adr = y*p+x;
840
841 /*
842 Norm 2 computation using 2x2 pixel window:
843 A B
844 C D
845 and
846 com1 = D-A, com2 = B-C.
847 Then
848 gx = B+D - (A+C) horizontal difference
849 gy = C+D - (A+B) vertical difference
850 com1 and com2 are just to avoid 2 additions.
851 */
852 com1 = in->data[adr+p+1] - in->data[adr];
853 com2 = in->data[adr+1] - in->data[adr+p];
854
855 gx = com1+com2; /* gradient x component */
856 gy = com1-com2; /* gradient y component */
857 norm2 = gx*gx+gy*gy;
858 norm = sqrt( norm2 / 4.0 ); /* gradient norm */
859
860 (*modgrad)->data[adr] = norm; /* store gradient norm */
861
862 if( norm <= threshold ) /* norm too small, gradient no defined */
863 g->data[adr] = NOTDEF; /* gradient angle not defined */
864 else
865 {
866 /* gradient angle computation */
867 g->data[adr] = atan2(gx,-gy);
868
869 /* look for the maximum of the gradient */
870 if( norm > max_grad ) max_grad = norm;
871 }
872 }
873
874 /* compute histogram of gradient values */
875 for(x=0;x<p-1;x++)
876 for(y=0;y<n-1;y++)
877 {
878 norm = (*modgrad)->data[y*p+x];
879
880 /* store the point in the right bin according to its norm */
881 i = (unsigned int) (norm * (double) n_bins / max_grad);
882 if( i >= n_bins ) i = n_bins-1;
883 if( range_l_e[i] == NULL )
884 range_l_s[i] = range_l_e[i] = list+list_count++;
885 else
886 {
887 range_l_e[i]->next = list+list_count;
888 range_l_e[i] = list+list_count++;
889 }
890 range_l_e[i]->x = (int) x;
891 range_l_e[i]->y = (int) y;
892 range_l_e[i]->next = NULL;
893 }
894
895 /* Make the list of pixels (almost) ordered by norm value.
896 It starts by the larger bin, so the list starts by the
897 pixels with the highest gradient value. Pixels would be ordered
898 by norm value, up to a precision given by max_grad/n_bins.
899 */
900 for(i=n_bins-1; i>0 && range_l_s[i]==NULL; i--);
901 start = range_l_s[i];
902 end = range_l_e[i];
903 if( start != NULL )
904 while(i>0)
905 {
906 --i;
907 if( range_l_s[i] != NULL )
908 {
909 end->next = range_l_s[i];
910 end = range_l_e[i];
911 }
912 }
913 *list_p = start;
914
915 /* free memory */
916 free( (void *) range_l_s );
917 free( (void *) range_l_e );
918
919 return g;
920}
921
922/*----------------------------------------------------------------------------*/
925static int isaligned( int x, int y, image_double angles, double theta,
926 double prec )
927{
928 double a;
929
930 /* check parameters */
931 if( angles == NULL || angles->data == NULL )
932 error("isaligned: invalid image 'angles'.");
933 if( x < 0 || y < 0 || x >= (int) angles->xsize || y >= (int) angles->ysize )
934 error("isaligned: (x,y) out of the image.");
935 if( prec < 0.0 ) error("isaligned: 'prec' must be positive.");
936
937 /* angle at pixel (x,y) */
938 a = angles->data[ x + y * angles->xsize ];
939
940 /* pixels whose level-line angle is not defined
941 are considered as NON-aligned */
942 if( a == NOTDEF ) return FALSE; /* there is no need to call the function
943 'double_equal' here because there is
944 no risk of problems related to the
945 comparison doubles, we are only
946 interested in the exact NOTDEF value */
947
948 /* it is assumed that 'theta' and 'a' are in the range [-pi,pi] */
949 theta -= a;
950 if( theta < 0.0 ) theta = -theta;
951 if( theta > M_3_2_PI )
952 {
953 theta -= M_2__PI;
954 if( theta < 0.0 ) theta = -theta;
955 }
956
957 return theta <= prec;
958}
959
960/*----------------------------------------------------------------------------*/
963static double angle_diff(double a, double b)
964{
965 a -= b;
966 while( a <= -M_PI ) a += M_2__PI;
967 while( a > M_PI ) a -= M_2__PI;
968 if( a < 0.0 ) a = -a;
969 return a;
970}
971
972/*----------------------------------------------------------------------------*/
975static double angle_diff_signed(double a, double b)
976{
977 a -= b;
978 while( a <= -M_PI ) a += M_2__PI;
979 while( a > M_PI ) a -= M_2__PI;
980 return a;
981}
982
983
984/*----------------------------------------------------------------------------*/
985/*----------------------------- NFA computation ------------------------------*/
986/*----------------------------------------------------------------------------*/
987
988/*----------------------------------------------------------------------------*/
1012static double log_gamma_lanczos(double x)
1013{
1014 static double q[7] = { 75122.6331530, 80916.6278952, 36308.2951477,
1015 8687.24529705, 1168.92649479, 83.8676043424,
1016 2.50662827511 };
1017 double a = (x+0.5) * log(x+5.5) - (x+5.5);
1018 double b = 0.0;
1019 int n;
1020
1021 for(n=0;n<7;n++)
1022 {
1023 a -= log( x + (double) n );
1024 b += q[n] * pow( x, (double) n );
1025 }
1026 return a + log(b);
1027}
1028
1029/*----------------------------------------------------------------------------*/
1046static double log_gamma_windschitl(double x)
1047{
1048 return 0.918938533204673 + (x-0.5)*log(x) - x
1049 + 0.5*x*log( x*sinh(1/x) + 1/(810.0*pow(x,6.0)) );
1050}
1051
1052/*----------------------------------------------------------------------------*/
1057#define log_gamma(x) ((x)>15.0?log_gamma_windschitl(x):log_gamma_lanczos(x))
1058
1059/*----------------------------------------------------------------------------*/
1062#define TABSIZE 100000
1063
1064// clang-format on
1065
1066static double *inv = NULL; /* table to keep computed inverse values */
1067
1069{
1070 if(inv) return;
1071 inv = malloc(sizeof(double) * TABSIZE);
1072}
1073
1074__attribute__((destructor)) static void invDestructor()
1075{
1076 free(inv);
1077 inv = NULL;
1078}
1079
1080// clang-format off
1081
1082/*----------------------------------------------------------------------------*/
1124static double nfa(int n, int k, double p, double logNT)
1125{
1126 double tolerance = 0.1; /* an error of 10% in the result is accepted */
1128 int i;
1129
1130 /* check parameters */
1131 if( n<0 || k<0 || k>n || p<=0.0 || p>=1.0 )
1132 error("nfa: wrong n, k or p values.");
1133
1134 /* trivial cases */
1135 if( n==0 || k==0 ) return -logNT;
1136 if( n==k ) return -logNT - (double) n * log10(p);
1137
1138 /* probability term */
1139 p_term = p / (1.0-p);
1140
1141 /* compute the first term of the series */
1142 /*
1143 binomial_tail(n,k,p) = sum_{i=k}^n bincoef(n,i) * p^i * (1-p)^{n-i}
1144 where bincoef(n,i) are the binomial coefficients.
1145 But
1146 bincoef(n,k) = gamma(n+1) / ( gamma(k+1) * gamma(n-k+1) ).
1147 We use this to compute the first term. Actually the log of it.
1148 */
1149 log1term = log_gamma( (double) n + 1.0 ) - log_gamma( (double) k + 1.0 )
1150 - log_gamma( (double) (n-k) + 1.0 )
1151 + (double) k * log(p) + (double) (n-k) * log(1.0-p);
1152 term = exp(log1term);
1153
1154 /* in some cases no more computations are needed */
1155 if( double_equal(term,0.0) ) /* the first term is almost zero */
1156 {
1157 if( (double) k > (double) n * p ) /* at begin or end of the tail? */
1158 return -log1term / M_LN10 - logNT; /* end: use just the first term */
1159 else
1160 return -logNT; /* begin: the tail is roughly 1 */
1161 }
1162
1163 /* compute more terms if needed */
1164 bin_tail = term;
1165 for(i=k+1;i<=n;i++)
1166 {
1167 /*
1168 As
1169 term_i = bincoef(n,i) * p^i * (1-p)^(n-i)
1170 and
1171 bincoef(n,i)/bincoef(n,i-1) = n-1+1 / i,
1172 then,
1173 term_i / term_i-1 = (n-i+1)/i * p/(1-p)
1174 and
1175 term_i = term_i-1 * (n-i+1)/i * p/(1-p).
1176 1/i is stored in a table as they are computed,
1177 because divisions are expensive.
1178 p/(1-p) is computed only once and stored in 'p_term'.
1179 */
1180 bin_term = (double) (n-i+1) * ( i<TABSIZE ?
1181 ( inv[i]!=0.0 ? inv[i] : ( inv[i] = 1.0 / (double) i ) ) :
1182 1.0 / (double) i );
1183
1185 term *= mult_term;
1186 bin_tail += term;
1187 if(bin_term<1.0)
1188 {
1189 /* When bin_term<1 then mult_term_j<mult_term_i for j>i.
1190 Then, the error on the binomial tail when truncated at
1191 the i term can be bounded by a geometric series of form
1192 term_i * sum mult_term_i^j. */
1193 err = term * ( ( 1.0 - pow( mult_term, (double) (n-i+1) ) ) /
1194 (1.0-mult_term) - 1.0 );
1195
1196 /* One wants an error at most of tolerance*final_result, or:
1197 tolerance * abs(-log10(bin_tail)-logNT).
1198 Now, the error that can be accepted on bin_tail is
1199 given by tolerance*final_result divided by the derivative
1200 of -log10(x) when x=bin_tail. that is:
1201 tolerance * abs(-log10(bin_tail)-logNT) / (1/bin_tail)
1202 Finally, we truncate the tail if the error is less than:
1203 tolerance * abs(-log10(bin_tail)-logNT) * bin_tail */
1204 if( err < tolerance * fabs(-log10(bin_tail)-logNT) * bin_tail ) break;
1205 }
1206 }
1207 return -log10(bin_tail) - logNT;
1208}
1209
1210
1211/*----------------------------------------------------------------------------*/
1212/*--------------------------- Rectangle structure ----------------------------*/
1213/*----------------------------------------------------------------------------*/
1214
1215/*----------------------------------------------------------------------------*/
1218struct rect
1219{
1220 double x1,y1,x2,y2; /* first and second point of the line segment */
1221 double width; /* rectangle width */
1222 double x,y; /* center of the rectangle */
1223 double theta; /* angle */
1224 double dx,dy; /* (dx,dy) is vector oriented as the line segment */
1225 double prec; /* tolerance angle */
1226 double p; /* probability of a point with angle within 'prec' */
1227};
1228
1229/*----------------------------------------------------------------------------*/
1232static void rect_copy(struct rect * in, struct rect * out)
1233{
1234 /* check parameters */
1235 if( in == NULL || out == NULL ) error("rect_copy: invalid 'in' or 'out'.");
1236
1237 /* copy values */
1238 out->x1 = in->x1;
1239 out->y1 = in->y1;
1240 out->x2 = in->x2;
1241 out->y2 = in->y2;
1242 out->width = in->width;
1243 out->x = in->x;
1244 out->y = in->y;
1245 out->theta = in->theta;
1246 out->dx = in->dx;
1247 out->dy = in->dy;
1248 out->prec = in->prec;
1249 out->p = in->p;
1250}
1251
1252/*----------------------------------------------------------------------------*/
1308typedef struct
1309{
1310 double vx[4]; /* rectangle's corner X coordinates in circular order */
1311 double vy[4]; /* rectangle's corner Y coordinates in circular order */
1312 double ys,ye; /* start and end Y values of current 'column' */
1313 int x,y; /* coordinates of currently explored pixel */
1314} rect_iter;
1315
1316/*----------------------------------------------------------------------------*/
1326static double inter_low(double x, double x1, double y1, double x2, double y2)
1327{
1328 /* check parameters */
1329 if( x1 > x2 || x < x1 || x > x2 )
1330 error("inter_low: unsuitable input, 'x1>x2' or 'x<x1' or 'x>x2'.");
1331
1332 /* interpolation */
1333 if( double_equal(x1,x2) && y1<y2 ) return y1;
1334 if( double_equal(x1,x2) && y1>y2 ) return y2;
1335 return y1 + (x-x1) * (y2-y1) / (x2-x1);
1336}
1337
1338/*----------------------------------------------------------------------------*/
1348static double inter_hi(double x, double x1, double y1, double x2, double y2)
1349{
1350 /* check parameters */
1351 if( x1 > x2 || x < x1 || x > x2 )
1352 error("inter_hi: unsuitable input, 'x1>x2' or 'x<x1' or 'x>x2'.");
1353
1354 /* interpolation */
1355 if( double_equal(x1,x2) && y1<y2 ) return y2;
1356 if( double_equal(x1,x2) && y1>y2 ) return y1;
1357 return y1 + (x-x1) * (y2-y1) / (x2-x1);
1358}
1359
1360/*----------------------------------------------------------------------------*/
1363static void ri_del(rect_iter * iter)
1364{
1365 if( iter == NULL ) error("ri_del: NULL iterator.");
1366 free( (void *) iter );
1367}
1368
1369/*----------------------------------------------------------------------------*/
1374static int ri_end(rect_iter * i)
1375{
1376 /* check input */
1377 if( i == NULL ) error("ri_end: NULL iterator.");
1378
1379 /* if the current x value is larger than the largest
1380 x value in the rectangle (vx[2]), we know the full
1381 exploration of the rectangle is finished. */
1382 return (double)(i->x) > i->vx[2];
1383}
1384
1385/*----------------------------------------------------------------------------*/
1390static void ri_inc(rect_iter * i)
1391{
1392 /* check input */
1393 if( i == NULL ) error("ri_inc: NULL iterator.");
1394
1395 /* if not at end of exploration,
1396 increase y value for next pixel in the 'column' */
1397 if( !ri_end(i) ) i->y++;
1398
1399 /* if the end of the current 'column' is reached,
1400 and it is not the end of exploration,
1401 advance to the next 'column' */
1402 while( (double) (i->y) > i->ye && !ri_end(i) )
1403 {
1404 /* increase x, next 'column' */
1405 i->x++;
1406
1407 /* if end of exploration, return */
1408 if( ri_end(i) ) return;
1409
1410 /* update lower y limit (start) for the new 'column'.
1411
1412 We need to interpolate the y value that corresponds to the
1413 lower side of the rectangle. The first thing is to decide if
1414 the corresponding side is
1415
1416 vx[0],vy[0] to vx[3],vy[3] or
1417 vx[3],vy[3] to vx[2],vy[2]
1418
1419 Then, the side is interpolated for the x value of the
1420 'column'. But, if the side is vertical (as it could happen if
1421 the rectangle is vertical and we are dealing with the first
1422 or last 'columns') then we pick the lower value of the side
1423 by using 'inter_low'.
1424 */
1425 if( (double) i->x < i->vx[3] )
1426 i->ys = inter_low((double)i->x,i->vx[0],i->vy[0],i->vx[3],i->vy[3]);
1427 else
1428 i->ys = inter_low((double)i->x,i->vx[3],i->vy[3],i->vx[2],i->vy[2]);
1429
1430 /* update upper y limit (end) for the new 'column'.
1431
1432 We need to interpolate the y value that corresponds to the
1433 upper side of the rectangle. The first thing is to decide if
1434 the corresponding side is
1435
1436 vx[0],vy[0] to vx[1],vy[1] or
1437 vx[1],vy[1] to vx[2],vy[2]
1438
1439 Then, the side is interpolated for the x value of the
1440 'column'. But, if the side is vertical (as it could happen if
1441 the rectangle is vertical and we are dealing with the first
1442 or last 'columns') then we pick the lower value of the side
1443 by using 'inter_low'.
1444 */
1445 if( (double)i->x < i->vx[1] )
1446 i->ye = inter_hi((double)i->x,i->vx[0],i->vy[0],i->vx[1],i->vy[1]);
1447 else
1448 i->ye = inter_hi((double)i->x,i->vx[1],i->vy[1],i->vx[2],i->vy[2]);
1449
1450 /* new y */
1451 i->y = (int) ceil(i->ys);
1452 }
1453}
1454
1455/*----------------------------------------------------------------------------*/
1460static rect_iter * ri_ini(struct rect * r)
1461{
1462 double vx[4],vy[4];
1463 int n,offset;
1464 rect_iter * i;
1465
1466 /* check parameters */
1467 if( r == NULL ) error("ri_ini: invalid rectangle.");
1468
1469 /* get memory */
1470 i = (rect_iter *) malloc(sizeof(rect_iter));
1471 if( i == NULL ) error("ri_ini: Not enough memory.");
1472
1473 /* build list of rectangle corners ordered
1474 in a circular way around the rectangle */
1475 vx[0] = r->x1 - r->dy * r->width / 2.0;
1476 vy[0] = r->y1 + r->dx * r->width / 2.0;
1477 vx[1] = r->x2 - r->dy * r->width / 2.0;
1478 vy[1] = r->y2 + r->dx * r->width / 2.0;
1479 vx[2] = r->x2 + r->dy * r->width / 2.0;
1480 vy[2] = r->y2 - r->dx * r->width / 2.0;
1481 vx[3] = r->x1 + r->dy * r->width / 2.0;
1482 vy[3] = r->y1 - r->dx * r->width / 2.0;
1483
1484 /* compute rotation of index of corners needed so that the first
1485 point has the smaller x.
1486
1487 if one side is vertical, thus two corners have the same smaller x
1488 value, the one with the largest y value is selected as the first.
1489 */
1490 if( r->x1 < r->x2 && r->y1 <= r->y2 ) offset = 0;
1491 else if( r->x1 >= r->x2 && r->y1 < r->y2 ) offset = 1;
1492 else if( r->x1 > r->x2 && r->y1 >= r->y2 ) offset = 2;
1493 else offset = 3;
1494
1495 /* apply rotation of index. */
1496 for(n=0; n<4; n++)
1497 {
1498 i->vx[n] = vx[(offset+n)%4];
1499 i->vy[n] = vy[(offset+n)%4];
1500 }
1501
1502 /* Set an initial condition.
1503
1504 The values are set to values that will cause 'ri_inc' (that will
1505 be called immediately) to initialize correctly the first 'column'
1506 and compute the limits 'ys' and 'ye'.
1507
1508 'y' is set to the integer value of vy[0], the starting corner.
1509
1510 'ys' and 'ye' are set to very small values, so 'ri_inc' will
1511 notice that it needs to start a new 'column'.
1512
1513 The smallest integer coordinate inside of the rectangle is
1514 'ceil(vx[0])'. The current 'x' value is set to that value minus
1515 one, so 'ri_inc' (that will increase x by one) will advance to
1516 the first 'column'.
1517 */
1518 i->x = (int) ceil(i->vx[0]) - 1;
1519 i->y = (int) ceil(i->vy[0]);
1520 i->ys = i->ye = -DBL_MAX;
1521
1522 /* advance to the first pixel */
1523 ri_inc(i);
1524
1525 return i;
1526}
1527
1528/*----------------------------------------------------------------------------*/
1531static double rect_nfa(struct rect * rec, image_double angles, double logNT)
1532{
1533 rect_iter * i;
1534 int pts = 0;
1535 int alg = 0;
1536
1537 /* check parameters */
1538 if( rec == NULL ) error("rect_nfa: invalid rectangle.");
1539 if( angles == NULL ) error("rect_nfa: invalid 'angles'.");
1540
1541 /* compute the total number of pixels and of aligned points in 'rec' */
1542 for(i=ri_ini(rec); !ri_end(i); ri_inc(i)) /* rectangle iterator */
1543 if( i->x >= 0 && i->y >= 0 &&
1544 i->x < (int) angles->xsize && i->y < (int) angles->ysize )
1545 {
1546 ++pts; /* total number of pixels counter */
1547 if( isaligned(i->x, i->y, angles, rec->theta, rec->prec) )
1548 ++alg; /* aligned points counter */
1549 }
1550 ri_del(i); /* delete iterator */
1551
1552 return nfa(pts,alg,rec->p,logNT); /* compute NFA value */
1553}
1554
1555
1556/*----------------------------------------------------------------------------*/
1557/*---------------------------------- Regions ---------------------------------*/
1558/*----------------------------------------------------------------------------*/
1559
1560/*----------------------------------------------------------------------------*/
1617static double get_theta( struct point * reg, int reg_size, double x, double y,
1618 image_double modgrad, double reg_angle, double prec )
1619{
1620 double lambda,theta,weight;
1621 double Ixx = 0.0;
1622 double Iyy = 0.0;
1623 double Ixy = 0.0;
1624 int i;
1625
1626 /* check parameters */
1627 if( reg == NULL ) error("get_theta: invalid region.");
1628 if( reg_size <= 1 ) error("get_theta: region size <= 1.");
1629 if( modgrad == NULL || modgrad->data == NULL )
1630 error("get_theta: invalid 'modgrad'.");
1631 if( prec < 0.0 ) error("get_theta: 'prec' must be positive.");
1632
1633 /* compute inertia matrix */
1634 for(i=0; i<reg_size; i++)
1635 {
1636 weight = modgrad->data[ reg[i].x + reg[i].y * modgrad->xsize ];
1637 Ixx += ( (double) reg[i].y - y ) * ( (double) reg[i].y - y ) * weight;
1638 Iyy += ( (double) reg[i].x - x ) * ( (double) reg[i].x - x ) * weight;
1639 Ixy -= ( (double) reg[i].x - x ) * ( (double) reg[i].y - y ) * weight;
1640 }
1641 if( double_equal(Ixx,0.0) && double_equal(Iyy,0.0) && double_equal(Ixy,0.0) )
1642 error("get_theta: null inertia matrix.");
1643
1644 /* compute smallest eigenvalue */
1645 lambda = 0.5 * ( Ixx + Iyy - sqrt( (Ixx-Iyy)*(Ixx-Iyy) + 4.0*Ixy*Ixy ) );
1646
1647 /* compute angle */
1648 theta = fabs(Ixx)>fabs(Iyy) ? atan2(lambda-Ixx,Ixy) : atan2(Ixy,lambda-Iyy);
1649
1650 /* The previous procedure doesn't cares about orientation,
1651 so it could be wrong by 180 degrees. Here is corrected if necessary. */
1652 if( angle_diff(theta,reg_angle) > prec ) theta += M_PI;
1653
1654 return theta;
1655}
1656
1657/*----------------------------------------------------------------------------*/
1660static void region2rect( struct point * reg, int reg_size,
1661 image_double modgrad, double reg_angle,
1662 double prec, double p, struct rect * rec )
1663{
1664 double x,y,dx,dy,l,w,theta,weight,sum,l_min,l_max,w_min,w_max;
1665 int i;
1666
1667 /* check parameters */
1668 if( reg == NULL ) error("region2rect: invalid region.");
1669 if( reg_size <= 1 ) error("region2rect: region size <= 1.");
1670 if( modgrad == NULL || modgrad->data == NULL )
1671 error("region2rect: invalid image 'modgrad'.");
1672 if( rec == NULL ) error("region2rect: invalid 'rec'.");
1673
1674 /* center of the region:
1675
1676 It is computed as the weighted sum of the coordinates
1677 of all the pixels in the region. The norm of the gradient
1678 is used as the weight of a pixel. The sum is as follows:
1679 cx = \sum_i G(i).x_i
1680 cy = \sum_i G(i).y_i
1681 where G(i) is the norm of the gradient of pixel i
1682 and x_i,y_i are its coordinates.
1683 */
1684 x = y = sum = 0.0;
1685 for(i=0; i<reg_size; i++)
1686 {
1687 weight = modgrad->data[ reg[i].x + reg[i].y * modgrad->xsize ];
1688 x += (double) reg[i].x * weight;
1689 y += (double) reg[i].y * weight;
1690 sum += weight;
1691 }
1692 if( sum <= 0.0 ) error("region2rect: weights sum equal to zero.");
1693 x /= sum;
1694 y /= sum;
1695
1696 /* theta */
1697 theta = get_theta(reg,reg_size,x,y,modgrad,reg_angle,prec);
1698
1699 /* length and width:
1700
1701 'l' and 'w' are computed as the distance from the center of the
1702 region to pixel i, projected along the rectangle axis (dx,dy) and
1703 to the orthogonal axis (-dy,dx), respectively.
1704
1705 The length of the rectangle goes from l_min to l_max, where l_min
1706 and l_max are the minimum and maximum values of l in the region.
1707 Analogously, the width is selected from w_min to w_max, where
1708 w_min and w_max are the minimum and maximum of w for the pixels
1709 in the region.
1710 */
1711 dx = cos(theta);
1712 dy = sin(theta);
1713 l_min = l_max = w_min = w_max = 0.0;
1714 for(i=0; i<reg_size; i++)
1715 {
1716 l = ( (double) reg[i].x - x) * dx + ( (double) reg[i].y - y) * dy;
1717 w = -( (double) reg[i].x - x) * dy + ( (double) reg[i].y - y) * dx;
1718
1719 if( l > l_max ) l_max = l;
1720 if( l < l_min ) l_min = l;
1721 if( w > w_max ) w_max = w;
1722 if( w < w_min ) w_min = w;
1723 }
1724
1725 /* store values */
1726 rec->x1 = x + l_min * dx;
1727 rec->y1 = y + l_min * dy;
1728 rec->x2 = x + l_max * dx;
1729 rec->y2 = y + l_max * dy;
1730 rec->width = w_max - w_min;
1731 rec->x = x;
1732 rec->y = y;
1733 rec->theta = theta;
1734 rec->dx = dx;
1735 rec->dy = dy;
1736 rec->prec = prec;
1737 rec->p = p;
1738
1739 /* we impose a minimal width of one pixel
1740
1741 A sharp horizontal or vertical step would produce a perfectly
1742 horizontal or vertical region. The width computed would be
1743 zero. But that corresponds to a one pixels width transition in
1744 the image.
1745 */
1746 if( rec->width < 1.0 ) rec->width = 1.0;
1747}
1748
1749/*----------------------------------------------------------------------------*/
1753static void region_grow( int x, int y, image_double angles, struct point * reg,
1754 int * reg_size, double * reg_angle, image_char used,
1755 double prec )
1756{
1757 double sumdx,sumdy;
1758 int xx,yy,i;
1759
1760 /* check parameters */
1761 if( x < 0 || y < 0 || x >= (int) angles->xsize || y >= (int) angles->ysize )
1762 error("region_grow: (x,y) out of the image.");
1763 if( angles == NULL || angles->data == NULL )
1764 error("region_grow: invalid image 'angles'.");
1765 if( reg == NULL ) error("region_grow: invalid 'reg'.");
1766 if( reg_size == NULL ) error("region_grow: invalid pointer 'reg_size'.");
1767 if( reg_angle == NULL ) error("region_grow: invalid pointer 'reg_angle'.");
1768 if( used == NULL || used->data == NULL )
1769 error("region_grow: invalid image 'used'.");
1770
1771 /* first point of the region */
1772 *reg_size = 1;
1773 reg[0].x = x;
1774 reg[0].y = y;
1775 *reg_angle = angles->data[x+y*angles->xsize]; /* region's angle */
1776 sumdx = cos(*reg_angle);
1777 sumdy = sin(*reg_angle);
1778 used->data[x+y*used->xsize] = USED;
1779
1780 /* try neighbors as new region points */
1781 for(i=0; i<*reg_size; i++)
1782 for(xx=reg[i].x-1; xx<=reg[i].x+1; xx++)
1783 for(yy=reg[i].y-1; yy<=reg[i].y+1; yy++)
1784 if( xx>=0 && yy>=0 && xx<(int)used->xsize && yy<(int)used->ysize &&
1785 used->data[xx+yy*used->xsize] != USED &&
1786 isaligned(xx,yy,angles,*reg_angle,prec) )
1787 {
1788 /* add point */
1789 used->data[xx+yy*used->xsize] = USED;
1790 reg[*reg_size].x = xx;
1791 reg[*reg_size].y = yy;
1792 ++(*reg_size);
1793
1794 /* update region's angle */
1795 sumdx += cos( angles->data[xx+yy*angles->xsize] );
1796 sumdy += sin( angles->data[xx+yy*angles->xsize] );
1797 *reg_angle = atan2(sumdy,sumdx);
1798 }
1799}
1800
1801/*----------------------------------------------------------------------------*/
1805static double rect_improve( struct rect * rec, image_double angles,
1806 double logNT, double log_eps )
1807{
1808 struct rect r;
1809 double log_nfa,log_nfa_new;
1810 double delta = 0.5;
1811 double delta_2 = delta / 2.0;
1812 int n;
1813
1815
1816 if( log_nfa > log_eps ) return log_nfa;
1817
1818 /* try finer precisions */
1819 rect_copy(rec,&r);
1820 for(n=0; n<5; n++)
1821 {
1822 r.p /= 2.0;
1823 r.prec = r.p * M_PI;
1825 if( log_nfa_new > log_nfa )
1826 {
1828 rect_copy(&r,rec);
1829 }
1830 }
1831
1832 if( log_nfa > log_eps ) return log_nfa;
1833
1834 /* try to reduce width */
1835 rect_copy(rec,&r);
1836 for(n=0; n<5; n++)
1837 {
1838 if( (r.width - delta) >= 0.5 )
1839 {
1840 r.width -= delta;
1842 if( log_nfa_new > log_nfa )
1843 {
1844 rect_copy(&r,rec);
1846 }
1847 }
1848 }
1849
1850 if( log_nfa > log_eps ) return log_nfa;
1851
1852 /* try to reduce one side of the rectangle */
1853 rect_copy(rec,&r);
1854 for(n=0; n<5; n++)
1855 {
1856 if( (r.width - delta) >= 0.5 )
1857 {
1858 r.x1 += -r.dy * delta_2;
1859 r.y1 += r.dx * delta_2;
1860 r.x2 += -r.dy * delta_2;
1861 r.y2 += r.dx * delta_2;
1862 r.width -= delta;
1864 if( log_nfa_new > log_nfa )
1865 {
1866 rect_copy(&r,rec);
1868 }
1869 }
1870 }
1871
1872 if( log_nfa > log_eps ) return log_nfa;
1873
1874 /* try to reduce the other side of the rectangle */
1875 rect_copy(rec,&r);
1876 for(n=0; n<5; n++)
1877 {
1878 if( (r.width - delta) >= 0.5 )
1879 {
1880 r.x1 -= -r.dy * delta_2;
1881 r.y1 -= r.dx * delta_2;
1882 r.x2 -= -r.dy * delta_2;
1883 r.y2 -= r.dx * delta_2;
1884 r.width -= delta;
1886 if( log_nfa_new > log_nfa )
1887 {
1888 rect_copy(&r,rec);
1890 }
1891 }
1892 }
1893
1894 if( log_nfa > log_eps ) return log_nfa;
1895
1896 /* try even finer precisions */
1897 rect_copy(rec,&r);
1898 for(n=0; n<5; n++)
1899 {
1900 r.p /= 2.0;
1901 r.prec = r.p * M_PI;
1903 if( log_nfa_new > log_nfa )
1904 {
1906 rect_copy(&r,rec);
1907 }
1908 }
1909
1910 return log_nfa;
1911}
1912
1913/*----------------------------------------------------------------------------*/
1918static int reduce_region_radius( struct point * reg, int * reg_size,
1920 double prec, double p, struct rect * rec,
1922 double density_th )
1923{
1924 double density,radius1,radius2,rad,xc,yc;
1925 int i;
1926
1927 /* check parameters */
1928 if( reg == NULL ) error("reduce_region_radius: invalid pointer 'reg'.");
1929 if( reg_size == NULL )
1930 error("reduce_region_radius: invalid pointer 'reg_size'.");
1931 if( prec < 0.0 ) error("reduce_region_radius: 'prec' must be positive.");
1932 if( rec == NULL ) error("reduce_region_radius: invalid pointer 'rec'.");
1933 if( used == NULL || used->data == NULL )
1934 error("reduce_region_radius: invalid image 'used'.");
1935 if( angles == NULL || angles->data == NULL )
1936 error("reduce_region_radius: invalid image 'angles'.");
1937
1938 /* compute region points density */
1939 density = (double) *reg_size /
1940 ( dist(rec->x1,rec->y1,rec->x2,rec->y2) * rec->width );
1941
1942 /* if the density criterion is satisfied there is nothing to do */
1943 if( density >= density_th ) return TRUE;
1944
1945 /* compute region's radius */
1946 xc = (double) reg[0].x;
1947 yc = (double) reg[0].y;
1948 radius1 = dist( xc, yc, rec->x1, rec->y1 );
1949 radius2 = dist( xc, yc, rec->x2, rec->y2 );
1951
1952 /* while the density criterion is not satisfied, remove farther pixels */
1953 while( density < density_th )
1954 {
1955 rad *= 0.75; /* reduce region's radius to 75% of its value */
1956
1957 /* remove points from the region and update 'used' map */
1958 for(i=0; i<*reg_size; i++)
1959 if( dist( xc, yc, (double) reg[i].x, (double) reg[i].y ) > rad )
1960 {
1961 /* point not kept, mark it as NOTUSED */
1962 used->data[ reg[i].x + reg[i].y * used->xsize ] = NOTUSED;
1963 /* remove point from the region */
1964 reg[i].x = reg[*reg_size-1].x; /* if i==*reg_size-1 copy itself */
1965 reg[i].y = reg[*reg_size-1].y;
1966 --(*reg_size);
1967 --i; /* to avoid skipping one point */
1968 }
1969
1970 /* reject if the region is too small.
1971 2 is the minimal region size for 'region2rect' to work. */
1972 if( *reg_size < 2 ) return FALSE;
1973
1974 /* re-compute rectangle */
1976
1977 /* re-compute region points density */
1978 density = (double) *reg_size /
1979 ( dist(rec->x1,rec->y1,rec->x2,rec->y2) * rec->width );
1980 }
1981
1982 /* if this point is reached, the density criterion is satisfied */
1983 return TRUE;
1984}
1985
1986/*----------------------------------------------------------------------------*/
1996static int refine( struct point * reg, int * reg_size, image_double modgrad,
1997 double reg_angle, double prec, double p, struct rect * rec,
1999{
2000 double angle,ang_d,mean_angle,tau,density,xc,yc,ang_c,sum,s_sum;
2001 int i,n;
2002
2003 /* check parameters */
2004 if( reg == NULL ) error("refine: invalid pointer 'reg'.");
2005 if( reg_size == NULL ) error("refine: invalid pointer 'reg_size'.");
2006 if( prec < 0.0 ) error("refine: 'prec' must be positive.");
2007 if( rec == NULL ) error("refine: invalid pointer 'rec'.");
2008 if( used == NULL || used->data == NULL )
2009 error("refine: invalid image 'used'.");
2010 if( angles == NULL || angles->data == NULL )
2011 error("refine: invalid image 'angles'.");
2012
2013 /* compute region points density */
2014 density = (double) *reg_size /
2015 ( dist(rec->x1,rec->y1,rec->x2,rec->y2) * rec->width );
2016
2017 /* if the density criterion is satisfied there is nothing to do */
2018 if( density >= density_th ) return TRUE;
2019
2020 /*------ First try: reduce angle tolerance ------*/
2021
2022 /* compute the new mean angle and tolerance */
2023 xc = (double) reg[0].x;
2024 yc = (double) reg[0].y;
2025 ang_c = angles->data[ reg[0].x + reg[0].y * angles->xsize ];
2026 sum = s_sum = 0.0;
2027 n = 0;
2028 for(i=0; i<*reg_size; i++)
2029 {
2030 used->data[ reg[i].x + reg[i].y * used->xsize ] = NOTUSED;
2031 if( dist( xc, yc, (double) reg[i].x, (double) reg[i].y ) < rec->width )
2032 {
2033 angle = angles->data[ reg[i].x + reg[i].y * angles->xsize ];
2034 ang_d = angle_diff_signed(angle,ang_c);
2035 sum += ang_d;
2036 s_sum += ang_d * ang_d;
2037 ++n;
2038 }
2039 }
2040
2041 /* should not happen */
2042 if(n == 0) return FALSE;
2043
2044 mean_angle = sum / (double) n;
2045 tau = 2.0 * sqrt( (s_sum - 2.0 * mean_angle * sum) / (double) n
2046 + mean_angle*mean_angle ); /* 2 * standard deviation */
2047
2048 /* find a new region from the same starting point and new angle tolerance */
2050
2051 /* if the region is too small, reject */
2052 if( *reg_size < 2 ) return FALSE;
2053
2054 /* re-compute rectangle */
2056
2057 /* re-compute region points density */
2058 density = (double) *reg_size /
2059 ( dist(rec->x1,rec->y1,rec->x2,rec->y2) * rec->width );
2060
2061 /*------ Second try: reduce region radius ------*/
2062 if( density < density_th )
2064 rec, used, angles, density_th );
2065
2066 /* if this point is reached, the density criterion is satisfied */
2067 return TRUE;
2068}
2069
2070
2071/*----------------------------------------------------------------------------*/
2072/*-------------------------- Line Segment Detector ---------------------------*/
2073/*----------------------------------------------------------------------------*/
2074
2075/*----------------------------------------------------------------------------*/
2078static double * LineSegmentDetection( int * n_out,
2079 double * img, int X, int Y,
2080 double scale, double sigma_scale, double quant,
2081 double ang_th, double log_eps, double density_th,
2082 int n_bins,
2083 int ** reg_img, int * reg_x, int * reg_y )
2084{
2085 image_double image;
2087 double * return_value;
2089 image_char used;
2091 struct coorlist * list_p;
2092 void * mem_p;
2093 struct rect rec;
2094 struct point * reg;
2095 int reg_size,min_reg_size,i;
2096 unsigned int xsize,ysize;
2097 double rho,reg_angle,prec,p,log_nfa,logNT;
2098 int ls_count = 0; /* line segments are numbered 1,2,3,... */
2099
2100
2101 /* check parameters */
2102 if( img == NULL || X <= 0 || Y <= 0 ) error("invalid image input.");
2103 if( scale <= 0.0 ) error("'scale' value must be positive.");
2104 if( sigma_scale <= 0.0 ) error("'sigma_scale' value must be positive.");
2105 if( quant < 0.0 ) error("'quant' value must be positive.");
2106 if( ang_th <= 0.0 || ang_th >= 180.0 )
2107 error("'ang_th' value must be in the range (0,180).");
2109 error("'density_th' value must be in the range [0,1].");
2110 if( n_bins <= 0 ) error("'n_bins' value must be positive.");
2111
2112
2113 /* angle tolerance */
2114 prec = M_PI * ang_th / 180.0;
2115 p = ang_th / 180.0;
2116 rho = quant / sin(prec); /* gradient magnitude threshold */
2117
2118
2119 /* load and scale image (if necessary) and compute angle at each pixel */
2120 image = new_image_double_ptr( (unsigned int) X, (unsigned int) Y, img );
2121 if( scale != 1.0 )
2122 {
2123 scaled_image = gaussian_sampler( image, scale, sigma_scale );
2125 &modgrad, (unsigned int) n_bins );
2127 }
2128 else
2129 angles = ll_angle( image, rho, &list_p, &mem_p, &modgrad,
2130 (unsigned int) n_bins );
2131 xsize = angles->xsize;
2132 ysize = angles->ysize;
2133
2134 /* Number of Tests - NT
2135
2136 The theoretical number of tests is Np.(XY)^(5/2)
2137 where X and Y are number of columns and rows of the image.
2138 Np corresponds to the number of angle precisions considered.
2139 As the procedure 'rect_improve' tests 5 times to halve the
2140 angle precision, and 5 more times after improving other factors,
2141 11 different precision values are potentially tested. Thus,
2142 the number of tests is
2143 11 * (X*Y)^(5/2)
2144 whose logarithm value is
2145 log10(11) + 5/2 * (log10(X) + log10(Y)).
2146 */
2147 logNT = 5.0 * ( log10( (double) xsize ) + log10( (double) ysize ) ) / 2.0
2148 + log10(11.0);
2149 min_reg_size = (int) (-logNT/log10(p)); /* minimal number of points in region
2150 that can give a meaningful event */
2151
2152
2153 /* initialize some structures */
2154 if( reg_img != NULL && reg_x != NULL && reg_y != NULL ) /* save region data */
2155 region = new_image_int_ini(angles->xsize,angles->ysize,0);
2156 used = new_image_char_ini(xsize,ysize,NOTUSED);
2157 reg = (struct point *) calloc( (size_t) (xsize*ysize), sizeof(struct point) );
2158 if( reg == NULL ) error("not enough memory!");
2159
2160
2161 /* search for line segments */
2162 for(; list_p != NULL; list_p = list_p->next )
2163 if( used->data[ list_p->x + list_p->y * used->xsize ] == NOTUSED &&
2164 angles->data[ list_p->x + list_p->y * angles->xsize ] != NOTDEF )
2165 /* there is no risk of double comparison problems here
2166 because we are only interested in the exact NOTDEF value */
2167 {
2168 /* find the region of connected point and ~equal angle */
2170 &reg_angle, used, prec );
2171
2172 /* reject small regions */
2173 if( reg_size < min_reg_size ) continue;
2174
2175 /* construct rectangular approximation for the region */
2177
2178 /* Check if the rectangle exceeds the minimal density of
2179 region points. If not, try to improve the region.
2180 The rectangle will be rejected if the final one does
2181 not fulfill the minimal density condition.
2182 This is an addition to the original LSD algorithm published in
2183 "LSD: A Fast Line Segment Detector with a False Detection Control"
2184 by R. Grompone von Gioi, J. Jakubowicz, J.M. Morel, and G. Randall.
2185 The original algorithm is obtained with density_th = 0.0.
2186 */
2188 prec, p, &rec, used, angles, density_th ) ) continue;
2189
2190 /* compute NFA value */
2192 if( log_nfa <= log_eps ) continue;
2193
2194 /* A New Line Segment was found! */
2195 ++ls_count; /* increase line segment counter */
2196
2197 /*
2198 The gradient was computed with a 2x2 mask, its value corresponds to
2199 points with an offset of (0.5,0.5), that should be added to output.
2200 The coordinates origin is at the center of pixel (0,0).
2201 */
2202 rec.x1 += 0.5; rec.y1 += 0.5;
2203 rec.x2 += 0.5; rec.y2 += 0.5;
2204
2205 /* scale the result values if a subsampling was performed */
2206 if( scale != 1.0 )
2207 {
2208 rec.x1 /= scale; rec.y1 /= scale;
2209 rec.x2 /= scale; rec.y2 /= scale;
2210 rec.width /= scale;
2211 }
2212
2213 /* add line segment found to output */
2214 add_7tuple( out, rec.x1, rec.y1, rec.x2, rec.y2,
2215 rec.width, rec.p, log_nfa );
2216
2217 /* add region number to 'region' image if needed */
2218 if( region != NULL )
2219 for(i=0; i<reg_size; i++)
2220 region->data[ reg[i].x + reg[i].y * region->xsize ] = ls_count;
2221 }
2222
2223
2224 /* free memory */
2225 free( (void *) image ); /* only the double_image structure should be freed,
2226 the data pointer was provided to this functions
2227 and should not be destroyed. */
2230 free_image_char(used);
2231 free( (void *) reg );
2232 free( (void *) mem_p );
2233
2234 /* return the result */
2235 if( reg_img != NULL && reg_x != NULL && reg_y != NULL )
2236 {
2237 if( region == NULL ) error("'region' should be a valid image.");
2238 *reg_img = region->data;
2239 if( region->xsize > (unsigned int) INT_MAX ||
2240 region->ysize > (unsigned int) INT_MAX )
2241 error("region image to big to fit in INT sizes.");
2242 *reg_x = (int) (region->xsize);
2243 *reg_y = (int) (region->ysize);
2244
2245 /* free the 'region' structure.
2246 we cannot use the function 'free_image_int' because we need to keep
2247 the memory with the image data to be returned by this function. */
2248 free( (void *) region );
2249 }
2250 if( out->size > (unsigned int) INT_MAX )
2251 error("too many detections to fit in an INT.");
2252 *n_out = (int) (out->size);
2253
2254 return_value = out->values;
2255 free( (void *) out ); /* only the 'ntuple_list' structure must be freed,
2256 but the 'values' pointer must be keep to return
2257 as a result. */
2258
2259 return return_value;
2260}
2261#if 0
2262/*----------------------------------------------------------------------------*/
2265static double * lsd_scale_region( int * n_out,
2266 double * img, int X, int Y, double scale,
2267 int ** reg_img, int * reg_x, int * reg_y )
2268{
2269 /* LSD parameters */
2270 double sigma_scale = 0.6; /* Sigma for Gaussian filter is computed as
2271 sigma = sigma_scale/scale. */
2272 double quant = 2.0; /* Bound to the quantization error on the
2273 gradient norm. */
2274 double ang_th = 22.5; /* Gradient angle tolerance in degrees. */
2275 double log_eps = 0.0; /* Detection threshold: -log10(NFA) > log_eps */
2276 double density_th = 0.7; /* Minimal density of region points in rectangle. */
2277 int n_bins = 1024; /* Number of bins in pseudo-ordering of gradient
2278 modulus. */
2279
2280 return LineSegmentDetection( n_out, img, X, Y, scale, sigma_scale, quant,
2282 reg_img, reg_x, reg_y );
2283}
2284
2285/*----------------------------------------------------------------------------*/
2288static double * lsd_scale(int * n_out, double * img, int X, int Y, double scale)
2289{
2290 return lsd_scale_region(n_out,img,X,Y,scale,NULL,NULL,NULL);
2291}
2292
2293/*----------------------------------------------------------------------------*/
2296static double * lsd(int * n_out, double * img, int X, int Y)
2297{
2298 /* LSD parameters */
2299 double scale = 0.8; /* Scale the image by Gaussian filter to 'scale'. */
2300
2301 return lsd_scale(n_out,img,X,Y,scale);
2302}
2303/*----------------------------------------------------------------------------*/
2304#endif
2305/*==================================================================================
2306 * end of LSD code
2307 *==================================================================================*/
2308
2309// clang-format on
2310
2311#undef NOTDEF
2312#undef NOTUSED
2313#undef USED
2314#undef RELATIVE_ERROR_FACTOR
2315#undef TABSIZE
2316
2317// clang-format off
2318// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
2319// vim: shiftwidth=2 expandtab tabstop=2 cindent
2320// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
2321// clang-format on
__attribute__((constructor))
Definition ashift_lsd.c:1068
static image_int new_image_int(unsigned int xsize, unsigned int ysize)
Definition ashift_lsd.c:455
static ntuple_list new_ntuple_list(unsigned int dim)
Definition ashift_lsd.c:293
static void region2rect(struct point *reg, int reg_size, image_double modgrad, double reg_angle, double prec, double p, struct rect *rec)
Definition ashift_lsd.c:1660
static double get_theta(struct point *reg, int reg_size, double x, double y, image_double modgrad, double reg_angle, double prec)
Definition ashift_lsd.c:1617
static double * LineSegmentDetection(int *n_out, double *img, int X, int Y, double scale, double sigma_scale, double quant, double ang_th, double log_eps, double density_th, int n_bins, int **reg_img, int *reg_x, int *reg_y)
Definition ashift_lsd.c:2078
#define NOTDEF
Definition ashift_lsd.c:155
static double dist(double x1, double y1, double x2, double y2)
Definition ashift_lsd.c:239
static void enlarge_ntuple_list(ntuple_list n_tuple)
Definition ashift_lsd.c:319
static int ri_end(rect_iter *i)
Definition ashift_lsd.c:1374
static void region_grow(int x, int y, image_double angles, struct point *reg, int *reg_size, double *reg_angle, image_char used, double prec)
Definition ashift_lsd.c:1753
static void free_ntuple_list(ntuple_list in)
Definition ashift_lsd.c:281
static image_double ll_angle(image_double in, double threshold, struct coorlist **list_p, void **mem_p, image_double *modgrad, unsigned int n_bins)
Definition ashift_lsd.c:784
struct image_double_s * image_double
static double angle_diff(double a, double b)
Definition ashift_lsd.c:963
static double log_gamma_windschitl(double x)
Definition ashift_lsd.c:1046
static image_double gaussian_sampler(image_double in, double scale, double sigma_scale)
Definition ashift_lsd.c:643
static image_char new_image_char(unsigned int xsize, unsigned int ysize)
Definition ashift_lsd.c:395
#define RELATIVE_ERROR_FACTOR
Definition ashift_lsd.c:200
static rect_iter * ri_ini(struct rect *r)
Definition ashift_lsd.c:1460
static image_int new_image_int_ini(unsigned int xsize, unsigned int ysize, int fill_value)
Definition ashift_lsd.c:479
static double rect_improve(struct rect *rec, image_double angles, double logNT, double log_eps)
Definition ashift_lsd.c:1805
#define TABSIZE
Definition ashift_lsd.c:1062
static void add_7tuple(ntuple_list out, double v1, double v2, double v3, double v4, double v5, double v6, double v7)
Definition ashift_lsd.c:337
static image_double new_image_double(unsigned int xsize, unsigned int ysize)
Definition ashift_lsd.c:521
static void gaussian_kernel(ntuple_list kernel, double sigma, double mean)
Definition ashift_lsd.c:580
struct ntuple_list_s * ntuple_list
struct image_int_s * image_int
static int refine(struct point *reg, int *reg_size, image_double modgrad, double reg_angle, double prec, double p, struct rect *rec, image_char used, image_double angles, double density_th)
Definition ashift_lsd.c:1996
#define NOTUSED
Definition ashift_lsd.c:164
static void rect_copy(struct rect *in, struct rect *out)
Definition ashift_lsd.c:1232
static double rect_nfa(struct rect *rec, image_double angles, double logNT)
Definition ashift_lsd.c:1531
#define M_2__PI
Definition ashift_lsd.c:161
static double nfa(int n, int k, double p, double logNT)
Definition ashift_lsd.c:1124
static void error(char *msg)
Definition ashift_lsd.c:191
static image_char new_image_char_ini(unsigned int xsize, unsigned int ysize, unsigned char fill_value)
Definition ashift_lsd.c:420
static void ri_del(rect_iter *iter)
Definition ashift_lsd.c:1363
static double * inv
Definition ashift_lsd.c:1066
static void free_image_char(image_char i)
Definition ashift_lsd.c:384
static double inter_hi(double x, double x1, double y1, double x2, double y2)
Definition ashift_lsd.c:1348
#define TRUE
Definition ashift_lsd.c:151
#define FALSE
Definition ashift_lsd.c:147
static double angle_diff_signed(double a, double b)
Definition ashift_lsd.c:975
#define USED
Definition ashift_lsd.c:167
static image_double new_image_double_ptr(unsigned int xsize, unsigned int ysize, double *data)
Definition ashift_lsd.c:545
static double inter_low(double x, double x1, double y1, double x2, double y2)
Definition ashift_lsd.c:1326
struct image_char_s * image_char
static double log_gamma_lanczos(double x)
Definition ashift_lsd.c:1012
static void free_image_double(image_double i)
Definition ashift_lsd.c:510
static int double_equal(double a, double b)
Definition ashift_lsd.c:213
static int isaligned(int x, int y, image_double angles, double theta, double prec)
Definition ashift_lsd.c:925
#define M_3_2_PI
Definition ashift_lsd.c:158
static int reduce_region_radius(struct point *reg, int *reg_size, image_double modgrad, double reg_angle, double prec, double p, struct rect *rec, image_char used, image_double angles, double density_th)
Definition ashift_lsd.c:1918
static void ri_inc(rect_iter *i)
Definition ashift_lsd.c:1390
#define log_gamma(x)
Definition ashift_lsd.c:1057
static float kernel(const float *x, const float *y)
Definition colorchecker.c:435
static void weight(const float *c1, const float *c2, const float sharpen, dt_aligned_pixel_t weight)
Definition eaw.c:29
#define M_LN10
Definition math.h:32
#define M_PI
Definition math.h:37
#define N
Definition noiseprofile.c:139
Definition ashift_lsd.c:173
int x
Definition ashift_lsd.c:174
int y
Definition ashift_lsd.c:174
struct coorlist * next
Definition ashift_lsd.c:175
Definition ashift_lsd.c:376
unsigned int xsize
Definition ashift_lsd.c:378
unsigned int ysize
Definition ashift_lsd.c:378
unsigned char * data
Definition ashift_lsd.c:377
Definition ashift_lsd.c:502
unsigned int xsize
Definition ashift_lsd.c:504
unsigned int ysize
Definition ashift_lsd.c:504
double * data
Definition ashift_lsd.c:503
Definition ashift_lsd.c:447
unsigned int xsize
Definition ashift_lsd.c:449
unsigned int ysize
Definition ashift_lsd.c:449
int * data
Definition ashift_lsd.c:448
Definition ashift_lsd.c:271
unsigned int dim
Definition ashift_lsd.c:274
unsigned int size
Definition ashift_lsd.c:272
double * values
Definition ashift_lsd.c:275
unsigned int max_size
Definition ashift_lsd.c:273
Definition ashift_lsd.c:181
int y
Definition ashift_lsd.c:181
int x
Definition ashift_lsd.c:181
Definition ashift_lsd.c:1309
double vy[4]
Definition ashift_lsd.c:1311
int y
Definition ashift_lsd.c:1313
double ys
Definition ashift_lsd.c:1312
int x
Definition ashift_lsd.c:1313
double ye
Definition ashift_lsd.c:1312
double vx[4]
Definition ashift_lsd.c:1310
Definition ashift_lsd.c:1219
double dx
Definition ashift_lsd.c:1224
double theta
Definition ashift_lsd.c:1223
double dy
Definition ashift_lsd.c:1224
double y2
Definition ashift_lsd.c:1220
double x1
Definition ashift_lsd.c:1220
double x2
Definition ashift_lsd.c:1220
double y1
Definition ashift_lsd.c:1220
double p
Definition ashift_lsd.c:1226
double x
Definition ashift_lsd.c:1222
double width
Definition ashift_lsd.c:1221
double prec
Definition ashift_lsd.c:1225
double y
Definition ashift_lsd.c:1222
typedef double((*spd)(unsigned long int wavelength, double TempK))