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