37 #ifndef VIGRA_EDGEDETECTION_HXX
38 #define VIGRA_EDGEDETECTION_HXX
43 #include "utilities.hxx"
44 #include "numerictraits.hxx"
45 #include "stdimage.hxx"
46 #include "stdimagefunctions.hxx"
47 #include "recursiveconvolution.hxx"
48 #include "separableconvolution.hxx"
49 #include "convolution.hxx"
50 #include "labelimage.hxx"
51 #include "mathutil.hxx"
52 #include "pixelneighborhood.hxx"
53 #include "linear_solve.hxx"
54 #include "functorexpression.hxx"
182 template <
class SrcIterator,
class SrcAccessor,
183 class DestIterator,
class DestAccessor,
184 class GradValue,
class DestValue>
186 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
187 DestIterator dul, DestAccessor da,
188 double scale, GradValue gradient_threshold, DestValue edge_marker)
190 vigra_precondition(scale > 0,
191 "differenceOfExponentialEdgeImage(): scale > 0 required.");
193 vigra_precondition(gradient_threshold > 0,
194 "differenceOfExponentialEdgeImage(): "
195 "gradient_threshold > 0 required.");
197 int w = slr.x - sul.x;
198 int h = slr.y - sul.y;
202 NumericTraits<typename SrcAccessor::value_type>::RealPromote
204 typedef BasicImage<TMPTYPE> TMPIMG;
215 typename TMPIMG::Iterator iy = smooth.upperLeft();
216 typename TMPIMG::Iterator ty = tmp.upperLeft();
217 DestIterator dy = dul;
219 static const Diff2D right(1, 0);
220 static const Diff2D bottom(0, 1);
223 TMPTYPE thresh = detail::RequiresExplicitCast<TMPTYPE>::cast((gradient_threshold * gradient_threshold) *
224 NumericTraits<TMPTYPE>::one());
225 TMPTYPE zero = NumericTraits<TMPTYPE>::zero();
227 for(y=0; y<h-1; ++y, ++iy.y, ++ty.y, ++dy.y)
229 typename TMPIMG::Iterator ix = iy;
230 typename TMPIMG::Iterator tx = ty;
231 DestIterator dx = dy;
233 for(x=0; x<w-1; ++x, ++ix.x, ++tx.x, ++dx.x)
235 TMPTYPE diff = *tx - *ix;
236 TMPTYPE gx = tx[right] - *tx;
237 TMPTYPE gy = tx[bottom] - *tx;
239 if((gx * gx > thresh) &&
240 (diff * (tx[right] - ix[right]) < zero))
244 da.set(edge_marker, dx, right);
248 da.set(edge_marker, dx);
251 if(((gy * gy > thresh) &&
252 (diff * (tx[bottom] - ix[bottom]) < zero)))
256 da.set(edge_marker, dx, bottom);
260 da.set(edge_marker, dx);
266 typename TMPIMG::Iterator ix = iy;
267 typename TMPIMG::Iterator tx = ty;
268 DestIterator dx = dy;
270 for(x=0; x<w-1; ++x, ++ix.x, ++tx.x, ++dx.x)
272 TMPTYPE diff = *tx - *ix;
273 TMPTYPE gx = tx[right] - *tx;
275 if((gx * gx > thresh) &&
276 (diff * (tx[right] - ix[right]) < zero))
280 da.set(edge_marker, dx, right);
284 da.set(edge_marker, dx);
290 template <
class SrcIterator,
class SrcAccessor,
291 class DestIterator,
class DestAccessor,
295 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
296 DestIterator dul, DestAccessor da,
297 double scale, GradValue gradient_threshold)
300 scale, gradient_threshold, 1);
303 template <
class SrcIterator,
class SrcAccessor,
304 class DestIterator,
class DestAccessor,
305 class GradValue,
class DestValue>
308 triple<SrcIterator, SrcIterator, SrcAccessor> src,
309 pair<DestIterator, DestAccessor> dest,
310 double scale, GradValue gradient_threshold,
311 DestValue edge_marker)
314 dest.first, dest.second,
315 scale, gradient_threshold,
319 template <
class SrcIterator,
class SrcAccessor,
320 class DestIterator,
class DestAccessor,
324 triple<SrcIterator, SrcIterator, SrcAccessor> src,
325 pair<DestIterator, DestAccessor> dest,
326 double scale, GradValue gradient_threshold)
329 dest.first, dest.second,
330 scale, gradient_threshold, 1);
467 template <
class SrcIterator,
class SrcAccessor,
468 class DestIterator,
class DestAccessor,
469 class GradValue,
class DestValue>
471 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
472 DestIterator dul, DestAccessor da,
473 double scale, GradValue gradient_threshold,
474 DestValue edge_marker)
476 vigra_precondition(scale > 0,
477 "differenceOfExponentialCrackEdgeImage(): scale > 0 required.");
479 vigra_precondition(gradient_threshold > 0,
480 "differenceOfExponentialCrackEdgeImage(): "
481 "gradient_threshold > 0 required.");
483 int w = slr.x - sul.x;
484 int h = slr.y - sul.y;
488 NumericTraits<typename SrcAccessor::value_type>::RealPromote
490 typedef BasicImage<TMPTYPE> TMPIMG;
495 TMPTYPE zero = NumericTraits<TMPTYPE>::zero();
497 static const Diff2D right(1,0);
498 static const Diff2D bottom(0,1);
499 static const Diff2D left(-1,0);
500 static const Diff2D top(0,-1);
508 typename TMPIMG::Iterator iy = smooth.upperLeft();
509 typename TMPIMG::Iterator ty = tmp.upperLeft();
510 DestIterator dy = dul;
512 TMPTYPE thresh = detail::RequiresExplicitCast<TMPTYPE>::cast((gradient_threshold * gradient_threshold) *
513 NumericTraits<TMPTYPE>::one());
516 for(y=0; y<h-1; ++y, ++iy.y, ++ty.y, dy.y+=2)
518 typename TMPIMG::Iterator ix = iy;
519 typename TMPIMG::Iterator tx = ty;
520 DestIterator dx = dy;
522 for(
int x=0; x<w-1; ++x, ++ix.x, ++tx.x, dx.x+=2)
524 TMPTYPE diff = *tx - *ix;
525 TMPTYPE gx = tx[right] - *tx;
526 TMPTYPE gy = tx[bottom] - *tx;
528 if((gx * gx > thresh) &&
529 (diff * (tx[right] - ix[right]) < zero))
531 da.set(edge_marker, dx, right);
533 if((gy * gy > thresh) &&
534 (diff * (tx[bottom] - ix[bottom]) < zero))
536 da.set(edge_marker, dx, bottom);
540 TMPTYPE diff = *tx - *ix;
541 TMPTYPE gy = tx[bottom] - *tx;
543 if((gy * gy > thresh) &&
544 (diff * (tx[bottom] - ix[bottom]) < zero))
546 da.set(edge_marker, dx, bottom);
550 typename TMPIMG::Iterator ix = iy;
551 typename TMPIMG::Iterator tx = ty;
552 DestIterator dx = dy;
554 for(x=0; x<w-1; ++x, ++ix.x, ++tx.x, dx.x+=2)
556 TMPTYPE diff = *tx - *ix;
557 TMPTYPE gx = tx[right] - *tx;
559 if((gx * gx > thresh) &&
560 (diff * (tx[right] - ix[right]) < zero))
562 da.set(edge_marker, dx, right);
566 iy = smooth.upperLeft() + Diff2D(0,1);
567 ty = tmp.upperLeft() + Diff2D(0,1);
568 dy = dul + Diff2D(1,2);
570 static const Diff2D topleft(-1,-1);
571 static const Diff2D topright(1,-1);
572 static const Diff2D bottomleft(-1,1);
573 static const Diff2D bottomright(1,1);
576 for(y=0; y<h-2; ++y, ++iy.y, ++ty.y, dy.y+=2)
578 typename TMPIMG::Iterator ix = iy;
579 typename TMPIMG::Iterator tx = ty;
580 DestIterator dx = dy;
582 for(
int x=0; x<w-2; ++x, ++ix.x, ++tx.x, dx.x+=2)
584 if(da(dx) == edge_marker)
continue;
586 TMPTYPE diff = *tx - *ix;
588 if((diff * (tx[right] - ix[right]) < zero) &&
589 (((da(dx, bottomright) == edge_marker) &&
590 (da(dx, topleft) == edge_marker)) ||
591 ((da(dx, bottomleft) == edge_marker) &&
592 (da(dx, topright) == edge_marker))))
595 da.set(edge_marker, dx);
600 iy = smooth.upperLeft() + Diff2D(1,0);
601 ty = tmp.upperLeft() + Diff2D(1,0);
602 dy = dul + Diff2D(2,1);
605 for(y=0; y<h-2; ++y, ++iy.y, ++ty.y, dy.y+=2)
607 typename TMPIMG::Iterator ix = iy;
608 typename TMPIMG::Iterator tx = ty;
609 DestIterator dx = dy;
611 for(
int x=0; x<w-2; ++x, ++ix.x, ++tx.x, dx.x+=2)
613 if(da(dx) == edge_marker)
continue;
615 TMPTYPE diff = *tx - *ix;
617 if((diff * (tx[bottom] - ix[bottom]) < zero) &&
618 (((da(dx, bottomright) == edge_marker) &&
619 (da(dx, topleft) == edge_marker)) ||
620 ((da(dx, bottomleft) == edge_marker) &&
621 (da(dx, topright) == edge_marker))))
624 da.set(edge_marker, dx);
629 dy = dul + Diff2D(1,1);
632 for(y=0; y<h-1; ++y, dy.y+=2)
634 DestIterator dx = dy;
636 for(
int x=0; x<w-1; ++x, dx.x+=2)
638 static const Diff2D dist[] = {right, top, left, bottom };
643 if(da(dx, dist[i]) == edge_marker)
break;
646 if(i < 4) da.set(edge_marker, dx);
651 template <
class SrcIterator,
class SrcAccessor,
652 class DestIterator,
class DestAccessor,
653 class GradValue,
class DestValue>
656 triple<SrcIterator, SrcIterator, SrcAccessor> src,
657 pair<DestIterator, DestAccessor> dest,
658 double scale, GradValue gradient_threshold,
659 DestValue edge_marker)
662 dest.first, dest.second,
663 scale, gradient_threshold,
751 template <
class Iterator,
class Accessor,
class Value>
753 Iterator sul, Iterator slr, Accessor sa,
754 unsigned int min_edge_length, Value non_edge_marker)
756 int w = slr.x - sul.x;
757 int h = slr.y - sul.y;
763 int number_of_regions =
765 destImage(labels),
true, non_edge_marker);
767 ArrayOfRegionStatistics<FindROISize<int> >
768 region_stats(number_of_regions);
775 for(y=0; y<h; ++y, ++oy.y, ++ly.y)
780 for(x=0; x<w; ++x, ++ox.x, ++lx.x)
782 if(sa(ox) == non_edge_marker)
continue;
783 if((region_stats[*lx].count) < min_edge_length)
785 sa.set(non_edge_marker, ox);
791 template <
class Iterator,
class Accessor,
class Value>
794 triple<Iterator, Iterator, Accessor> src,
795 unsigned int min_edge_length, Value non_edge_marker)
798 min_edge_length, non_edge_marker);
887 template <
class SrcIterator,
class SrcAccessor,
class SrcValue>
889 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
890 SrcValue edge_marker)
892 int w = slr.x - sul.x;
893 int h = slr.y - sul.y;
895 vigra_precondition(w % 2 == 1 && h % 2 == 1,
896 "closeGapsInCrackEdgeImage(): Input is not a crack edge image (must have odd-numbered shape).");
898 int w2 = w / 2, h2 = h / 2, x, y;
900 int count1, count2, count3;
902 static const Diff2D right(1,0);
903 static const Diff2D bottom(0,1);
904 static const Diff2D left(-1,0);
905 static const Diff2D top(0,-1);
907 static const Diff2D leftdist[] = {
908 Diff2D(0, 0), Diff2D(-1, 1), Diff2D(-2, 0), Diff2D(-1, -1)};
909 static const Diff2D rightdist[] = {
910 Diff2D(2, 0), Diff2D(1, 1), Diff2D(0, 0), Diff2D(1, -1)};
911 static const Diff2D topdist[] = {
912 Diff2D(1, -1), Diff2D(0, 0), Diff2D(-1, -1), Diff2D(0, -2)};
913 static const Diff2D bottomdist[] = {
914 Diff2D(1, 1), Diff2D(0, 2), Diff2D(-1, 1), Diff2D(0, 0)};
918 SrcIterator sy = sul + Diff2D(0,1);
922 for(y=0; y<h2; ++y, sy.y+=2)
924 sx = sy + Diff2D(2,0);
926 for(x=2; x<w2; ++x, sx.x+=2)
928 if(sa(sx) == edge_marker)
continue;
930 if(sa(sx, left) != edge_marker)
continue;
931 if(sa(sx, right) != edge_marker)
continue;
939 if(sa(sx, leftdist[i]) == edge_marker)
944 if(sa(sx, rightdist[i]) == edge_marker)
951 if(count1 <= 1 || count2 <= 1 || count3 == 15)
953 sa.set(edge_marker, sx);
958 sy = sul + Diff2D(1,2);
961 for(y=2; y<h2; ++y, sy.y+=2)
965 for(x=0; x<w2; ++x, sx.x+=2)
967 if(sa(sx) == edge_marker)
continue;
969 if(sa(sx, top) != edge_marker)
continue;
970 if(sa(sx, bottom) != edge_marker)
continue;
978 if(sa(sx, topdist[i]) == edge_marker)
983 if(sa(sx, bottomdist[i]) == edge_marker)
990 if(count1 <= 1 || count2 <= 1 || count3 == 15)
992 sa.set(edge_marker, sx);
998 template <
class SrcIterator,
class SrcAccessor,
class SrcValue>
1001 triple<SrcIterator, SrcIterator, SrcAccessor> src,
1002 SrcValue edge_marker)
1104 template <
class SrcIterator,
class SrcAccessor,
class SrcValue>
1106 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1107 SrcValue edge_marker, SrcValue background_marker)
1109 int w = slr.x - sul.x;
1110 int h = slr.y - sul.y;
1112 vigra_precondition(w % 2 == 1 && h % 2 == 1,
1113 "beautifyCrackEdgeImage(): Input is not a crack edge image (must have odd-numbered shape).");
1115 int w2 = w / 2, h2 = h / 2, x, y;
1117 SrcIterator sy = sul + Diff2D(1,1);
1120 static const Diff2D right(1,0);
1121 static const Diff2D bottom(0,1);
1122 static const Diff2D left(-1,0);
1123 static const Diff2D top(0,-1);
1126 for(y=0; y<h2; ++y, sy.y+=2)
1130 for(x=0; x<w2; ++x, sx.x+=2)
1132 if(sa(sx) != edge_marker)
continue;
1134 if(sa(sx, right) == edge_marker && sa(sx, left) == edge_marker)
continue;
1135 if(sa(sx, bottom) == edge_marker && sa(sx, top) == edge_marker)
continue;
1137 sa.set(background_marker, sx);
1142 template <
class SrcIterator,
class SrcAccessor,
class SrcValue>
1145 triple<SrcIterator, SrcIterator, SrcAccessor> src,
1146 SrcValue edge_marker, SrcValue background_marker)
1149 edge_marker, background_marker);
1217 template <
class SrcIterator,
class SrcAccessor,
1218 class MagnitudeImage,
class BackInsertable>
1219 void internalCannyFindEdgels(SrcIterator ul, SrcAccessor grad,
1220 MagnitudeImage
const & magnitude,
1221 BackInsertable & edgels)
1223 typedef typename SrcAccessor::value_type PixelType;
1224 typedef typename PixelType::value_type ValueType;
1229 for(
int y=1; y<magnitude.height()-1; ++y, ++ul.y)
1231 SrcIterator ix = ul;
1232 for(
int x=1; x<magnitude.width()-1; ++x, ++ix.x)
1234 double mag = magnitude(x, y);
1237 ValueType gradx = grad.getComponent(ix, 0);
1238 ValueType grady = grad.getComponent(ix, 1);
1248 double m1 = magnitude(x1, y1);
1249 double m3 = magnitude(x2, y2);
1251 if(m1 < mag && m3 <= mag)
1256 double del = 0.5 * (m1 - m3) / (m1 + m3 - 2.0*mag);
1261 if(orientation < 0.0)
1262 orientation += 2.0*M_PI;
1264 edgels.push_back(edgel);
1368 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
1371 BackInsertable & edgels,
double scale)
1373 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
1374 BasicImage<TinyVector<TmpType, 2> > grad(lr-ul);
1380 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
1382 cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1383 BackInsertable & edgels,
double scale)
1388 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
1391 BackInsertable & edgels)
1393 using namespace functor;
1395 typedef typename SrcAccessor::value_type SrcType;
1396 typedef typename NumericTraits<typename SrcType::value_type>::RealPromote TmpType;
1397 BasicImage<TmpType> magnitude(lr-ul);
1401 internalCannyFindEdgels(ul, src, magnitude, edgels);
1404 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
1406 cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1407 BackInsertable & edgels)
1493 template <
class SrcIterator,
class SrcAccessor,
1494 class DestIterator,
class DestAccessor,
1495 class GradValue,
class DestValue>
1497 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1498 DestIterator dul, DestAccessor da,
1499 double scale, GradValue gradient_threshold, DestValue edge_marker)
1501 std::vector<Edgel> edgels;
1505 int w = slr.x - sul.x;
1506 int h = slr.y - sul.y;
1508 for(
unsigned int i=0; i<edgels.size(); ++i)
1510 if(gradient_threshold < edgels[i].strength)
1512 Diff2D pix((
int)(edgels[i].x + 0.5), (
int)(edgels[i].y + 0.5));
1514 if(pix.x < 0 || pix.x >= w || pix.y < 0 || pix.y >= h)
1517 da.set(edge_marker, dul, pix);
1522 template <
class SrcIterator,
class SrcAccessor,
1523 class DestIterator,
class DestAccessor,
1524 class GradValue,
class DestValue>
1526 triple<SrcIterator, SrcIterator, SrcAccessor> src,
1527 pair<DestIterator, DestAccessor> dest,
1528 double scale, GradValue gradient_threshold, DestValue edge_marker)
1531 dest.first, dest.second,
1532 scale, gradient_threshold, edge_marker);
1539 template <
class DestIterator>
1540 int neighborhoodConfiguration(DestIterator dul)
1544 for(
int i=0; i<8; ++i, --c)
1546 v = (v << 1) | ((*c != 0) ? 1 : 0);
1552 template <
class GradValue>
1558 SimplePoint(Diff2D
const & p, GradValue g)
1562 bool operator<(SimplePoint
const & o)
const
1564 return grad < o.grad;
1567 bool operator>(SimplePoint
const & o)
const
1569 return grad > o.grad;
1573 template <
class SrcIterator,
class SrcAccessor,
1574 class DestIterator,
class DestAccessor,
1575 class GradValue,
class DestValue>
1576 void cannyEdgeImageFromGrad(
1577 SrcIterator sul, SrcIterator slr, SrcAccessor grad,
1578 DestIterator dul, DestAccessor da,
1579 GradValue gradient_threshold, DestValue edge_marker)
1581 typedef typename SrcAccessor::value_type PixelType;
1582 typedef typename NormTraits<PixelType>::SquaredNormType NormType;
1584 NormType zero = NumericTraits<NormType>::zero();
1585 double tan22_5 = M_SQRT2 - 1.0;
1586 typename NormTraits<GradValue>::SquaredNormType g2thresh =
squaredNorm(gradient_threshold);
1588 int w = slr.x - sul.x;
1589 int h = slr.y - sul.y;
1595 for(
int y = 1; y < h-1; ++y, ++sul.y, ++dul.y)
1597 SrcIterator sx = sul;
1598 DestIterator dx = dul;
1599 for(
int x = 1; x < w-1; ++x, ++sx.x, ++dx.x)
1601 PixelType g = grad(sx);
1606 NormType g2n1, g2n3;
1608 if(
abs(g[1]) < tan22_5*
abs(g[0]))
1614 else if(
abs(g[0]) < tan22_5*
abs(g[1]))
1620 else if(g[0]*g[1] < zero)
1633 if(g2n1 < g2n && g2n3 <= g2n)
1635 da.set(edge_marker, dx);
1740 template <
class SrcIterator,
class SrcAccessor,
1741 class DestIterator,
class DestAccessor,
1742 class GradValue,
class DestValue>
1744 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1745 DestIterator dul, DestAccessor da,
1746 GradValue gradient_threshold,
1747 DestValue edge_marker,
bool addBorder)
1749 int w = slr.x - sul.x;
1750 int h = slr.y - sul.y;
1757 detail::cannyEdgeImageFromGrad(sul, slr, sa, eul, ea, gradient_threshold, 1);
1759 static bool isSimplePoint[256] = {
1760 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
1761 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
1762 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
1763 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
1764 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1,
1765 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0,
1766 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0,
1767 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
1768 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
1769 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1770 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
1771 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
1772 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0,
1773 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1,
1781 typedef detail::SimplePoint<GradValue> SP;
1783 std::priority_queue<SP, std::vector<SP>, std::greater<SP> > pqueue;
1786 for(; p.y < h2; ++p.y)
1788 for(p.x = 0; p.x < w2; ++p.x)
1793 int v = detail::neighborhoodConfiguration(e);
1794 if(isSimplePoint[v])
1796 pqueue.push(SP(p,
norm(sa(sul+p))));
1802 static const Diff2D dist[] = { Diff2D(-1,0), Diff2D(0,-1),
1803 Diff2D(1,0), Diff2D(0,1) };
1805 while(pqueue.size())
1807 p = pqueue.top().point;
1811 int v = detail::neighborhoodConfiguration(e);
1812 if(!isSimplePoint[v])
1817 for(
int i=0; i<4; ++i)
1819 Diff2D pneu = p + dist[i];
1820 if(pneu.x == -1 || pneu.y == -1 || pneu.x == w2 || pneu.y == h2)
1826 int v = detail::neighborhoodConfiguration(eneu);
1827 if(isSimplePoint[v])
1829 pqueue.push(SP(pneu,
norm(sa(sul+pneu))));
1836 initImageIf(destIterRange(dul, dul+Diff2D(w,h), da),
1837 maskImage(edgeImage), edge_marker);
1840 template <
class SrcIterator,
class SrcAccessor,
1841 class DestIterator,
class DestAccessor,
1842 class GradValue,
class DestValue>
1844 triple<SrcIterator, SrcIterator, SrcAccessor> src,
1845 pair<DestIterator, DestAccessor> dest,
1846 GradValue gradient_threshold,
1847 DestValue edge_marker,
bool addBorder)
1850 dest.first, dest.second,
1851 gradient_threshold, edge_marker, addBorder);
1854 template <
class SrcIterator,
class SrcAccessor,
1855 class DestIterator,
class DestAccessor,
1856 class GradValue,
class DestValue>
1858 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1859 DestIterator dul, DestAccessor da,
1860 GradValue gradient_threshold, DestValue edge_marker)
1864 gradient_threshold, edge_marker,
true);
1867 template <
class SrcIterator,
class SrcAccessor,
1868 class DestIterator,
class DestAccessor,
1869 class GradValue,
class DestValue>
1871 triple<SrcIterator, SrcIterator, SrcAccessor> src,
1872 pair<DestIterator, DestAccessor> dest,
1873 GradValue gradient_threshold, DestValue edge_marker)
1876 dest.first, dest.second,
1877 gradient_threshold, edge_marker,
true);
1960 template <
class SrcIterator,
class SrcAccessor,
1961 class DestIterator,
class DestAccessor,
1962 class GradValue,
class DestValue>
1964 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1965 DestIterator dul, DestAccessor da,
1966 double scale, GradValue gradient_threshold,
1967 DestValue edge_marker,
bool addBorder)
1970 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
1971 BasicImage<TinyVector<TmpType, 2> > grad(slr-sul);
1974 gradient_threshold, edge_marker, addBorder);
1977 template <
class SrcIterator,
class SrcAccessor,
1978 class DestIterator,
class DestAccessor,
1979 class GradValue,
class DestValue>
1981 triple<SrcIterator, SrcIterator, SrcAccessor> src,
1982 pair<DestIterator, DestAccessor> dest,
1983 double scale, GradValue gradient_threshold,
1984 DestValue edge_marker,
bool addBorder)
1987 dest.first, dest.second,
1988 scale, gradient_threshold, edge_marker, addBorder);
1991 template <
class SrcIterator,
class SrcAccessor,
1992 class DestIterator,
class DestAccessor,
1993 class GradValue,
class DestValue>
1995 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1996 DestIterator dul, DestAccessor da,
1997 double scale, GradValue gradient_threshold, DestValue edge_marker)
2001 scale, gradient_threshold, edge_marker,
true);
2004 template <
class SrcIterator,
class SrcAccessor,
2005 class DestIterator,
class DestAccessor,
2006 class GradValue,
class DestValue>
2008 triple<SrcIterator, SrcIterator, SrcAccessor> src,
2009 pair<DestIterator, DestAccessor> dest,
2010 double scale, GradValue gradient_threshold, DestValue edge_marker)
2013 dest.first, dest.second,
2014 scale, gradient_threshold, edge_marker,
true);
2019 template <
class SrcIterator,
class SrcAccessor,
2020 class MaskImage,
class BackInsertable>
2021 void internalCannyFindEdgels3x3(SrcIterator ul, SrcAccessor grad,
2022 MaskImage
const & mask,
2023 BackInsertable & edgels)
2025 typedef typename SrcAccessor::value_type PixelType;
2026 typedef typename PixelType::value_type ValueType;
2029 for(
int y=1; y<mask.height()-1; ++y, ++ul.y)
2031 SrcIterator ix = ul;
2032 for(
int x=1; x<mask.width()-1; ++x, ++ix.x)
2037 ValueType gradx = grad.getComponent(ix, 0);
2038 ValueType grady = grad.getComponent(ix, 1);
2039 double mag =
hypot(gradx, grady);
2042 double c = gradx / mag,
2045 Matrix<double> ml(3,3), mr(3,1), l(3,1), r(3,1);
2048 for(
int yy = -1; yy <= 1; ++yy)
2050 for(
int xx = -1; xx <= 1; ++xx)
2052 double u = c*xx + s*yy;
2053 double v =
norm(grad(ix, Diff2D(xx, yy)));
2066 double del = -r(1,0) / 2.0 / r(2,0);
2067 if(std::fabs(del) > 1.5)
2073 if(orientation < 0.0)
2074 orientation += 2.0*M_PI;
2076 edgels.push_back(edgel);
2176 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
2179 BackInsertable & edgels,
double scale)
2181 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
2182 BasicImage<TinyVector<TmpType, 2> > grad(lr-ul);
2188 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
2191 BackInsertable & edgels,
double scale)
2196 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
2199 BackInsertable & edgels)
2206 internalCannyFindEdgels3x3(ul, src, edges, edgels);
2209 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
2212 BackInsertable & edgels)
2266 #endif // VIGRA_EDGEDETECTION_HXX