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,
class GradValue>
1219 void internalCannyFindEdgels(SrcIterator ul, SrcAccessor grad,
1220 MagnitudeImage
const & magnitude,
1221 BackInsertable & edgels, GradValue grad_thresh)
1223 typedef typename SrcAccessor::value_type PixelType;
1224 typedef typename PixelType::value_type ValueType;
1226 vigra_precondition(grad_thresh >= NumericTraits<GradValue>::zero(),
1227 "cannyFindEdgels(): gradient threshold must not be negative.");
1232 for(
int y=1; y<magnitude.height()-1; ++y, ++ul.y)
1234 SrcIterator ix = ul;
1235 for(
int x=1; x<magnitude.width()-1; ++x, ++ix.x)
1237 double mag = magnitude(x, y);
1238 if(mag <= grad_thresh)
1240 ValueType gradx = grad.getComponent(ix, 0);
1241 ValueType grady = grad.getComponent(ix, 1);
1251 double m1 = magnitude(x1, y1);
1252 double m3 = magnitude(x2, y2);
1254 if(m1 < mag && m3 <= mag)
1259 double del = 0.5 * (m1 - m3) / (m1 + m3 - 2.0*mag);
1264 if(orientation < 0.0)
1265 orientation += 2.0*M_PI;
1267 edgels.push_back(edgel);
1371 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
1374 BackInsertable & edgels,
double scale)
1376 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
1377 BasicImage<TinyVector<TmpType, 2> > grad(lr-ul);
1383 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
1385 cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1386 BackInsertable & edgels,
double scale)
1391 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
1394 BackInsertable & edgels)
1396 using namespace functor;
1398 typedef typename SrcAccessor::value_type SrcType;
1399 typedef typename NumericTraits<typename SrcType::value_type>::RealPromote TmpType;
1400 BasicImage<TmpType> magnitude(lr-ul);
1404 internalCannyFindEdgels(ul, src, magnitude, edgels, NumericTraits<TmpType>::zero());
1407 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
1409 cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1410 BackInsertable & edgels)
1506 template <
class SrcIterator,
class SrcAccessor,
1507 class BackInsertable,
class GradValue>
1510 BackInsertable & edgels,
double scale, GradValue grad_threshold)
1512 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
1513 BasicImage<TinyVector<TmpType, 2> > grad(lr-ul);
1519 template <
class SrcIterator,
class SrcAccessor,
1520 class BackInsertable,
class GradValue>
1523 BackInsertable & edgels,
double scale, GradValue grad_threshold)
1528 template <
class SrcIterator,
class SrcAccessor,
1529 class BackInsertable,
class GradValue>
1532 BackInsertable & edgels, GradValue grad_threshold)
1534 using namespace functor;
1536 typedef typename SrcAccessor::value_type SrcType;
1537 typedef typename NumericTraits<typename SrcType::value_type>::RealPromote TmpType;
1538 BasicImage<TmpType> magnitude(lr-ul);
1542 internalCannyFindEdgels(ul, src, magnitude, edgels, grad_threshold);
1545 template <
class SrcIterator,
class SrcAccessor,
1546 class BackInsertable,
class GradValue>
1549 BackInsertable & edgels, GradValue grad_threshold)
1635 template <
class SrcIterator,
class SrcAccessor,
1636 class DestIterator,
class DestAccessor,
1637 class GradValue,
class DestValue>
1639 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1640 DestIterator dul, DestAccessor da,
1641 double scale, GradValue gradient_threshold, DestValue edge_marker)
1643 std::vector<Edgel> edgels;
1647 int w = slr.x - sul.x;
1648 int h = slr.y - sul.y;
1650 for(
unsigned int i=0; i<edgels.size(); ++i)
1652 Diff2D pix((
int)(edgels[i].x + 0.5), (
int)(edgels[i].y + 0.5));
1654 if(pix.x < 0 || pix.x >= w || pix.y < 0 || pix.y >= h)
1657 da.set(edge_marker, dul, pix);
1661 template <
class SrcIterator,
class SrcAccessor,
1662 class DestIterator,
class DestAccessor,
1663 class GradValue,
class DestValue>
1665 triple<SrcIterator, SrcIterator, SrcAccessor> src,
1666 pair<DestIterator, DestAccessor> dest,
1667 double scale, GradValue gradient_threshold, DestValue edge_marker)
1670 dest.first, dest.second,
1671 scale, gradient_threshold, edge_marker);
1678 template <
class DestIterator>
1679 int neighborhoodConfiguration(DestIterator dul)
1683 for(
int i=0; i<8; ++i, --c)
1685 v = (v << 1) | ((*c != 0) ? 1 : 0);
1691 template <
class GradValue>
1697 SimplePoint(Diff2D
const & p, GradValue g)
1701 bool operator<(SimplePoint
const & o)
const
1703 return grad < o.grad;
1706 bool operator>(SimplePoint
const & o)
const
1708 return grad > o.grad;
1712 template <
class SrcIterator,
class SrcAccessor,
1713 class DestIterator,
class DestAccessor,
1714 class GradValue,
class DestValue>
1715 void cannyEdgeImageFromGrad(
1716 SrcIterator sul, SrcIterator slr, SrcAccessor grad,
1717 DestIterator dul, DestAccessor da,
1718 GradValue gradient_threshold, DestValue edge_marker)
1720 typedef typename SrcAccessor::value_type PixelType;
1721 typedef typename NormTraits<PixelType>::SquaredNormType NormType;
1723 NormType zero = NumericTraits<NormType>::zero();
1724 double tan22_5 = M_SQRT2 - 1.0;
1725 typename NormTraits<GradValue>::SquaredNormType g2thresh =
squaredNorm(gradient_threshold);
1727 int w = slr.x - sul.x;
1728 int h = slr.y - sul.y;
1734 for(
int y = 1; y < h-1; ++y, ++sul.y, ++dul.y)
1736 SrcIterator sx = sul;
1737 DestIterator dx = dul;
1738 for(
int x = 1; x < w-1; ++x, ++sx.x, ++dx.x)
1740 PixelType g = grad(sx);
1745 NormType g2n1, g2n3;
1747 if(
abs(g[1]) < tan22_5*
abs(g[0]))
1753 else if(
abs(g[0]) < tan22_5*
abs(g[1]))
1759 else if(g[0]*g[1] < zero)
1772 if(g2n1 < g2n && g2n3 <= g2n)
1774 da.set(edge_marker, dx);
1879 template <
class SrcIterator,
class SrcAccessor,
1880 class DestIterator,
class DestAccessor,
1881 class GradValue,
class DestValue>
1883 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1884 DestIterator dul, DestAccessor da,
1885 GradValue gradient_threshold,
1886 DestValue edge_marker,
bool addBorder)
1888 int w = slr.x - sul.x;
1889 int h = slr.y - sul.y;
1896 detail::cannyEdgeImageFromGrad(sul, slr, sa, eul, ea, gradient_threshold, 1);
1898 static bool isSimplePoint[256] = {
1899 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
1900 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
1901 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
1902 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
1903 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1,
1904 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0,
1905 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0,
1906 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
1907 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
1908 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1909 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
1910 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
1911 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0,
1912 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1,
1920 typedef detail::SimplePoint<GradValue> SP;
1922 std::priority_queue<SP, std::vector<SP>, std::greater<SP> > pqueue;
1925 for(; p.y < h2; ++p.y)
1927 for(p.x = 0; p.x < w2; ++p.x)
1932 int v = detail::neighborhoodConfiguration(e);
1933 if(isSimplePoint[v])
1935 pqueue.push(SP(p,
norm(sa(sul+p))));
1941 static const Diff2D dist[] = { Diff2D(-1,0), Diff2D(0,-1),
1942 Diff2D(1,0), Diff2D(0,1) };
1944 while(pqueue.size())
1946 p = pqueue.top().point;
1950 int v = detail::neighborhoodConfiguration(e);
1951 if(!isSimplePoint[v])
1956 for(
int i=0; i<4; ++i)
1958 Diff2D pneu = p + dist[i];
1959 if(pneu.x == -1 || pneu.y == -1 || pneu.x == w2 || pneu.y == h2)
1965 int v = detail::neighborhoodConfiguration(eneu);
1966 if(isSimplePoint[v])
1968 pqueue.push(SP(pneu,
norm(sa(sul+pneu))));
1975 initImageIf(destIterRange(dul, dul+Diff2D(w,h), da),
1976 maskImage(edgeImage), edge_marker);
1979 template <
class SrcIterator,
class SrcAccessor,
1980 class DestIterator,
class DestAccessor,
1981 class GradValue,
class DestValue>
1983 triple<SrcIterator, SrcIterator, SrcAccessor> src,
1984 pair<DestIterator, DestAccessor> dest,
1985 GradValue gradient_threshold,
1986 DestValue edge_marker,
bool addBorder)
1989 dest.first, dest.second,
1990 gradient_threshold, edge_marker, addBorder);
1993 template <
class SrcIterator,
class SrcAccessor,
1994 class DestIterator,
class DestAccessor,
1995 class GradValue,
class DestValue>
1997 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1998 DestIterator dul, DestAccessor da,
1999 GradValue gradient_threshold, DestValue edge_marker)
2003 gradient_threshold, edge_marker,
true);
2006 template <
class SrcIterator,
class SrcAccessor,
2007 class DestIterator,
class DestAccessor,
2008 class GradValue,
class DestValue>
2010 triple<SrcIterator, SrcIterator, SrcAccessor> src,
2011 pair<DestIterator, DestAccessor> dest,
2012 GradValue gradient_threshold, DestValue edge_marker)
2015 dest.first, dest.second,
2016 gradient_threshold, edge_marker,
true);
2099 template <
class SrcIterator,
class SrcAccessor,
2100 class DestIterator,
class DestAccessor,
2101 class GradValue,
class DestValue>
2103 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
2104 DestIterator dul, DestAccessor da,
2105 double scale, GradValue gradient_threshold,
2106 DestValue edge_marker,
bool addBorder)
2109 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
2110 BasicImage<TinyVector<TmpType, 2> > grad(slr-sul);
2113 gradient_threshold, edge_marker, addBorder);
2116 template <
class SrcIterator,
class SrcAccessor,
2117 class DestIterator,
class DestAccessor,
2118 class GradValue,
class DestValue>
2120 triple<SrcIterator, SrcIterator, SrcAccessor> src,
2121 pair<DestIterator, DestAccessor> dest,
2122 double scale, GradValue gradient_threshold,
2123 DestValue edge_marker,
bool addBorder)
2126 dest.first, dest.second,
2127 scale, gradient_threshold, edge_marker, addBorder);
2130 template <
class SrcIterator,
class SrcAccessor,
2131 class DestIterator,
class DestAccessor,
2132 class GradValue,
class DestValue>
2134 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
2135 DestIterator dul, DestAccessor da,
2136 double scale, GradValue gradient_threshold, DestValue edge_marker)
2140 scale, gradient_threshold, edge_marker,
true);
2143 template <
class SrcIterator,
class SrcAccessor,
2144 class DestIterator,
class DestAccessor,
2145 class GradValue,
class DestValue>
2147 triple<SrcIterator, SrcIterator, SrcAccessor> src,
2148 pair<DestIterator, DestAccessor> dest,
2149 double scale, GradValue gradient_threshold, DestValue edge_marker)
2152 dest.first, dest.second,
2153 scale, gradient_threshold, edge_marker,
true);
2158 template <
class SrcIterator,
class SrcAccessor,
2159 class MaskImage,
class BackInsertable,
class GradValue>
2160 void internalCannyFindEdgels3x3(SrcIterator ul, SrcAccessor grad,
2161 MaskImage
const & mask,
2162 BackInsertable & edgels,
2163 GradValue grad_thresh)
2165 typedef typename SrcAccessor::value_type PixelType;
2166 typedef typename PixelType::value_type ValueType;
2168 vigra_precondition(grad_thresh >= NumericTraits<GradValue>::zero(),
2169 "cannyFindEdgels3x3(): gradient threshold must not be negative.");
2172 for(
int y=1; y<mask.height()-1; ++y, ++ul.y)
2174 SrcIterator ix = ul;
2175 for(
int x=1; x<mask.width()-1; ++x, ++ix.x)
2180 ValueType gradx = grad.getComponent(ix, 0);
2181 ValueType grady = grad.getComponent(ix, 1);
2182 double mag =
hypot(gradx, grady);
2183 if(mag <= grad_thresh)
2185 double c = gradx / mag,
2188 Matrix<double> ml(3,3), mr(3,1), l(3,1), r(3,1);
2191 for(
int yy = -1; yy <= 1; ++yy)
2193 for(
int xx = -1; xx <= 1; ++xx)
2195 double u = c*xx + s*yy;
2196 double v =
norm(grad(ix, Diff2D(xx, yy)));
2209 double del = -r(1,0) / 2.0 / r(2,0);
2210 if(std::fabs(del) > 1.5)
2216 if(orientation < 0.0)
2217 orientation += 2.0*M_PI;
2219 edgels.push_back(edgel);
2319 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
2322 BackInsertable & edgels,
double scale)
2324 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
2325 BasicImage<TinyVector<TmpType, 2> > grad(lr-ul);
2331 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
2334 BackInsertable & edgels,
double scale)
2339 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
2342 BackInsertable & edgels)
2344 typedef typename NormTraits<typename SrcAccessor::value_type>::NormType NormType;
2351 internalCannyFindEdgels3x3(ul, src, edges, edgels, NumericTraits<NormType>::zero());
2354 template <
class SrcIterator,
class SrcAccessor,
class BackInsertable>
2357 BackInsertable & edgels)
2453 template <
class SrcIterator,
class SrcAccessor,
2454 class BackInsertable,
class GradValue>
2457 BackInsertable & edgels,
double scale, GradValue grad_thresh)
2459 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
2460 BasicImage<TinyVector<TmpType, 2> > grad(lr-ul);
2466 template <
class SrcIterator,
class SrcAccessor,
2467 class BackInsertable,
class GradValue>
2470 BackInsertable & edgels,
double scale, GradValue grad_thresh)
2475 template <
class SrcIterator,
class SrcAccessor,
2476 class BackInsertable,
class GradValue>
2479 BackInsertable & edgels, GradValue grad_thresh)
2486 internalCannyFindEdgels3x3(ul, src, edges, edgels, grad_thresh);
2489 template <
class SrcIterator,
class SrcAccessor,
2490 class BackInsertable,
class GradValue>
2493 BackInsertable & edgels, GradValue grad_thresh)
2547 #endif // VIGRA_EDGEDETECTION_HXX