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

| vigra/tensorutilities.hxx |
--- | --- | ---

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*               Copyright 2002-2004 by Ullrich Koethe                  */
    00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
    00005 /*                                                                      */
    00006 /*    This file is part of the VIGRA computer vision library.           */
    00007 /*    ( Version 1.3.2, Jan 27 2005 )                                    */
    00008 /*    You may use, modify, and distribute this software according       */
    00009 /*    to the terms stated in the LICENSE file included in               */
    00010 /*    the VIGRA distribution.                                           */
    00011 /*                                                                      */
    00012 /*    The VIGRA Website is                                              */
    00013 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
    00014 /*    Please direct questions, bug reports, and contributions to        */
    00015 /*        koethe@informatik.uni-hamburg.de                              */
    00016 /*                                                                      */
    00017 /*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
    00018 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
    00019 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
    00020 /*                                                                      */
    00021 /************************************************************************/
    00022
    00023 #ifndef VIGRA_TENSORUTILITIES_HXX
    00024 #define VIGRA_TENSORUTILITIES_HXX
    00025
    00026 #include <cmath>
    00027 #include "vigra/utilities.hxx"
    00028
    00029 namespace vigra {
    00030
    00031 /** \addtogroup TensorImaging Tensor Image Processing
    00032 */
    00033 //@{
    00034
    00035 /********************************************************/
    00036 /*                                                      */
    00037 /*                      vectorToTensor                  */
    00038 /*                                                      */
    00039 /********************************************************/
    00040
    00041 /** \brief Calculate the tensor (outer) product of a 2D vector with itself.
    00042
    00043     This function is useful to transform vector images into a tensor representation
    00044     that can be used as input to tensor based processing and analysis functions
    00045     (e.g. tensor smoothing). The imput pixel type must be vectors of length 2, whereas
    00046     the output must contain vectors of length 3 which will represent the tensor components
    00047     in the order t11, t12 (== t21 due to symmetry), t22.
    00048
    00049     <b>Note:</b> By default, this function negates the second component of the vector
    00050     in order to turn a left handed vector (the usual resul of convolution,
    00051     e.g. a gradient filter, because <tt>y</tt> runs from top to bottom)
    00052     into a right handed tensor (as is required by all tensor function in VIGRA). This
    00053     behavior can be switched off by setting <tt>negateComponent2 = false</tt>.
    00054
    00055     <b> Declarations:</b>
    00056
    00057     pass arguments explicitly:
    00058     \code
    00059     namespace vigra {
    00060         template <class SrcIterator, class SrcAccessor,
    00061                 class DestIterator, class DestAccessor>
    00062         void vectorToTensor(SrcIterator sul, SrcIterator slr, SrcAccessor src,
    00063                             DestIterator dul, DestAccessor dest,
    00064                             bool negateComponent2 = true);
    00065     }
    00066     \endcode
    00067
    00068
    00069     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00070     \code
    00071     namespace vigra {
    00072         template <class SrcIterator, class SrcAccessor,
    00073                 class DestIterator, class DestAccessor>
    00074         void vectorToTensor(triple<SrcIterator, SrcIterator, SrcAccessor> s,
    00075                             pair<DestIterator, DestAccessor> d,
    00076                             bool negateComponent2 = true);
    00077     }
    00078     \endcode
    00079
    00080     <b> Usage:</b>
    00081
    00082     <b>\#include</b> "<a href="tensorutilities_8hxx-source.html">vigra/tensorutilities.hxx</a>"
    00083
    00084     \code
    00085     FImage img(w,h);
    00086     FVector2Image gradient(w,h);
    00087     FVector3Image tensor(w,h);
    00088
    00089     gaussianGradient(srcImageRange(img), destImage(gradient), 2.0);
    00090     vectorToTensor(srcImageRange(gradient), destImage(tensor));
    00091     \endcode
    00092
    00093 */
    00094 template <class SrcIterator, class SrcAccessor,
    00095           class DestIterator, class DestAccessor>
    00096 void vectorToTensor(SrcIterator sul, SrcIterator slr, SrcAccessor src,
    00097                     DestIterator dul, DestAccessor dest,
    00098                     bool negateComponent2)
    00099 {
    00100     vigra_precondition(src.size(sul) == 2,
    00101                        "vectorToTensor(): input image must have 2 bands.");
    00102     vigra_precondition(dest.size(dul) == 3,
    00103                        "vectorToTensor(): output image must have 3 bands.");
    00104
    00105     int w = slr.x - sul.x;
    00106     int h = slr.y - sul.y;
    00107
    00108     for(int y=0; y<h; ++y, ++sul.y, ++dul.y)
    00109     {
    00110         typename SrcIterator::row_iterator s = sul.rowIterator();
    00111         typename SrcIterator::row_iterator send = s + w;
    00112         typename DestIterator::row_iterator d = dul.rowIterator();
    00113         if(negateComponent2)
    00114         {
    00115             for(; s < send; ++s, ++d)
    00116             {
    00117                 dest.setComponent(sq(src.getComponent(s, 0)), d, 0);
    00118                 dest.setComponent(-src.getComponent(s, 0)*src.getComponent(s, 1), d, 1);
    00119                                // ^ negative sign to turn left-handed into right-handed coordinates
    00120                 dest.setComponent(sq(src.getComponent(s, 1)), d, 2);
    00121             }
    00122         }
    00123         else
    00124         {
    00125             for(; s < send; ++s, ++d)
    00126             {
    00127                 dest.setComponent(sq(src.getComponent(s, 0)), d, 0);
    00128                 dest.setComponent(src.getComponent(s, 0)*src.getComponent(s, 1), d, 1);
    00129                 dest.setComponent(sq(src.getComponent(s, 1)), d, 2);
    00130             }
    00131         }
    00132     }
    00133 }
    00134
    00135 template <class SrcIterator, class SrcAccessor,
    00136           class DestIterator, class DestAccessor>
    00137 inline
    00138 void vectorToTensor(SrcIterator sul, SrcIterator slr, SrcAccessor src,
    00139                     DestIterator dul, DestAccessor dest)
    00140 {
    00141     vectorToTensor(sul, slr, src, dul, dest, true);
    00142 }
    00143
    00144 template <class SrcIterator, class SrcAccessor,
    00145           class DestIterator, class DestAccessor>
    00146 inline
    00147 void vectorToTensor(triple<SrcIterator, SrcIterator, SrcAccessor> s,
    00148                      pair<DestIterator, DestAccessor> d,
    00149                      bool negateComponent2)
    00150 {
    00151     vectorToTensor(s.first, s.second, s.third, d.first, d.second, negateComponent2);
    00152 }
    00153
    00154 template <class SrcIterator, class SrcAccessor,
    00155           class DestIterator, class DestAccessor>
    00156 inline
    00157 void vectorToTensor(triple<SrcIterator, SrcIterator, SrcAccessor> s,
    00158                     pair<DestIterator, DestAccessor> d)
    00159 {
    00160     vectorToTensor(s.first, s.second, s.third, d.first, d.second, true);
    00161 }
    00162
    00163 /********************************************************/
    00164 /*                                                      */
    00165 /*               tensorEigenRepresentation              */
    00166 /*                                                      */
    00167 /********************************************************/
    00168
    00169 /** \brief Calculate eigen representation of a symmetric 2x2 tensor.
    00170
    00171     This function turns a 3-band image representing the tensor components
    00172     t11, t12 (== t21 due to symmetry), t22 into the a 3-band image holding the eigen
    00173     representation e1, e2, and angle, where e1 &gt; e2. The original tensor must be
    00174     defined in a right-handed coordinate system, and the angle of the tensor will
    00175     then be given in mathematical positive (counter-clockwise) orientation, starting
    00176     at the x-axis.
    00177
    00178     <b> Declarations:</b>
    00179
    00180     pass arguments explicitly:
    00181     \code
    00182     namespace vigra {
    00183         template <class SrcIterator, class SrcAccessor,
    00184                 class DestIterator, class DestAccessor>
    00185         void tensorEigenRepresentation(SrcIterator sul, SrcIterator slr, SrcAccessor src,
    00186                                        DestIterator dul, DestAccessor dest);
    00187     }
    00188     \endcode
    00189
    00190
    00191     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00192     \code
    00193     namespace vigra {
    00194         template <class SrcIterator, class SrcAccessor,
    00195                 class DestIterator, class DestAccessor>
    00196         void tensorEigenRepresentation(triple<SrcIterator, SrcIterator, SrcAccessor> s,
    00197                                        pair<DestIterator, DestAccessor> d);
    00198     }
    00199     \endcode
    00200
    00201     <b> Usage:</b>
    00202
    00203     <b>\#include</b> "<a href="tensorutilities_8hxx-source.html">vigra/tensorutilities.hxx</a>"
    00204
    00205     \code
    00206     FVector3Image tensor(w,h);
    00207     FVector3Image eigen(w,h);
    00208
    00209     tensorEigenRepresentation(srcImageRange(tensor), destImage(eigen));
    00210     \endcode
    00211
    00212 */
    00213 template <class SrcIterator, class SrcAccessor,
    00214           class DestIterator, class DestAccessor>
    00215 void tensorEigenRepresentation(SrcIterator sul, SrcIterator slr, SrcAccessor src,
    00216                                DestIterator dul, DestAccessor dest)
    00217 {
    00218     vigra_precondition(src.size(sul) == 3,
    00219                        "tensorEigenRepresentation(): input image must have 3 bands.");
    00220     vigra_precondition(dest.size(dul) == 3,
    00221                        "tensorEigenRepresentation(): output image must have 3 bands.");
    00222
    00223     int w = slr.x - sul.x;
    00224     int h = slr.y - sul.y;
    00225
    00226     for(int y=0; y<h; ++y, ++sul.y, ++dul.y)
    00227     {
    00228         typename SrcIterator::row_iterator s = sul.rowIterator();
    00229         typename SrcIterator::row_iterator send = s + w;
    00230         typename DestIterator::row_iterator d = dul.rowIterator();
    00231         for(; s < send; ++s, ++d)
    00232         {
    00233             typedef typename
    00234                NumericTraits<typename SrcAccessor::component_type>::RealPromote TmpType;
    00235             TmpType d1 = src.getComponent(s,0) + src.getComponent(s,2);
    00236             TmpType d2 = src.getComponent(s,0) - src.getComponent(s,2);
    00237             TmpType d3 = 2.0 * src.getComponent(s,1);
    00238             TmpType d4 = VIGRA_CSTD::sqrt(sq(d2) + sq(d3));
    00239
    00240             dest.setComponent(0.5 * (d1 + d4), d, 0); // large EV
    00241             dest.setComponent(0.5 * (d1 - d4), d, 1); // small EV
    00242             dest.setComponent(0.5 * VIGRA_CSTD::atan2(d3, d2), d, 2); // orientation
    00243         }
    00244     }
    00245 }
    00246
    00247 template <class SrcIterator, class SrcAccessor,
    00248           class DestIterator, class DestAccessor>
    00249 inline
    00250 void tensorEigenRepresentation(triple<SrcIterator, SrcIterator, SrcAccessor> s,
    00251                                pair<DestIterator, DestAccessor> d)
    00252 {
    00253     tensorEigenRepresentation(s.first, s.second, s.third, d.first, d.second);
    00254 }
    00255
    00256 /********************************************************/
    00257 /*                                                      */
    00258 /*                      tensorTrace                     */
    00259 /*                                                      */
    00260 /********************************************************/
    00261
    00262 /** \brief Calculate the trace of a 2x2 tensor.
    00263
    00264     This function turns a 3-band image representing the tensor components
    00265     t11, t12 (== t21 due to symmetry), t22 into the a 1-band image holding the
    00266     tensor trace t11 + t22.
    00267
    00268     <b> Declarations:</b>
    00269
    00270     pass arguments explicitly:
    00271     \code
    00272     namespace vigra {
    00273         template <class SrcIterator, class SrcAccessor,
    00274                 class DestIterator, class DestAccessor>
    00275         void tensorTrace(SrcIterator sul, SrcIterator slr, SrcAccessor src,
    00276                          DestIterator dul, DestAccessor dest);
    00277     }
    00278     \endcode
    00279
    00280
    00281     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00282     \code
    00283     namespace vigra {
    00284         template <class SrcIterator, class SrcAccessor,
    00285                 class DestIterator, class DestAccessor>
    00286         void tensorTrace(triple<SrcIterator, SrcIterator, SrcAccessor> s,
    00287                          pair<DestIterator, DestAccessor> d);
    00288     }
    00289     \endcode
    00290
    00291     <b> Usage:</b>
    00292
    00293     <b>\#include</b> "<a href="tensorutilities_8hxx-source.html">vigra/tensorutilities.hxx</a>"
    00294
    00295     \code
    00296     FVector3Image tensor(w,h);
    00297     FImage trace(w,h);
    00298
    00299     tensorTrace(srcImageRange(tensor), destImage(trace));
    00300     \endcode
    00301
    00302 */
    00303 template <class SrcIterator, class SrcAccessor,
    00304           class DestIterator, class DestAccessor>
    00305 void tensorTrace(SrcIterator sul, SrcIterator slr, SrcAccessor src,
    00306                  DestIterator dul, DestAccessor dest)
    00307 {
    00308     vigra_precondition(src.size(sul) == 3,
    00309                        "tensorTrace(): input image must have 3 bands.");
    00310
    00311     int w = slr.x - sul.x;
    00312     int h = slr.y - sul.y;
    00313
    00314     for(int y=0; y<h; ++y, ++sul.y, ++dul.y)
    00315     {
    00316         typename SrcIterator::row_iterator s = sul.rowIterator();
    00317         typename SrcIterator::row_iterator send = s + w;
    00318         typename DestIterator::row_iterator d = dul.rowIterator();
    00319         for(; s < send; ++s, ++d)
    00320         {
    00321             dest.set(src.getComponent(s,0) + src.getComponent(s,2), d);
    00322         }
    00323     }
    00324 }
    00325
    00326 template <class SrcIterator, class SrcAccessor,
    00327           class DestIterator, class DestAccessor>
    00328 inline
    00329 void tensorTrace(triple<SrcIterator, SrcIterator, SrcAccessor> s,
    00330                  pair<DestIterator, DestAccessor> d)
    00331 {
    00332     tensorTrace(s.first, s.second, s.third, d.first, d.second);
    00333 }
    00334
    00335 /********************************************************/
    00336 /*                                                      */
    00337 /*                  tensorToEdgeCorner                  */
    00338 /*                                                      */
    00339 /********************************************************/
    00340
    00341 /** \brief Decompose a symmetric 2x2 tensor into its edge and corner parts.
    00342
    00343     This function turns a 3-band image representing the tensor components
    00344     t11, t12 (== t21 due to symmetry), t22 into the a 2-band image holding
    00345     the tensor's edgeness (difference of the tensor's
    00346     eigenvalues) and orientation, and a 1-band image representing its corner part
    00347     (equal to the twice the small eigen value). The original tensor must be
    00348     positive definite and defined in a right-handed coordinate system (e.g.
    00349     the tensor resulting from \ref boundaryTensor()).
    00350
    00351     <b> Declarations:</b>
    00352
    00353     pass arguments explicitly:
    00354     \code
    00355     namespace vigra {
    00356         template <class SrcIterator, class SrcAccessor,
    00357                   class DestIterator1, class DestAccessor1,
    00358                   class DestIterator2, class DestAccessor2>
    00359         void tensorToEdgeCorner(SrcIterator sul, SrcIterator slr, SrcAccessor src,
    00360                                 DestIterator1 edgeul, DestAccessor1 edge,
    00361                                 DestIterator2 cornerul, DestAccessor2 corner);
    00362     }
    00363     \endcode
    00364
    00365
    00366     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00367     \code
    00368     namespace vigra {
    00369         template <class SrcIterator, class SrcAccessor,
    00370                   class DestIterator1, class DestAccessor1,
    00371                   class DestIterator2, class DestAccessor2>
    00372         void tensorToEdgeCorner(triple<SrcIterator, SrcIterator, SrcAccessor> s,
    00373                                 pair<DestIterator1, DestAccessor1> edge,
    00374                                 pair<DestIterator2, DestAccessor2> corner);
    00375     }
    00376     \endcode
    00377
    00378     <b> Usage:</b>
    00379
    00380     <b>\#include</b> "<a href="tensorutilities_8hxx-source.html">vigra/tensorutilities.hxx</a>"
    00381
    00382     \code
    00383     FVector3Image tensor(w,h);
    00384     FVector2Image edgePart(w,h);
    00385     FImage cornerPart(w,h);
    00386
    00387     tensorTrace(srcImageRange(tensor), destImage(edgePart), destImage(cornerPart));
    00388     \endcode
    00389
    00390 */
    00391 template <class SrcIterator, class SrcAccessor,
    00392           class DestIterator1, class DestAccessor1,
    00393           class DestIterator2, class DestAccessor2>
    00394 void tensorToEdgeCorner(SrcIterator sul, SrcIterator slr, SrcAccessor src,
    00395                         DestIterator1 edgeul, DestAccessor1 edge,
    00396                         DestIterator2 cornerul, DestAccessor2 corner)
    00397 {
    00398     vigra_precondition(src.size(sul) == 3,
    00399                        "tensorToEdgeCorner(): input image must have 3 bands.");
    00400     vigra_precondition(edge.size(edgeul) == 2,
    00401                        "tensorToEdgeCorner(): edge image must have 2 bands.");
    00402
    00403     int w = slr.x - sul.x;
    00404     int h = slr.y - sul.y;
    00405
    00406     for(int y=0; y<h; ++y, ++sul.y, ++edgeul.y, ++cornerul.y)
    00407     {
    00408         typename SrcIterator::row_iterator s = sul.rowIterator();
    00409         typename SrcIterator::row_iterator send = s + w;
    00410         typename DestIterator1::row_iterator e = edgeul.rowIterator();
    00411         typename DestIterator2::row_iterator c = cornerul.rowIterator();
    00412         for(; s < send; ++s, ++e, ++c)
    00413         {
    00414             typedef typename
    00415                NumericTraits<typename SrcAccessor::component_type>::RealPromote TmpType;
    00416             TmpType d1 = src.getComponent(s,0) + src.getComponent(s,2);
    00417             TmpType d2 = src.getComponent(s,0) - src.getComponent(s,2);
    00418             TmpType d3 = 2.0 * src.getComponent(s,1);
    00419             TmpType d4 = VIGRA_CSTD::sqrt(sq(d2) + sq(d3));
    00420
    00421             edge.setComponent(d4, e, 0); // edgeness = difference of EVs
    00422             edge.setComponent(0.5 * VIGRA_CSTD::atan2(d3, d2), e, 1); // orientation
    00423             corner.set(d1 - d4, c); // cornerness = 2 * small EV
    00424         }
    00425     }
    00426 }
    00427
    00428 template <class SrcIterator, class SrcAccessor,
    00429           class DestIterator1, class DestAccessor1,
    00430           class DestIterator2, class DestAccessor2>
    00431 inline
    00432 void tensorToEdgeCorner(triple<SrcIterator, SrcIterator, SrcAccessor> s,
    00433                         pair<DestIterator1, DestAccessor1> edge,
    00434                         pair<DestIterator2, DestAccessor2> corner)
    00435 {
    00436     tensorToEdgeCorner(s.first, s.second, s.third,
    00437                        edge.first, edge.second, corner.first, corner.second);
    00438 }
    00439
    00440 //@}
    00441
    00442 } // namespace vigra
    00443
    00444 #endif /* VIGRA_TENSORUTILITIES_HXX */

© Ullrich Köthe (koethe@informatik.uni-hamburg.de) Cognitive Systems Group, University of Hamburg, Germany | html generated using doxygen and Python VIGRA 1.3.2 (27 Jan 2005)