[ 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 > 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) |
html generated using doxygen and Python
|