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

cornerdetection.hxx
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*/
281doxygen_overloaded_function(template <...> void cornerResponseFunction)
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
319 void cornerResponseFunction(
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*/
468doxygen_overloaded_function(template <...> void foerstnerCornerDetector)
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*/
652doxygen_overloaded_function(template <...> void rohrCornerDetector)
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*/
827doxygen_overloaded_function(template <...> void beaudetCornerDetector)
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
vigra::RGBValue
Class for a single RGB value.
Definition rgbvalue.hxx:128
vigra
vigra::structureTensor
void structureTensor(...)
Calculate the Structure Tensor for each pixel of and image, using Gaussian (derivative) filters.
vigra::beaudetCornerDetector
void beaudetCornerDetector(...)
Find corners in an image (4).
vigra::foerstnerCornerDetector
void foerstnerCornerDetector(...)
Find corners in an image (2).
vigra::combineThreeImages
void combineThreeImages(...)
Combine three source images into destination image.
vigra::cornerResponseFunction
void cornerResponseFunction(...)
Find corners in an image (1).
vigra::hessianMatrixOfGaussian
void hessianMatrixOfGaussian(...)
Filter image with the 2nd derivatives of the Gaussian at the given scale to get the Hessian matrix.
vigra::rohrCornerDetector
void rohrCornerDetector(...)
Find corners in an image (3).
utilities.hxx

© 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