33 #include <vigra/copyimage.hxx>
34 #include <vigra/pixelneighborhood.hxx>
45 vigra::BImage edge(input.width(), input.height(),
N8_bg);
46 vigra::BImage
line(input.size());
48 vigra::copyImage(input.upperLeft() + vigra::Diff2D(1, 1), input.lowerRight() - vigra::Diff2D(1, 1), input.accessor(), edge.upperLeft(), edge.accessor());
50 int width = input.width(),
51 height = input.height();
53 vigra::BImage::traverser eul, lul;
61 eul = edge.upperLeft() + vigra::Diff2D(1, 1);
62 for(
int y=1; y<height-1; ++y, ++eul.y )
64 vigra::BImage::traverser ix = eul;
65 for(
int x=1; x<width-1; ++x, ++ix.x )
71 int nh = 0, nv = 0, nu = 0, nd = 0;
72 if( ix( 1, 0 ) !=
N8_bg ) ++nh, ++n;
73 if( ix( 1, -1 ) !=
N8_bg ) ++nu, ++n;
74 if( ix( 0, -1 ) !=
N8_bg ) ++nv, ++n;
75 if( ix( -1, -1 ) !=
N8_bg ) ++nd, ++n;
76 if( ix( -1, 0 ) !=
N8_bg ) ++nh, ++n;
77 if( ix( -1, 1 ) !=
N8_bg ) ++nu, ++n;
78 if( ix( 0, 1 ) !=
N8_bg ) ++nv, ++n;
79 if( ix( 1, 1 ) !=
N8_bg ) ++nd, ++n;
81 if( nh == 1 && nv == 1 && n > 1 && n < 5 )
98 eul = (edge.upperLeft() + vigra::Diff2D(1, 1));
99 lul = (
line.upperLeft() + vigra::Diff2D(1, 1));
102 for(
int y=1; y<height-1; ++y, ++eul.y, ++lul.y)
104 vigra::BImage::traverser ix = eul;
105 vigra::BImage::traverser ox = lul;
106 for(
int x=1; x<width-1; ++x, ++ix.x, ++ox.x)
111 int nh = 0, nv = 0, nu = 0, nd = 0;
113 if( ix( 1, 0 ) !=
N8_bg ) ++nh, ++n;
114 if( ix( 1, -1 ) !=
N8_bg ) ++nu, ++n;
115 if( ix( 0, -1 ) !=
N8_bg ) ++nv, ++n;
116 if( ix( -1, -1 ) !=
N8_bg ) ++nd, ++n;
117 if( ix( -1, 0 ) !=
N8_bg ) ++nh, ++n;
118 if( ix( -1, 1 ) !=
N8_bg ) ++nu, ++n;
119 if( ix( 0, 1 ) !=
N8_bg ) ++nv, ++n;
120 if( ix( 1, 1 ) !=
N8_bg ) ++nd, ++n;
127 else if( nu ) code = 3;
128 else if( nv ) code = 5;
134 if( nh == 2 ) code = 1;
135 else if( nu == 2 ) code = 3;
136 else if( nv == 2 ) code = 5;
137 else if( nd == 2 ) code = 7;
138 else if( nh && nu ) code = 2;
139 else if( nh && nd ) code = 8;
140 else if( nv && nu ) code = 4;
141 else if( nv && nd ) code = 6;
144 *ox = code ? code :
N8_bg;
153 lul = (
line.upperLeft() + vigra::Diff2D(1, 1));
155 for(
int y=1; y<height-1; ++y, ++lul.y)
157 vigra::BImage::traverser ix = lul;
158 for(
int x=1; x<width-1; ++x, ++ix.x )
163 assert( c > 0 && c < 9 );
164 int n = 0, omin = 9, omax = 0;
165 vigra::NeighborhoodCirculator<vigra::BImage::traverser, vigra::EightNeighborCode>
169 int nc = *circulator;
172 assert( nc > 0 && nc < 9 );
173 if( nc < omin ) omin = nc;
174 if( nc > omax ) omax = nc;
177 }
while(++circulator != end);
195 lul = (
line.upperLeft() + vigra::Diff2D(1, 1));
197 for(
int y=1; y<height-1; ++y, ++lul.y)
199 vigra::BImage::traverser ix = lul;
200 for(
int x=1; x<width-1; ++x, ++ix.x )
206 vigra::NeighborhoodCirculator<vigra::BImage::traverser, vigra::EightNeighborCode> circulator(ix);
207 vigra::NeighborhoodCirculator<vigra::BImage::traverser, vigra::EightNeighborCode> end(circulator);
209 int nc = *circulator;
214 }
while(++circulator != end);
216 if( n == 0 ) *ix =
N8_bg;
217 else if( n == 1 ) *ix = 1;
227 lul = (
line.upperLeft() + vigra::Diff2D(1, 1));
228 eul = (edge.upperLeft() + vigra::Diff2D(1, 1));
231 for(
int y=1; y<height-1; ++y, ++lul.y, ++eul.y )
233 vigra::BImage::traverser ox = eul;
234 vigra::BImage::traverser ix = lul;
235 for(
int x=1; x<width-1; ++x, ++ix.x, ++ox.x )
241 vigra::NeighborhoodCirculator<vigra::BImage::traverser, vigra::EightNeighborCode> circulator(ix);
242 vigra::NeighborhoodCirculator<vigra::BImage::traverser, vigra::EightNeighborCode> end(circulator);
244 int nc = *circulator;
248 if( c == 1 && nc == 1 ) c = 0;
250 }
while(++circulator != end);
273 dx = abs(dx); dy = abs(dy);
280 register float x = dx, y = dy;
281 return sqrt( x*x + y*y );
287 inline float scurv(vigra::Point2D & l, vigra::Point2D & m, vigra::Point2D & r)
289 return float(m.x - l.x) * float(r.y - l.y)
290 + float(m.y - l.y) * float(l.x - r.x );
296 inline void vcurv(vigra::Point2D & l, vigra::Point2D & m, vigra::Point2D & r,
float & vx,
float & vy)
298 vx = 0.5 * (l.x + r.x) -
float( m.x );
299 vy = 0.5 * (l.y + r.y) -
float( m.y );
319 double xcen,
double ycen
323 const double crcmin = 0.20;
325 const double cvrmax = 3.0;
327 double r90 = 1.57 * flpix;
329 int n = (int)pts.size();
335 double x0 = pts.at(0).x,
337 double dx = pts.at(n-1).x - x0,
338 dy = pts.at(n-1).y - y0;
339 double chord = sqrt( dx*dx + dy*dy );
340 if( chord < 0.6 * n )
343 double ccx = x0 + 0.5 * dx - xcen,
344 ccy = y0 + 0.5 * dy - ycen;
347 double acx = pts.at(n/2).x - xcen,
348 acy = pts.at(n/2).y - ycen;
349 double acd = sqrt( acx*acx + acy*acy );
351 double cvx = acx - ccx,
353 double cvd = sqrt( cvx*cvx + cvy*cvy );
355 double cosrc = fabs( acx * dy - acy * dx ) / (chord * acd);
356 if( fabs(cosrc) < crcmin )
361 double S = 1.2 * chord * cosrc / r90;
362 double C = r90 * (1 - sqrt( 1 - S * S ));
364 if( cvd / C > cvrmax )
397 int nadd = 0, nrejL = 0;
399 static vigra::Diff2D offs[8] = {
401 vigra::Diff2D(1, -1),
402 vigra::Diff2D(0, -1),
403 vigra::Diff2D(-1, -1),
404 vigra::Diff2D(-1, 0),
405 vigra::Diff2D(-1, 1),
412 const float maxacd = 2.0f;
414 if(minsize < span) minsize = span;
416 int width = img.width(),
417 height = img.height();
418 double xcen = 0.5 * width,
422 vigra::BImage::traverser ul(img.upperLeft() + vigra::Diff2D(1, 1));
423 for(
int y=1; y<height-1; ++y, ++ul.y)
425 vigra::BImage::traverser ix = ul;
426 for(
int x=1; x<width-1; ++x, ++ix.x )
432 vigra::BImage::traverser tr = ix;
433 vigra::Point2D pos(x, y);
434 std::vector<vigra::Point2D> pts;
440 for( dir = 0; dir < 8; dir++ )
443 if( tr[dif] !=
N8_bg )
break;
453 if( pts.size() < minsize )
460 int ncopy = 0, nskip = 0;
466 int ip = 0, np = (int)pts.size();
468 std::vector<vigra::Point2D> tmp;
470 int isql = 0, isqr = 0;
471 int xl = pts.at( 0 ).x,
473 float dx = pts.at(span-1).x - xl,
474 dy = pts.at(span-1).y - yl;
475 float Chord = sqrt(dx*dx + dy*dy);
478 for( isqr = 0; isqr < span-1; isqr++ )
480 register int x = pts.at( isqr + 1).x,
481 y = pts.at( isqr + 1 ).y;
482 float d =
ccdist( x - xl, y - yl );
488 if( Arc - Chord <= maxacd )
490 for(
int i = 0; i < span; i++ )
492 tmp.push_back(vigra::Point2D(pts.at(i).x, pts.at(i).y));
497 for( ip = 1; ip < np - span; ip++ )
499 int irgt = ip + span - 1;
502 isql = (isql + 1) & 31;
503 isqr = (isqr + 1) & 31;
504 int x = pts.at( irgt ).x,
505 y = pts.at( irgt ).y;
506 float d =
ccdist( x - xl, y - yl );
510 dx = x - pts.at(ip).x; dy = y - pts.at(ip).y;
511 Chord = sqrt( dx*dx + dy*dy );
515 if( Arc - Chord <= maxacd )
518 tmp.push_back(vigra::Point2D(pts.at(irgt).x, pts.at(irgt).y));
522 int q =
lineFilter( tmp, minsize, flpix, xcen, ycen );
533 lines.push_back(line);
539 int q =
lineFilter( tmp, minsize, flpix, xcen, ycen );
550 lines.push_back(line);
557 lines.push_back(line);
std::vector< vigra::Point2D > line
a single line extracted from image
declaration of find lines algorithm
float ccdist(int dx, int dy)
static int lineFilter(std::vector< vigra::Point2D > &pts, int lmin, double flpix, double xcen, double ycen)
float scurv(vigra::Point2D &l, vigra::Point2D &m, vigra::Point2D &r)
std::vector< SingleLine > Lines
vector of extracted lines from image
void copyImage(SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor src_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc)
void vcurv(vigra::Point2D &l, vigra::Point2D &m, vigra::Point2D &r, float &vx, float &vy)
float eudist(int dx, int dy)
int linePts2lineList(vigra::BImage &img, int minsize, double flpix, Lines &lines)
converts a linePts image to a list of lines
vigra::BImage edgeMap2linePts(vigra::BImage &input)
marks line point