[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

cornerdetection.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2004 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 
37 #ifndef VIGRA_CORNERDETECTION_HXX
38 #define VIGRA_CORNERDETECTION_HXX
39 
40 #include "utilities.hxx"
41 #include "numerictraits.hxx"
42 #include "stdimage.hxx"
43 #include "combineimages.hxx"
44 #include "convolution.hxx"
45 #include "functortraits.hxx"
46 #include "multi_shape.hxx"
47 
48 namespace vigra {
49 
50 template <class SrcType>
51 struct CornerResponseFunctor
52 {
53  typedef typename NumericTraits<SrcType>::RealPromote argument_type;
54  typedef argument_type result_type;
55 
56  result_type operator()(argument_type a1,
57  argument_type a2, argument_type a3) const
58  {
59  return detail::RequiresExplicitCast<result_type>::cast((a1*a2 - a3*a3) - 0.04 * (a1 + a2) * (a1 + a2));
60  }
61 };
62 
63 template <class T>
64 class FunctorTraits<CornerResponseFunctor<T> >
65 : public FunctorTraitsBase<CornerResponseFunctor<T> >
66 {
67  public:
68  typedef VigraTrueType isTernaryFunctor;
69 };
70 
71 template <class SrcType>
72 struct FoerstnerCornerFunctor
73 {
74  typedef typename NumericTraits<SrcType>::RealPromote argument_type;
75  typedef argument_type result_type;
76 
77  result_type operator()(argument_type a1,
78  argument_type a2, argument_type a3) const
79  {
80  return (a1*a2 - a3*a3) / (a1 + a2);
81  }
82 };
83 
84 template <class T>
85 class FunctorTraits<FoerstnerCornerFunctor<T> >
86 : public FunctorTraitsBase<FoerstnerCornerFunctor<T> >
87 {
88  public:
89  typedef VigraTrueType isTernaryFunctor;
90 };
91 
92 template <class SrcType>
93 struct RohrCornerFunctor
94 {
95  typedef typename NumericTraits<SrcType>::RealPromote argument_type;
96  typedef argument_type result_type;
97 
98  result_type operator()(argument_type a1,
99  argument_type a2, argument_type a3) const
100  {
101  return (a1*a2 - a3*a3);
102  }
103 };
104 
105 template <class T>
106 class FunctorTraits<RohrCornerFunctor<T> >
107 : public FunctorTraitsBase<RohrCornerFunctor<T> >
108 {
109  public:
110  typedef VigraTrueType isTernaryFunctor;
111 };
112 
113 template <class SrcType>
114 struct BeaudetCornerFunctor
115 {
116  typedef typename NumericTraits<SrcType>::RealPromote argument_type;
117  typedef argument_type result_type;
118 
119  result_type operator()(argument_type a1,
120  argument_type a2, argument_type a3) const
121  {
122  return (a3*a3 - a1*a2);
123  }
124 };
125 
126 template <class T>
127 class FunctorTraits<BeaudetCornerFunctor<T> >
128 : public FunctorTraitsBase<BeaudetCornerFunctor<T> >
129 {
130  public:
131  typedef VigraTrueType isTernaryFunctor;
132 };
133 
134 /** \addtogroup CornerDetection Corner Detection
135  Measure the 'cornerness' at each pixel.
136  Note: The Kitchen-Rosenfeld detector is not implemented because of its
137  inferior performance. The SUSAN detector is missing because it's patented.
138 */
139 //@{
140 
141 /********************************************************/
142 /* */
143 /* cornerResponseFunction */
144 /* */
145 /********************************************************/
146 
147 /** \brief Find corners in an image (1).
148 
149  This algorithm implements the so called 'corner response function'
150  to measure the 'cornerness' of each pixel in the image, according to
151  [C.G. Harris and M.J. Stevens: <em> "A Combined Corner and Edge Detector"</em>,
152  Proc. of 4th Alvey Vision Conference, 1988]. Several studies have found this to be a
153  very robust corner detector, although it moves the corners somewhat into one
154  region, depending on the scale.
155 
156  The algorithm first determines the structure tensor at each pixel by calling
157  \ref structureTensor(). Then the entries of the structure tensor are combined as
158 
159  \f[
160  \mbox{\rm CornerResponse} = \mbox{\rm det(StructureTensor)} - 0.04 \mbox{\rm tr(StructureTensor)}^2
161  = A B - C^2 - 0.04 (A + B)^2
162  \f]
163 
164  The local maxima of the corner response denote the corners in the gray level
165  image.
166 
167  The source value type must be a linear algebra, i.e. addition, subtraction, and
168  multiplication with itself, multiplication with doubles and
169  \ref NumericTraits "NumericTraits" must
170  be defined.
171 
172  <b> Declarations:</b>
173 
174  pass 2D array views:
175  \code
176  namespace vigra {
177  template <class T1, class S1,
178  class T2, class S2>
179  void
180  cornerResponseFunction(MultiArrayView<2, T1, S1> const & src,
181  MultiArrayView<2, T2, S2> dest,
182  double scale);
183  }
184  \endcode
185 
186  \deprecatedAPI{cornerResponseFunction}
187  pass \ref ImageIterators and \ref DataAccessors :
188  \code
189  namespace vigra {
190  template <class SrcIterator, class SrcAccessor,
191  class DestIterator, class DestAccessor>
192  void
193  cornerResponseFunction(SrcIterator sul, SrcIterator slr, SrcAccessor as,
194  DestIterator dul, DestAccessor ad,
195  double scale)
196  }
197  \endcode
198  use argument objects in conjunction with \ref ArgumentObjectFactories :
199  \code
200  namespace vigra {
201  template <class SrcIterator, class SrcAccessor,
202  class DestIterator, class DestAccessor>
203  void cornerResponseFunction(
204  triple<SrcIterator, SrcIterator, SrcAccessor> src,
205  pair<DestIterator, DestAccessor> dest,
206  double scale)
207  }
208  \endcode
209  \deprecatedEnd
210 
211  <b> Usage:</b>
212 
213  <b>\#include</b> <vigra/cornerdetection.hxx><br>
214  Namespace: vigra
215 
216  \code
217  MultiArray<2, unsigned char> src(w,h), corners(w,h);
218  MultiArray<2, float> corner_response(w,h);
219  ...
220 
221  // find corner response at scale 1.0
222  cornerResponseFunction(src, corner_response, 1.0);
223 
224  // find local maxima of corner response, mark with 1
225  localMaxima(corner_response, corners);
226 
227  // threshold corner response to keep only strong corners (above 400.0)
228  transformImage(corner_response, corner_response,
229  Threshold<double, double>(400.0, std::numeric_limits<double>::max(), 0.0, 1.0));
230 
231  // combine thresholding and local maxima
232  combineTwoImages(corners, corner_response,
233  corners, std::multiplies<float>());
234  \endcode
235 
236  \deprecatedUsage{cornerResponseFunction}
237  \code
238  vigra::BImage src(w,h), corners(w,h);
239  vigra::FImage corner_response(w,h);
240 
241  // empty corner image
242  corners.init(0.0);
243  ...
244 
245  // find corner response at scale 1.0
246  vigra::cornerResponseFunction(srcImageRange(src), destImage(corner_response),
247  1.0);
248 
249  // find local maxima of corner response, mark with 1
250  vigra::localMaxima(srcImageRange(corner_response), destImage(corners));
251 
252  // threshold corner response to keep only strong corners (above 400.0)
253  transformImage(srcImageRange(corner_response), destImage(corner_response),
254  vigra::Threshold<double, double>(
255  400.0, std::numeric_limits<double>::max(), 0.0, 1.0));
256 
257  // combine thresholding and local maxima
258  vigra::combineTwoImages(srcImageRange(corners), srcImage(corner_response),
259  destImage(corners), std::multiplies<float>());
260  \endcode
261  <b> Required Interface:</b>
262  \code
263  SrcImageIterator src_upperleft, src_lowerright;
264  DestImageIterator dest_upperleft;
265 
266  SrcAccessor src_accessor;
267  DestAccessor dest_accessor;
268 
269  SrcAccessor::value_type u = src_accessor(src_upperleft);
270  double d;
271 
272  u = u + u
273  u = u - u
274  u = u * u
275  u = d * u
276 
277  dest_accessor.set(u, dest_upperleft);
278  \endcode
279  \deprecatedEnd
280 */
282 
283 template <class SrcIterator, class SrcAccessor,
284  class DestIterator, class DestAccessor>
285 void
286 cornerResponseFunction(SrcIterator sul, SrcIterator slr, SrcAccessor as,
287  DestIterator dul, DestAccessor ad,
288  double scale)
289 {
290  vigra_precondition(scale > 0.0,
291  "cornerResponseFunction(): Scale must be > 0");
292 
293  int w = slr.x - sul.x;
294  int h = slr.y - sul.y;
295 
296  if(w <= 0 || h <= 0) return;
297 
298  typedef typename
299  NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
300 
301  typedef BasicImage<TmpType> TmpImage;
302 
303  TmpImage gx(w,h);
304  TmpImage gy(w,h);
305  TmpImage gxy(w,h);
306 
307  structureTensor(srcIterRange(sul, slr, as),
308  destImage(gx), destImage(gxy), destImage(gy),
309  scale, scale);
310  CornerResponseFunctor<typename SrcAccessor::value_type > cf;
311 
312  combineThreeImages(srcImageRange(gx), srcImage(gy), srcImage(gxy),
313  destIter(dul, ad), cf );
314 }
315 
316 template <class SrcIterator, class SrcAccessor,
317  class DestIterator, class DestAccessor>
318 inline
320  triple<SrcIterator, SrcIterator, SrcAccessor> src,
321  pair<DestIterator, DestAccessor> dest,
322  double scale)
323 {
324  cornerResponseFunction(src.first, src.second, src.third,
325  dest.first, dest.second,
326  scale);
327 }
328 
329 template <class T1, class S1,
330  class T2, class S2>
331 inline void
332 cornerResponseFunction(MultiArrayView<2, T1, S1> const & src,
333  MultiArrayView<2, T2, S2> dest,
334  double scale)
335 {
336  vigra_precondition(src.shape() == dest.shape(),
337  "cornerResponseFunction(): shape mismatch between input and output.");
338  cornerResponseFunction(srcImageRange(src), destImage(dest), scale);
339 }
340 
341 /********************************************************/
342 /* */
343 /* foerstnerCornerDetector */
344 /* */
345 /********************************************************/
346 
347 /** \brief Find corners in an image (2).
348 
349  This algorithm implements the so called 'Foerstner Corner Detector'
350  to measure the 'cornerness' of each pixel in the image, according to
351  [W. F&ouml;rstner: <em> "A feature based correspondence algorithms for image
352  matching"</em>, Intl. Arch. Photogrammetry and Remote Sensing, vol. 24, pp 160-166,
353  1986]. It is also known as the "Plessey Detector" by Harris. However, it should not
354  be confused with the
355  "\link cornerResponseFunction Corner Response Function\endlink ",
356  another detector invented by Harris.
357 
358  The algorithm first determines the structure tensor at each pixel by calling
359  \ref structureTensor(), where the given scale is used for both the inner and outer scales.
360  Then the entries of the structure tensor are combined as
361 
362  \f[
363  \mbox{\rm FoerstnerCornerStrength} = \frac{\mbox{\rm det(StructureTensor)}}{\mbox{\rm tr(StructureTensor)}} =
364  \frac{A B - C^2}{A + B}
365  \f]
366 
367  The local maxima of the corner strength denote the corners in the gray level
368  image. Its performance is similar to the \ref cornerResponseFunction().
369 
370  The source value type must be a division algebra, i.e. addition, subtraction,
371  multiplication, and division with itself, multiplication with doubles and
372  \ref NumericTraits "NumericTraits" must
373  be defined.
374 
375  <b> Declarations:</b>
376 
377  pass 2D array views:
378  \code
379  namespace vigra {
380  template <class T1, class S1,
381  class T2, class S2>
382  void
383  foerstnerCornerDetector(MultiArrayView<2, T1, S1> const & src,
384  MultiArrayView<2, T2, S2> dest,
385  double scale);
386  }
387  \endcode
388 
389  \deprecatedAPI{foerstnerCornerDetector}
390  pass \ref ImageIterators and \ref DataAccessors :
391  \code
392  namespace vigra {
393  template <class SrcIterator, class SrcAccessor,
394  class DestIterator, class DestAccessor>
395  void
396  foerstnerCornerDetector(SrcIterator sul, SrcIterator slr, SrcAccessor as,
397  DestIterator dul, DestAccessor ad,
398  double scale)
399  }
400  \endcode
401  use argument objects in conjunction with \ref ArgumentObjectFactories :
402  \code
403  namespace vigra {
404  template <class SrcIterator, class SrcAccessor,
405  class DestIterator, class DestAccessor>
406  void foerstnerCornerDetector(
407  triple<SrcIterator, SrcIterator, SrcAccessor> src,
408  pair<DestIterator, DestAccessor> dest,
409  double scale)
410  }
411  \endcode
412  \deprecatedEnd
413 
414  <b> Usage:</b>
415 
416  <b>\#include</b> <vigra/cornerdetection.hxx><br>
417  Namespace: vigra
418 
419  \code
420  MultiArray<2, unsigned char> src(w,h), corners(w,h);
421  MultiArray<2, float> foerstner_corner_strength(w,h);
422  ...
423 
424  // find corner response at scale 1.0
425  foerstnerCornerDetector(src, foerstner_corner_strength, 1.0);
426 
427  // find local maxima of corner response, mark with 1
428  localMaxima(foerstner_corner_strength, corners);
429  \endcode
430 
431  \deprecatedUsage{foerstnerCornerDetector}
432  \code
433  vigra::BImage src(w,h), corners(w,h);
434  vigra::FImage foerstner_corner_strength(w,h);
435 
436  // empty corner image
437  corners.init(0.0);
438  ...
439 
440  // find corner response at scale 1.0
441  vigra::foerstnerCornerDetector(srcImageRange(src), destImage(foerstner_corner_strength),
442  1.0);
443 
444  // find local maxima of corner response, mark with 1
445  vigra::localMaxima(srcImageRange(foerstner_corner_strength), destImage(corners));
446  \endcode
447  <b> Required Interface:</b>
448  \code
449  SrcImageIterator src_upperleft, src_lowerright;
450  DestImageIterator dest_upperleft;
451 
452  SrcAccessor src_accessor;
453  DestAccessor dest_accessor;
454 
455  SrcAccessor::value_type u = src_accessor(src_upperleft);
456  double d;
457 
458  u = u + u
459  u = u - u
460  u = u * u
461  u = u / u
462  u = d * u
463 
464  dest_accessor.set(u, dest_upperleft);
465  \endcode
466  \deprecatedEnd
467 */
469 
470 template <class SrcIterator, class SrcAccessor,
471  class DestIterator, class DestAccessor>
472 void
473 foerstnerCornerDetector(SrcIterator sul, SrcIterator slr, SrcAccessor as,
474  DestIterator dul, DestAccessor ad,
475  double scale)
476 {
477  vigra_precondition(scale > 0.0,
478  "foerstnerCornerDetector(): Scale must be > 0");
479 
480  int w = slr.x - sul.x;
481  int h = slr.y - sul.y;
482 
483  if(w <= 0 || h <= 0) return;
484 
485  typedef typename
486  NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
487 
488  typedef BasicImage<TmpType> TmpImage;
489 
490  TmpImage gx(w,h);
491  TmpImage gy(w,h);
492  TmpImage gxy(w,h);
493 
494  structureTensor(srcIterRange(sul, slr, as),
495  destImage(gx), destImage(gxy), destImage(gy),
496  scale, scale);
497  FoerstnerCornerFunctor<typename SrcAccessor::value_type > cf;
498 
499  combineThreeImages(srcImageRange(gx), srcImage(gy), srcImage(gxy),
500  destIter(dul, ad), cf );
501 }
502 
503 template <class SrcIterator, class SrcAccessor,
504  class DestIterator, class DestAccessor>
505 inline void
506 foerstnerCornerDetector(triple<SrcIterator, SrcIterator, SrcAccessor> src,
507  pair<DestIterator, DestAccessor> dest,
508  double scale)
509 {
510  foerstnerCornerDetector(src.first, src.second, src.third,
511  dest.first, dest.second,
512  scale);
513 }
514 
515 template <class T1, class S1,
516  class T2, class S2>
517 inline void
518 foerstnerCornerDetector(MultiArrayView<2, T1, S1> const & src,
519  MultiArrayView<2, T2, S2> dest,
520  double scale)
521 {
522  vigra_precondition(src.shape() == dest.shape(),
523  "foerstnerCornerDetector(): shape mismatch between input and output.");
524  foerstnerCornerDetector(srcImageRange(src),
525  destImage(dest),
526  scale);
527 }
528 
529 /********************************************************/
530 /* */
531 /* rohrCornerDetector */
532 /* */
533 /********************************************************/
534 
535 /** \brief Find corners in an image (3).
536 
537  This algorithm implements yet another structure tensor-based corner detector,
538  according to [K. Rohr: <em>"Untersuchung von grauwertabh&auml;ngigen
539  Transformationen zur Ermittlung der optischen Flusses in Bildfolgen"</em>,
540  Diploma thesis, Inst. f&uuml;r Nachrichtensysteme, Univ. Karlsruhe, 1987, see also
541  K. Rohr: <em>"Modelling and Identification of Characteristic Intensity Variations"</em>,
542  Image and Vision Computing 10:2 (1992) 66-76 and K. Rohr: <em>"Localization Properties of
543  Direct Corner Detectors"</em>, J. of Mathematical Imaging and Vision 4:2 (1994) 139-150].
544 
545  The algorithm first determines the structure tensor at each pixel by calling
546  \ref structureTensor(), where the given scale is used for both the inner and outer scales.
547  Then the entries of the structure tensor are combined as
548 
549  \f[
550  \mbox{\rm RohrCornerStrength} = \mbox{\rm det(StructureTensor)} = A B - C^2
551  \f]
552 
553  The local maxima of the corner strength denote the corners in the gray level
554  image. Its performance is similar to the \ref cornerResponseFunction().
555 
556  The source value type must be a linear algebra, i.e. addition, subtraction, and
557  multiplication with itself, multiplication with doubles and
558  \ref NumericTraits "NumericTraits" must be defined.
559 
560  <b> Declarations:</b>
561 
562  pass 2D array views:
563  \code
564  namespace vigra {
565  template <class T1, class S1,
566  class T2, class S2>
567  void
568  rohrCornerDetector(MultiArrayView<2, T1, S1> const & src,
569  MultiArrayView<2, T2, S2> dest,
570  double scale);
571  }
572  \endcode
573 
574  \deprecatedAPI{rohrCornerDetector}
575  pass \ref ImageIterators and \ref DataAccessors :
576  \code
577  namespace vigra {
578  template <class SrcIterator, class SrcAccessor,
579  class DestIterator, class DestAccessor>
580  void
581  rohrCornerDetector(SrcIterator sul, SrcIterator slr, SrcAccessor as,
582  DestIterator dul, DestAccessor ad,
583  double scale)
584  }
585  \endcode
586  use argument objects in conjunction with \ref ArgumentObjectFactories :
587  \code
588  namespace vigra {
589  template <class SrcIterator, class SrcAccessor,
590  class DestIterator, class DestAccessor>
591  void rohrCornerDetector(
592  triple<SrcIterator, SrcIterator, SrcAccessor> src,
593  pair<DestIterator, DestAccessor> dest,
594  double scale)
595  }
596  \endcode
597  \deprecatedEnd
598 
599  <b> Usage:</b>
600 
601  <b>\#include</b> <vigra/cornerdetection.hxx><br>
602  Namespace: vigra
603 
604  \code
605  MultiArray<2, unsigned char> src(w,h), corners(w,h);
606  MultiArray<2, float> rohr_corner_strength(w,h);
607  ...
608 
609  // find corner response at scale 1.0
610  rohrCornerDetector(src, rohr_corner_strength, 1.0);
611 
612  // find local maxima of corner response, mark with 1
613  localMaxima(rohr_corner_strength, corners);
614  \endcode
615 
616  \deprecatedUsage{rohrCornerDetector}
617  \code
618  vigra::BImage src(w,h), corners(w,h);
619  vigra::FImage rohr_corner_strength(w,h);
620 
621  // empty corner image
622  corners.init(0.0);
623  ...
624 
625  // find corner response at scale 1.0
626  vigra::rohrCornerDetector(srcImageRange(src), destImage(rohr_corner_strength),
627  1.0);
628 
629  // find local maxima of corner response, mark with 1
630  vigra::localMaxima(srcImageRange(rohr_corner_strength), destImage(corners));
631  \endcode
632  <b> Required Interface:</b>
633  \code
634  SrcImageIterator src_upperleft, src_lowerright;
635  DestImageIterator dest_upperleft;
636 
637  SrcAccessor src_accessor;
638  DestAccessor dest_accessor;
639 
640  SrcAccessor::value_type u = src_accessor(src_upperleft);
641  double d;
642 
643  u = u + u
644  u = u - u
645  u = u * u
646  u = d * u
647 
648  dest_accessor.set(u, dest_upperleft);
649  \endcode
650  \deprecatedEnd
651 */
653 
654 template <class SrcIterator, class SrcAccessor,
655  class DestIterator, class DestAccessor>
656 void
657 rohrCornerDetector(SrcIterator sul, SrcIterator slr, SrcAccessor as,
658  DestIterator dul, DestAccessor ad,
659  double scale)
660 {
661  vigra_precondition(scale > 0.0,
662  "rohrCornerDetector(): Scale must be > 0");
663 
664  int w = slr.x - sul.x;
665  int h = slr.y - sul.y;
666 
667  if(w <= 0 || h <= 0) return;
668 
669  typedef typename
670  NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
671 
672  typedef BasicImage<TmpType> TmpImage;
673 
674  TmpImage gx(w,h);
675  TmpImage gy(w,h);
676  TmpImage gxy(w,h);
677 
678  structureTensor(srcIterRange(sul, slr, as),
679  destImage(gx), destImage(gxy), destImage(gy),
680  scale, scale);
681  RohrCornerFunctor<typename SrcAccessor::value_type > cf;
682 
683  combineThreeImages(srcImageRange(gx), srcImage(gy), srcImage(gxy),
684  destIter(dul, ad), cf );
685 }
686 
687 template <class SrcIterator, class SrcAccessor,
688  class DestIterator, class DestAccessor>
689 inline void
690 rohrCornerDetector(triple<SrcIterator, SrcIterator, SrcAccessor> src,
691  pair<DestIterator, DestAccessor> dest,
692  double scale)
693 {
694  rohrCornerDetector(src.first, src.second, src.third,
695  dest.first, dest.second,
696  scale);
697 }
698 
699 template <class T1, class S1,
700  class T2, class S2>
701 inline void
702 rohrCornerDetector(MultiArrayView<2, T1, S1> const & src,
703  MultiArrayView<2, T2, S2> dest,
704  double scale)
705 {
706  vigra_precondition(src.shape() == dest.shape(),
707  "rohrCornerDetector(): shape mismatch between input and output.");
708  rohrCornerDetector(srcImageRange(src),
709  destImage(dest),
710  scale);
711 }
712 
713 /********************************************************/
714 /* */
715 /* beaudetCornerDetector */
716 /* */
717 /********************************************************/
718 
719 /** \brief Find corners in an image (4).
720 
721  This algorithm implements a corner detector
722  according to [P.R. Beaudet: <em> "Rotationally Invariant Image Operators"</em>,
723  Proc. Intl. Joint Conf. on Pattern Recognition, Kyoto, Japan, 1978, pp. 579-583].
724 
725  The algorithm calculates the corner strength as the negative determinant of the
726  \link hessianMatrixOfGaussian() Hessian Matrix\endlink.
727  The local maxima of the corner strength denote the corners in the gray level
728  image.
729 
730  The source value type must be a linear algebra, i.e. addition, subtraction, and
731  multiplication with itself, multiplication with doubles and
732  \ref NumericTraits "NumericTraits" must
733  be defined.
734 
735  <b> Declarations:</b>
736 
737  pass 2D array views:
738  \code
739  namespace vigra {
740  template <class T1, class S1,
741  class T2, class S2>
742  void
743  beaudetCornerDetector(MultiArrayView<2, T1, S1> const & src,
744  MultiArrayView<2, T2, S2> dest,
745  double scale);
746  }
747  \endcode
748 
749  \deprecatedAPI{beaudetCornerDetector}
750  pass \ref ImageIterators and \ref DataAccessors :
751  \code
752  namespace vigra {
753  template <class SrcIterator, class SrcAccessor,
754  class DestIterator, class DestAccessor>
755  void
756  beaudetCornerDetector(SrcIterator sul, SrcIterator slr, SrcAccessor as,
757  DestIterator dul, DestAccessor ad,
758  double scale)
759  }
760  \endcode
761  use argument objects in conjunction with \ref ArgumentObjectFactories :
762  \code
763  namespace vigra {
764  template <class SrcIterator, class SrcAccessor,
765  class DestIterator, class DestAccessor>
766  void beaudetCornerDetector(
767  triple<SrcIterator, SrcIterator, SrcAccessor> src,
768  pair<DestIterator, DestAccessor> dest,
769  double scale)
770  }
771  \endcode
772  \deprecatedEnd
773 
774  <b> Usage:</b>
775 
776  <b>\#include</b> <vigra/cornerdetection.hxx><br>
777  Namespace: vigra
778 
779  \code
780  MultiArray<2, unsigned char> src(w,h), corners(w,h);
781  MultiArray<2, float> beaudet_corner_strength(w,h);
782  ...
783 
784  // find corner response at scale 1.0
785  beaudetCornerDetector(src, beaudet_corner_strength, 1.0);
786 
787  // find local maxima of corner response, mark with 1
788  localMaxima(beaudet_corner_strength, corners);
789  \endcode
790 
791  \deprecatedUsage{beaudetCornerDetector}
792  \code
793  vigra::BImage src(w,h), corners(w,h);
794  vigra::FImage beaudet_corner_strength(w,h);
795 
796  // empty corner image
797  corners.init(0.0);
798  ...
799 
800  // find corner response at scale 1.0
801  vigra::beaudetCornerDetector(srcImageRange(src), destImage(beaudet_corner_strength),
802  1.0);
803 
804  // find local maxima of corner response, mark with 1
805  vigra::localMaxima(srcImageRange(beaudet_corner_strength), destImage(corners));
806  \endcode
807  <b> Required Interface:</b>
808  \code
809  SrcImageIterator src_upperleft, src_lowerright;
810  DestImageIterator dest_upperleft;
811 
812  SrcAccessor src_accessor;
813  DestAccessor dest_accessor;
814 
815  SrcAccessor::value_type u = src_accessor(src_upperleft);
816  double d;
817 
818  u = u + u
819  u = u - u
820  u = u * u
821  u = d * u
822 
823  dest_accessor.set(u, dest_upperleft);
824  \endcode
825  \deprecatedEnd
826 */
828 
829 template <class SrcIterator, class SrcAccessor,
830  class DestIterator, class DestAccessor>
831 void
832 beaudetCornerDetector(SrcIterator sul, SrcIterator slr, SrcAccessor as,
833  DestIterator dul, DestAccessor ad,
834  double scale)
835 {
836  vigra_precondition(scale > 0.0,
837  "beaudetCornerDetector(): Scale must be > 0");
838 
839  int w = slr.x - sul.x;
840  int h = slr.y - sul.y;
841 
842  if(w <= 0 || h <= 0) return;
843 
844  typedef typename
845  NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
846 
847  typedef BasicImage<TmpType> TmpImage;
848 
849  TmpImage gx(w,h);
850  TmpImage gy(w,h);
851  TmpImage gxy(w,h);
852 
853  hessianMatrixOfGaussian(srcIterRange(sul, slr, as),
854  destImage(gx), destImage(gxy), destImage(gy),
855  scale);
856  BeaudetCornerFunctor<typename SrcAccessor::value_type > cf;
857 
858  combineThreeImages(srcImageRange(gx), srcImage(gy), srcImage(gxy),
859  destIter(dul, ad), cf );
860 }
861 
862 template <class SrcIterator, class SrcAccessor,
863  class DestIterator, class DestAccessor>
864 inline void
865 beaudetCornerDetector(triple<SrcIterator, SrcIterator, SrcAccessor> src,
866  pair<DestIterator, DestAccessor> dest,
867  double scale)
868 {
869  beaudetCornerDetector(src.first, src.second, src.third,
870  dest.first, dest.second,
871  scale);
872 }
873 
874 template <class T1, class S1,
875  class T2, class S2>
876 inline void
877 beaudetCornerDetector(MultiArrayView<2, T1, S1> const & src,
878  MultiArrayView<2, T2, S2> dest,
879  double scale)
880 {
881  vigra_precondition(src.shape() == dest.shape(),
882  "beaudetCornerDetector(): shape mismatch between input and output.");
883  beaudetCornerDetector(srcImageRange(src),
884  destImage(dest),
885  scale);
886 }
887 
888 
889 //@}
890 
891 } // namespace vigra
892 
893 #endif // VIGRA_CORNERDETECTION_HXX
void foerstnerCornerDetector(...)
Find corners in an image (2).
void rohrCornerDetector(...)
Find corners in an image (3).
void hessianMatrixOfGaussian(...)
Filter image with the 2nd derivatives of the Gaussian at the given scale to get the Hessian matrix...
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
void structureTensor(...)
Calculate the Structure Tensor for each pixel of and image, using Gaussian (derivative) filters...
void beaudetCornerDetector(...)
Find corners in an image (4).
void combineThreeImages(...)
Combine three source images into destination image.
void cornerResponseFunction(...)
Find corners in an image (1).

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.11.1 (Fri May 19 2017)