find_line_segment initial speedup

This commit is contained in:
Larry Bank 2020-01-14 19:43:25 +01:00
parent 3b5b4eb4a0
commit 49ba439610

View File

@ -445,13 +445,14 @@ float * lsd(int * n_out, unsigned char * img, int X, int Y);
#endif /* !TRUE */ #endif /* !TRUE */
/** Label for pixels with undefined gradient. */ /** Label for pixels with undefined gradient. */
#define NOTDEF -512.0 // -1024.0 #define NOTDEF -512.0f // -1024.0f
#define NOTDEF_INT -29335
/** 3/2 pi */ /** 3/2 pi */
#define M_3_2_PI 4.71238898038 #define M_3_2_PI 4.71238898038f
/** 2 pi */ /** 2 pi */
#define M_2__PI 6.28318530718 #define M_2__PI 6.28318530718f
/** Label for pixels not used in yet. */ /** Label for pixels not used in yet. */
#define NOTUSED 0 #define NOTUSED 0
@ -1190,7 +1191,7 @@ static image_int ll_angle( image_char in, float threshold,
(*modgrad)->data[adr] = norm; /* store gradient norm */ (*modgrad)->data[adr] = norm; /* store gradient norm */
if( norm <= threshold ) /* norm too small, gradient no defined */ if( norm <= threshold ) /* norm too small, gradient no defined */
g->data[adr] = radToDeg(NOTDEF); /* gradient angle not defined */ g->data[adr] = NOTDEF_INT; //radToDeg(NOTDEF); /* gradient angle not defined */
else else
{ {
/* gradient angle computation */ /* gradient angle computation */
@ -1287,6 +1288,36 @@ static int isaligned( int x, int y, image_int angles, float theta,
return theta <= prec; return theta <= prec;
} }
static int isaligned_fast(int angle, float theta,
float prec )
{
float a;
if (angle == NOTDEF_INT) return FALSE;
/* angle at pixel (x,y) */
a = degToRad(angle);
/* pixels whose level-line angle is not defined
are considered as NON-aligned */
// if( a == NOTDEF ) return FALSE; /* there is no need to call the function
// 'double_equal' here because there is
// no risk of problems related to the
// comparison doubles, we are only
// interested in the exact NOTDEF value */
/* it is assumed that 'theta' and 'a' are in the range [-pi,pi] */
theta -= a;
if( theta < 0.0 ) theta = -theta;
if( theta > M_3_2_PI )
{
theta -= M_2__PI;
if( theta < 0.0 ) theta = -theta;
}
return theta <= prec;
} /* isaligned_fast() */
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/** Absolute value angle difference. /** Absolute value angle difference.
*/ */
@ -1864,7 +1895,7 @@ static float rect_nfa(struct rect * rec, image_int angles, float logNT)
i->x < (int) angles->xsize && i->y < (int) angles->ysize ) i->x < (int) angles->xsize && i->y < (int) angles->ysize )
{ {
++pts; /* total number of pixels counter */ ++pts; /* total number of pixels counter */
if( isaligned(i->x, i->y, angles, rec->theta, rec->prec) ) if( isaligned_fast((float)angles->data[(i->y*angles->xsize)+i->x], rec->theta, rec->prec) )
++alg; /* aligned points counter */ ++alg; /* aligned points counter */
} }
ri_del(i); /* delete iterator */ ri_del(i); /* delete iterator */
@ -2076,7 +2107,9 @@ static void region_grow( int x, int y, image_int angles, struct lsd_point * reg,
{ {
float sumdx,sumdy; float sumdx,sumdy;
int xx,yy,i; int xx,yy,i;
int l_size; // local copy
float l_angle; // local copy
int xsize = used->xsize;
/* check parameters */ /* check parameters */
if( x < 0 || y < 0 || x >= (int) angles->xsize || y >= (int) angles->ysize ) if( x < 0 || y < 0 || x >= (int) angles->xsize || y >= (int) angles->ysize )
error("region_grow: (x,y) out of the image."); error("region_grow: (x,y) out of the image.");
@ -2089,35 +2122,50 @@ static void region_grow( int x, int y, image_int angles, struct lsd_point * reg,
error("region_grow: invalid image 'used'."); error("region_grow: invalid image 'used'.");
/* first point of the region */ /* first point of the region */
*reg_size = 1; l_size = 1;
reg[0].x = x; reg[0].x = x;
reg[0].y = y; reg[0].y = y;
*reg_angle = degToRad(angles->data[x+y*angles->xsize]); /* region's angle */ l_angle = degToRad(angles->data[x+y*angles->xsize]); /* region's angle */
sumdx = cos(*reg_angle); sumdx = cos(l_angle);
sumdy = sin(*reg_angle); sumdy = sin(l_angle);
used->data[x+y*used->xsize] = USED; used->data[x+y*used->xsize] = USED;
/* try neighbors as new region points */ /* try neighbors as new region points */
for(i=0; i<*reg_size; i++) for(i=0; i<l_size; i++) {
for(xx=reg[i].x-1; xx<=reg[i].x+1; xx++) int dx=3, dy=3; // assume 3x3 region to try
for(yy=reg[i].y-1; yy<=reg[i].y+1; yy++) int ty = reg[i].y-1;
if( xx>=0 && yy>=0 && xx<(int)used->xsize && yy<(int)used->ysize && int tx = reg[i].x-1;
used->data[xx+yy*used->xsize] != USED && if (tx < 0) {
isaligned(xx,yy,angles,*reg_angle,prec) ) tx = 0; dx--;
} else if (tx+dx >= xsize) {
dx--;
}
if (ty < 0) {
ty = 0; dy--;
} else if (ty+dy >= used->ysize) {
dy--;
}
for(xx=tx; xx<tx+dx; xx++)
for(yy=ty; yy<ty+dy; yy++)
if( used->data[xx+yy*xsize] != USED &&
isaligned_fast((float)angles->data[(yy*xsize)+xx],l_angle,prec) )
{ {
/* add point */ /* add point */
used->data[xx+yy*used->xsize] = USED; used->data[xx+yy*xsize] = USED;
reg[*reg_size].x = xx; reg[l_size].x = xx;
reg[*reg_size].y = yy; reg[l_size].y = yy;
++(*reg_size); ++l_size;
/* update region's angle */ /* update region's angle */
int16_t angle = angles->data[xx+yy*angles->xsize] % 360; int16_t angle = angles->data[xx+yy*xsize] % 360;
if (angle < 0) angle += 360; if (angle < 0) angle += 360;
sumdx += cos_table[angle]; sumdx += cos_table[angle];
sumdy += sin_table[angle]; sumdy += sin_table[angle];
*reg_angle = atan2(sumdy,sumdx); l_angle = atan2(sumdy,sumdx);
} }
}
*reg_size = l_size;
*reg_angle = l_angle;
} }
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
@ -2479,7 +2527,8 @@ float * LineSegmentDetection( int * n_out,
/* search for line segments */ /* search for line segments */
for(; list_p != NULL; list_p = list_p->next ) for(; list_p != NULL; list_p = list_p->next )
if( used->data[ list_p->x + list_p->y * used->xsize ] == NOTUSED && if( used->data[ list_p->x + list_p->y * used->xsize ] == NOTUSED &&
degToRad(angles->data[ list_p->x + list_p->y * angles->xsize ]) != NOTDEF ) angles->data[ list_p->x + list_p->y * angles->xsize ] != NOTDEF_INT )
// degToRad(angles->data[ list_p->x + list_p->y * angles->xsize ]) != NOTDEF )
/* there is no risk of float comparison problems here /* there is no risk of float comparison problems here
because we are only interested in the exact NOTDEF value */ because we are only interested in the exact NOTDEF value */
{ {