166#define NOTDEF -1024.0
169#define M_3_2_PI 4.71238898038
172#define M_2__PI 6.28318530718
204 fprintf(stderr,
"LSD Error: %s\n",msg);
211#define RELATIVE_ERROR_FACTOR 100.0
226 double abs_diff,aa,bb,abs_max;
229 if( a == b )
return TRUE;
231 abs_diff = fabs(a-b);
234 abs_max = aa > bb ? aa : bb;
241 if( abs_max < DBL_MIN ) abs_max = DBL_MIN;
250static double dist(
double x1,
double y1,
double x2,
double y2)
252 return sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );
295 error(
"free_ntuple_list: invalid n-tuple input.");
309 if( dim == 0 )
error(
"new_ntuple_list: 'dim' must be positive.");
321 n_tuple->
values = (
double *) malloc(
sizeof(
double) * dim * n_tuple->
max_size);
334 error(
"enlarge_ntuple_list: invalid n-tuple.");
340 n_tuple->
values = (
double *) realloc( (
void *) n_tuple->
values,
349 double v4,
double v5,
double v6,
double v7 )
353 if(
out->dim != 7 )
error(
"add_7tuple: the n-tuple must be a 7-tuple.");
360 out->values[
out->size *
out->dim + 0 ] = v1;
361 out->values[
out->size *
out->dim + 1 ] = v2;
362 out->values[
out->size *
out->dim + 2 ] = v3;
363 out->values[
out->size *
out->dim + 3 ] = v4;
364 out->values[
out->size *
out->dim + 4 ] = v5;
365 out->values[
out->size *
out->dim + 5 ] = v6;
366 out->values[
out->size *
out->dim + 6 ] = v7;
398 error(
"free_image_char: invalid input image.");
411 if( xsize == 0 || ysize == 0 )
error(
"new_image_char: invalid image size.");
416 image->
data = (
unsigned char *) calloc( (
size_t) (xsize*ysize),
417 sizeof(
unsigned char) );
421 image->
xsize = xsize;
422 image->
ysize = ysize;
432 unsigned char fill_value )
435 unsigned int N = xsize*ysize;
440 error(
"new_image_char_ini: invalid image.");
443 for(
i=0;
i<
N;
i++) image->
data[
i] = fill_value;
471 if( xsize == 0 || ysize == 0 )
error(
"new_image_int: invalid image size.");
476 image->
data = (
int *) calloc( (
size_t) (xsize*ysize),
sizeof(
int) );
480 image->
xsize = xsize;
481 image->
ysize = ysize;
494 unsigned int N = xsize*ysize;
498 for(
i=0;
i<
N;
i++) image->
data[
i] = fill_value;
524 error(
"free_image_double: invalid input image.");
537 if( xsize == 0 || ysize == 0 )
error(
"new_image_double: invalid image size.");
542 image->
data = (
double *) calloc( (
size_t) (xsize*ysize),
sizeof(
double) );
546 image->
xsize = xsize;
547 image->
ysize = ysize;
557 unsigned int ysize,
double * data )
562 if( xsize == 0 || ysize == 0 )
563 error(
"new_image_double_ptr: invalid image size.");
571 image->
xsize = xsize;
572 image->
ysize = ysize;
599 error(
"gaussian_kernel: invalid n-tuple 'kernel'.");
600 if(
sigma <= 0.0 )
error(
"gaussian_kernel: 'sigma' must be positive.");
608 kernel->values[
i] = exp( -0.5 * val * val );
659 unsigned int N,
M,h,
n,
x,y,
i;
660 int xc,yc,j,double_x_size,double_y_size;
661 double sigma,xx,yy,sum,prec;
665 error(
"gaussian_sampler: invalid image.");
666 if( scale <= 0.0 )
error(
"gaussian_sampler: 'scale' must be positive.");
667 if( sigma_scale <= 0.0 )
668 error(
"gaussian_sampler: 'sigma_scale' must be positive.");
671 if( in->
xsize * scale > (
double) UINT_MAX ||
672 in->
ysize * scale > (
double) UINT_MAX )
673 error(
"gaussian_sampler: the output image size exceeds the handled size.");
674 N = (
unsigned int) ceil( in->
xsize * scale );
675 M = (
unsigned int) ceil( in->
ysize * scale );
680 sigma = scale < 1.0 ? sigma_scale / scale : sigma_scale;
690 h = (
unsigned int) ceil(
sigma * sqrt( 2.0 * prec *
log(10.0) ) );
695 double_x_size = (int) (2 * in->
xsize);
696 double_y_size = (int) (2 * in->
ysize);
709 xc = (int) floor( xx + 0.5 );
714 for(y=0;y<aux->
ysize;y++)
722 while( j < 0 ) j += double_x_size;
723 while( j >= double_x_size ) j -= double_x_size;
724 if( j >= (
int) in->
xsize ) j = double_x_size-1-j;
733 for(y=0;y<
out->ysize;y++)
743 yc = (int) floor( yy + 0.5 );
756 while( j < 0 ) j += double_y_size;
757 while( j >= double_y_size ) j -= double_y_size;
758 if( j >= (
int) in->
ysize ) j = double_y_size-1-j;
762 out->data[
x + y *
out->xsize ] = sum;
796 struct coorlist ** list_p,
void ** mem_p,
800 unsigned int n,
p,
x,y,adr,
i;
801 double com1,com2,gx,gy,norm,norm2;
810 double max_grad = 0.0;
814 error(
"ll_angle: invalid image.");
815 if(
threshold < 0.0 )
error(
"ll_angle: 'threshold' must be positive.");
819 if( n_bins == 0 )
error(
"ll_angle: 'n_bins' must be positive.");
833 *mem_p = (
void *) list;
834 range_l_s = (
struct coorlist **) calloc( (
size_t) n_bins,
836 range_l_e = (
struct coorlist **) calloc( (
size_t) n_bins,
839 error(
"not enough memory.");
840 for(
i=0;
i<n_bins;
i++) range_l_s[
i] = range_l_e[
i] = NULL;
863 com1 = in->
data[adr+
p+1] - in->
data[adr];
864 com2 = in->
data[adr+1] - in->
data[adr+
p];
869 norm = sqrt( norm2 / 4.0 );
871 (*modgrad)->data[adr] = norm;
878 g->data[adr] = atan2(gx,-gy);
881 if( norm > max_grad ) max_grad = norm;
889 norm = (*modgrad)->data[
y*
p+
x];
892 i = (
unsigned int) (norm * (
double) n_bins / max_grad);
893 if(
i >= n_bins )
i = n_bins-1;
894 if( range_l_e[
i] == NULL )
895 range_l_s[
i] = range_l_e[
i] = list+list_count++;
898 range_l_e[
i]->
next = list+list_count;
899 range_l_e[
i] = list+list_count++;
901 range_l_e[
i]->
x = (int)
x;
902 range_l_e[
i]->
y = (int)
y;
903 range_l_e[
i]->
next = NULL;
911 for(
i=n_bins-1;
i>0 && range_l_s[
i]==NULL;
i--);
912 start = range_l_s[
i];
920 end->
next = range_l_s[
i];
943 error(
"isaligned: invalid image 'angles'.");
944 if(
x < 0 || y < 0 || x >= (
int) angles->
xsize ||
y >= (
int) angles->
ysize )
945 error(
"isaligned: (x,y) out of the image.");
946 if( prec < 0.0 )
error(
"isaligned: 'prec' must be positive.");
961 if( theta < 0.0 ) theta = -theta;
965 if( theta < 0.0 ) theta = -theta;
968 return theta <= prec;
979 if( a < 0.0 ) a = -a;
1025 static double q[7] = { 75122.6331530, 80916.6278952, 36308.2951477,
1026 8687.24529705, 1168.92649479, 83.8676043424,
1028 double a = (
x+0.5) *
log(
x+5.5) - (
x+5.5);
1034 a -=
log(
x + (
double)
n );
1035 b += q[
n] * pow(
x, (
double)
n );
1059 return 0.918938533204673 + (
x-0.5)*
log(
x) -
x
1060 + 0.5*
x*
log(
x*sinh(1/
x) + 1/(810.0*pow(
x,6.0)) );
1068#define log_gamma(x) ((x)>15.0?log_gamma_windschitl(x):log_gamma_lanczos(x))
1073#define TABSIZE 100000
1134static double nfa(
int n,
int k,
double p,
double logNT)
1136 double tolerance = 0.1;
1137 double log1term,term,bin_term,mult_term,bin_tail,err,p_term;
1141 if(
n<0 || k<0 || k>
n || p<=0.0 || p>=1.0 )
1142 error(
"nfa: wrong n, k or p values.");
1145 if(
n==0 ||
k==0 )
return -logNT;
1146 if(
n==
k )
return -logNT - (
double)
n * log10(
p);
1149 p_term =
p / (1.0-
p);
1162 term = exp(log1term);
1167 if( (
double)
k > (
double)
n *
p )
1168 return -log1term /
M_LN10 - logNT;
1194 mult_term = bin_term * p_term;
1203 err = term * ( ( 1.0 - pow( mult_term, (
double) (
n-
i+1) ) ) /
1204 (1.0-mult_term) - 1.0 );
1214 if( err < tolerance * fabs(-log10(bin_tail)-logNT) * bin_tail )
break;
1217 return -log10(bin_tail) - logNT;
1336static double inter_low(
double x,
double x1,
double y1,
double x2,
double y2)
1339 if( x1 > x2 || x < x1 || x > x2 )
1340 error(
"inter_low: unsuitable input, 'x1>x2' or 'x<x1' or 'x>x2'.");
1345 return y1 + (
x-x1) * (y2-y1) / (x2-x1);
1358static double inter_hi(
double x,
double x1,
double y1,
double x2,
double y2)
1361 if( x1 > x2 || x < x1 || x > x2 )
1362 error(
"inter_hi: unsuitable input, 'x1>x2' or 'x<x1' or 'x>x2'.");
1367 return y1 + (
x-x1) * (y2-y1) / (x2-x1);
1392 return (
double)(
i->x) >
i->vx[2];
1412 while( (
double) (
i->y) >
i->ye && !
ri_end(
i) )
1435 if( (
double)
i->x <
i->vx[3] )
1455 if( (
double)
i->x <
i->vx[1] )
1456 i->ye =
inter_hi((
double)
i->x,
i->vx[0],
i->vy[0],
i->vx[1],
i->vy[1]);
1458 i->ye =
inter_hi((
double)
i->x,
i->vx[1],
i->vy[1],
i->vx[2],
i->vy[2]);
1461 i->y = (int) ceil(
i->ys);
1485 vx[0] =
r->x1 -
r->dy *
r->width / 2.0;
1486 vy[0] =
r->y1 +
r->dx *
r->width / 2.0;
1487 vx[1] =
r->x2 -
r->dy *
r->width / 2.0;
1488 vy[1] =
r->y2 +
r->dx *
r->width / 2.0;
1489 vx[2] =
r->x2 +
r->dy *
r->width / 2.0;
1490 vy[2] =
r->y2 -
r->dx *
r->width / 2.0;
1491 vx[3] =
r->x1 +
r->dy *
r->width / 2.0;
1492 vy[3] =
r->y1 -
r->dx *
r->width / 2.0;
1500 if(
r->x1 <
r->x2 &&
r->y1 <=
r->y2 ) offset = 0;
1501 else if(
r->x1 >=
r->x2 &&
r->y1 <
r->y2 ) offset = 1;
1502 else if(
r->x1 >
r->x2 &&
r->y1 >=
r->y2 ) offset = 2;
1508 i->vx[
n] = vx[(offset+
n)%4];
1509 i->vy[
n] = vy[(offset+
n)%4];
1528 i->x = (int) ceil(
i->vx[0]) - 1;
1529 i->y = (int) ceil(
i->vy[0]);
1530 i->ys =
i->ye = -DBL_MAX;
1553 if(
i->x >= 0 &&
i->y >= 0 &&
1554 i->x < (
int) angles->
xsize &&
i->y < (int) angles->
ysize )
1562 return nfa(pts,alg,rec->
p,logNT);
1630 double lambda,theta,
weight;
1638 if( reg_size <= 1 )
error(
"get_theta: region size <= 1.");
1640 error(
"get_theta: invalid 'modgrad'.");
1641 if( prec < 0.0 )
error(
"get_theta: 'prec' must be positive.");
1644 for(
i=0;
i<reg_size;
i++)
1652 error(
"get_theta: null inertia matrix.");
1655 lambda = 0.5 * ( Ixx + Iyy - sqrt( (Ixx-Iyy)*(Ixx-Iyy) + 4.0*Ixy*Ixy ) );
1658 theta = fabs(Ixx)>fabs(Iyy) ? atan2(lambda-Ixx,Ixy) : atan2(Ixy,lambda-Iyy);
1672 double prec,
double p,
struct rect * rec )
1674 double x,y,dx,dy,l,w,theta,
weight,sum,l_min,l_max,w_min,w_max;
1679 if( reg_size <= 1 )
error(
"region2rect: region size <= 1.");
1681 error(
"region2rect: invalid image 'modgrad'.");
1695 for(
i=0;
i<reg_size;
i++)
1702 if( sum <= 0.0 )
error(
"region2rect: weights sum equal to zero.");
1707 theta =
get_theta(reg,reg_size,
x,y,modgrad,reg_angle,prec);
1723 l_min = l_max = w_min = w_max = 0.0;
1724 for(
i=0;
i<reg_size;
i++)
1729 if( l > l_max ) l_max = l;
1730 if( l < l_min ) l_min = l;
1731 if( w > w_max ) w_max = w;
1732 if( w < w_min ) w_min = w;
1736 rec->
x1 =
x + l_min * dx;
1737 rec->
y1 = y + l_min * dy;
1738 rec->
x2 =
x + l_max * dx;
1739 rec->
y2 = y + l_max * dy;
1740 rec->
width = w_max - w_min;
1764 int * reg_size,
double * reg_angle,
image_char used,
1771 if(
x < 0 || y < 0 || x >= (
int) angles->
xsize || y >= (
int) angles->
ysize )
1772 error(
"region_grow: (x,y) out of the image.");
1774 error(
"region_grow: invalid image 'angles'.");
1776 if(
IS_NULL_PTR(reg_size) )
error(
"region_grow: invalid pointer 'reg_size'.");
1777 if(
IS_NULL_PTR(reg_angle) )
error(
"region_grow: invalid pointer 'reg_angle'.");
1779 error(
"region_grow: invalid image 'used'.");
1785 *reg_angle = angles->
data[
x+y*angles->
xsize];
1786 sumdx = cos(*reg_angle);
1787 sumdy = sin(*reg_angle);
1791 for(
i=0;
i<*reg_size;
i++)
1792 for(xx=reg[
i].
x-1; xx<=reg[
i].
x+1; xx++)
1793 for(yy=reg[
i].y-1; yy<=reg[
i].
y+1; yy++)
1794 if( xx>=0 && yy>=0 && xx<(
int)used->
xsize && yy<(
int)used->
ysize &&
1796 isaligned(xx,yy,angles,*reg_angle,prec) )
1800 reg[*reg_size].
x = xx;
1801 reg[*reg_size].
y = yy;
1805 sumdx += cos( angles->
data[xx+yy*angles->
xsize] );
1806 sumdy += sin( angles->
data[xx+yy*angles->
xsize] );
1807 *reg_angle = atan2(sumdy,sumdx);
1816 double logNT,
double log_eps )
1819 double log_nfa,log_nfa_new;
1821 double delta_2 =
delta / 2.0;
1824 log_nfa =
rect_nfa(rec,angles,logNT);
1826 if( log_nfa > log_eps )
return log_nfa;
1834 log_nfa_new =
rect_nfa(&
r,angles,logNT);
1835 if( log_nfa_new > log_nfa )
1837 log_nfa = log_nfa_new;
1842 if( log_nfa > log_eps )
return log_nfa;
1848 if( (
r.width -
delta) >= 0.5 )
1851 log_nfa_new =
rect_nfa(&
r,angles,logNT);
1852 if( log_nfa_new > log_nfa )
1855 log_nfa = log_nfa_new;
1860 if( log_nfa > log_eps )
return log_nfa;
1866 if( (
r.width -
delta) >= 0.5 )
1868 r.x1 += -
r.dy * delta_2;
1869 r.y1 +=
r.dx * delta_2;
1870 r.x2 += -
r.dy * delta_2;
1871 r.y2 +=
r.dx * delta_2;
1873 log_nfa_new =
rect_nfa(&
r,angles,logNT);
1874 if( log_nfa_new > log_nfa )
1877 log_nfa = log_nfa_new;
1882 if( log_nfa > log_eps )
return log_nfa;
1888 if( (
r.width -
delta) >= 0.5 )
1890 r.x1 -= -
r.dy * delta_2;
1891 r.y1 -=
r.dx * delta_2;
1892 r.x2 -= -
r.dy * delta_2;
1893 r.y2 -=
r.dx * delta_2;
1895 log_nfa_new =
rect_nfa(&
r,angles,logNT);
1896 if( log_nfa_new > log_nfa )
1899 log_nfa = log_nfa_new;
1904 if( log_nfa > log_eps )
return log_nfa;
1912 log_nfa_new =
rect_nfa(&
r,angles,logNT);
1913 if( log_nfa_new > log_nfa )
1915 log_nfa = log_nfa_new;
1930 double prec,
double p,
struct rect * rec,
1934 double density,radius1,radius2,rad,xc,yc;
1938 if(
IS_NULL_PTR(reg) )
error(
"reduce_region_radius: invalid pointer 'reg'.");
1940 error(
"reduce_region_radius: invalid pointer 'reg_size'.");
1941 if(
prec < 0.0 )
error(
"reduce_region_radius: 'prec' must be positive.");
1942 if(
IS_NULL_PTR(rec) )
error(
"reduce_region_radius: invalid pointer 'rec'.");
1944 error(
"reduce_region_radius: invalid image 'used'.");
1946 error(
"reduce_region_radius: invalid image 'angles'.");
1949 density = (
double) *reg_size /
1953 if( density >= density_th )
return TRUE;
1958 radius1 =
dist( xc, yc, rec->
x1, rec->
y1 );
1959 radius2 =
dist( xc, yc, rec->
x2, rec->
y2 );
1960 rad = radius1 > radius2 ? radius1 : radius2;
1963 while( density < density_th )
1968 for(
i=0;
i<*reg_size;
i++)
1969 if(
dist( xc, yc, (
double) reg[
i].
x, (
double) reg[
i].
y ) > rad )
1974 reg[
i].
x = reg[*reg_size-1].
x;
1975 reg[
i].
y = reg[*reg_size-1].
y;
1982 if( *reg_size < 2 )
return FALSE;
1988 density = (
double) *reg_size /
2007 double reg_angle,
double prec,
double p,
struct rect * rec,
2010 double angle,ang_d,mean_angle,tau,density,xc,yc,ang_c,sum,s_sum;
2016 if(
prec < 0.0 )
error(
"refine: 'prec' must be positive.");
2019 error(
"refine: invalid image 'used'.");
2021 error(
"refine: invalid image 'angles'.");
2024 density = (
double) *reg_size /
2028 if( density >= density_th )
return TRUE;
2035 ang_c = angles->
data[ reg[0].
x + reg[0].
y * angles->
xsize ];
2038 for(
i=0;
i<*reg_size;
i++)
2043 angle = angles->
data[ reg[
i].
x + reg[
i].
y * angles->
xsize ];
2046 s_sum += ang_d * ang_d;
2054 mean_angle = sum / (
double)
n;
2055 tau = 2.0 * sqrt( (s_sum - 2.0 * mean_angle * sum) / (
double)
n
2056 + mean_angle*mean_angle );
2059 region_grow(reg[0].
x,reg[0].
y,angles,reg,reg_size,®_angle,used,tau);
2062 if( *reg_size < 2 )
return FALSE;
2068 density = (
double) *reg_size /
2072 if( density < density_th )
2074 rec, used, angles, density_th );
2089 double * img,
int X,
int Y,
2090 double scale,
double sigma_scale,
double quant,
2091 double ang_th,
double log_eps,
double density_th,
2093 int ** reg_img,
int * reg_x,
int * reg_y )
2097 double * return_value;
2105 int reg_size,min_reg_size,
i;
2106 unsigned int xsize,ysize;
2107 double rho,reg_angle,prec,
p,log_nfa,logNT;
2113 if( scale <= 0.0 )
error(
"'scale' value must be positive.");
2114 if( sigma_scale <= 0.0 )
error(
"'sigma_scale' value must be positive.");
2115 if( quant < 0.0 )
error(
"'quant' value must be positive.");
2116 if( ang_th <= 0.0 || ang_th >= 180.0 )
2117 error(
"'ang_th' value must be in the range (0,180).");
2118 if( density_th < 0.0 || density_th > 1.0 )
2119 error(
"'density_th' value must be in the range [0,1].");
2120 if( n_bins <= 0 )
error(
"'n_bins' value must be positive.");
2124 prec =
M_PI * ang_th / 180.0;
2126 rho = quant / sin(prec);
2134 angles =
ll_angle( scaled_image, rho, &list_p, &mem_p,
2135 &modgrad, (
unsigned int) n_bins );
2139 angles =
ll_angle( image, rho, &list_p, &mem_p, &modgrad,
2140 (
unsigned int) n_bins );
2141 xsize = angles->
xsize;
2142 ysize = angles->
ysize;
2157 logNT = 5.0 * ( log10( (
double) xsize ) + log10( (
double) ysize ) ) / 2.0
2159 min_reg_size = (int) (-logNT/log10(
p));
2167 reg = (
struct point *) calloc( (
size_t) (xsize*ysize),
sizeof(
struct point) );
2180 ®_angle, used, prec );
2183 if( reg_size < min_reg_size )
continue;
2186 region2rect(reg,reg_size,modgrad,reg_angle,prec,
p,&rec);
2197 if( !
refine( reg, ®_size, modgrad, reg_angle,
2198 prec,
p, &rec, used, angles, density_th ) )
continue;
2202 if( log_nfa <= log_eps )
continue;
2212 rec.
x1 += 0.5; rec.
y1 += 0.5;
2213 rec.
x2 += 0.5; rec.
y2 += 0.5;
2218 rec.
x1 /= scale; rec.
y1 /= scale;
2219 rec.
x2 /= scale; rec.
y2 /= scale;
2225 rec.
width, rec.
p, log_nfa );
2229 for(
i=0;
i<reg_size;
i++)
2230 region->
data[ reg[
i].
x + reg[
i].
y * region->
xsize ] = ls_count;
2248 *reg_img = region->
data;
2249 if( region->
xsize > (
unsigned int) INT_MAX ||
2250 region->
ysize > (
unsigned int) INT_MAX )
2251 error(
"region image to big to fit in INT sizes.");
2252 *reg_x = (int) (region->
xsize);
2253 *reg_y = (int) (region->
ysize);
2260 if(
out->size > (
unsigned int) INT_MAX )
2261 error(
"too many detections to fit in an INT.");
2262 *n_out = (int) (
out->size);
2264 return_value =
out->values;
2269 return return_value;
2275static double * lsd_scale_region(
int * n_out,
2276 double * img,
int X,
int Y,
double scale,
2277 int ** reg_img,
int * reg_x,
int * reg_y )
2280 double sigma_scale = 0.6;
2284 double ang_th = 22.5;
2285 double log_eps = 0.0;
2286 double density_th = 0.7;
2291 ang_th, log_eps, density_th, n_bins,
2292 reg_img, reg_x, reg_y );
2298static double * lsd_scale(
int * n_out,
double * img,
int X,
int Y,
double scale)
2300 return lsd_scale_region(n_out,img,X,Y,scale,NULL,NULL,NULL);
2306static double * lsd(
int * n_out,
double * img,
int X,
int Y)
2311 return lsd_scale(n_out,img,X,Y,scale);
2324#undef RELATIVE_ERROR_FACTOR
static image_int new_image_int(unsigned int xsize, unsigned int ysize)
static ntuple_list new_ntuple_list(unsigned int dim)
static void region2rect(struct point *reg, int reg_size, image_double modgrad, double reg_angle, double prec, double p, struct rect *rec)
static double get_theta(struct point *reg, int reg_size, double x, double y, image_double modgrad, double reg_angle, double prec)
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)
static double dist(double x1, double y1, double x2, double y2)
static void enlarge_ntuple_list(ntuple_list n_tuple)
static int ri_end(rect_iter *i)
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)
static void free_ntuple_list(ntuple_list in)
static image_double ll_angle(image_double in, double threshold, struct coorlist **list_p, void **mem_p, image_double *modgrad, unsigned int n_bins)
struct image_double_s * image_double
static double angle_diff(double a, double b)
static double log_gamma_windschitl(double x)
static image_double gaussian_sampler(image_double in, double scale, double sigma_scale)
static image_char new_image_char(unsigned int xsize, unsigned int ysize)
#define RELATIVE_ERROR_FACTOR
static rect_iter * ri_ini(struct rect *r)
static image_int new_image_int_ini(unsigned int xsize, unsigned int ysize, int fill_value)
static double rect_improve(struct rect *rec, image_double angles, double logNT, double log_eps)
static void add_7tuple(ntuple_list out, double v1, double v2, double v3, double v4, double v5, double v6, double v7)
static image_double new_image_double(unsigned int xsize, unsigned int ysize)
static void gaussian_kernel(ntuple_list kernel, double sigma, double mean)
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)
static void rect_copy(struct rect *in, struct rect *out)
static double rect_nfa(struct rect *rec, image_double angles, double logNT)
static double nfa(int n, int k, double p, double logNT)
static void error(char *msg)
static image_char new_image_char_ini(unsigned int xsize, unsigned int ysize, unsigned char fill_value)
static void ri_del(rect_iter *iter)
static void free_image_char(image_char i)
static double inter_hi(double x, double x1, double y1, double x2, double y2)
static double angle_diff_signed(double a, double b)
static image_double new_image_double_ptr(unsigned int xsize, unsigned int ysize, double *data)
static double inter_low(double x, double x1, double y1, double x2, double y2)
struct image_char_s * image_char
static double log_gamma_lanczos(double x)
static void free_image_double(image_double i)
static int double_equal(double a, double b)
static int isaligned(int x, int y, image_double angles, double theta, double prec)
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)
static void ri_inc(rect_iter *i)
const dt_colormatrix_t dt_aligned_pixel_t out
static const dt_colormatrix_t M
static void weight(const float *c1, const float *c2, const float sharpen, dt_aligned_pixel_t weight)
static float kernel(const float *x, const float *y)
float *const restrict const size_t k
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
typedef double((*spd)(unsigned long int wavelength, double TempK))