36#ifndef VIGRA_TENSORUTILITIES_HXX
37#define VIGRA_TENSORUTILITIES_HXX
41#include "mathutil.hxx"
42#include "multi_shape.hxx"
134template <
class SrcIterator,
class SrcAccessor,
135 class DestIterator,
class DestAccessor>
136void vectorToTensor(SrcIterator sul, SrcIterator slr, SrcAccessor src,
137 DestIterator dul, DestAccessor dest,
138 bool negateComponent2)
140 vigra_precondition(src.size(sul) == 2,
141 "vectorToTensor(): input image must have 2 bands.");
142 vigra_precondition(dest.size(dul) == 3,
143 "vectorToTensor(): output image must have 3 bands.");
145 int w = slr.x - sul.x;
146 int h = slr.y - sul.y;
148 for(
int y=0; y<h; ++y, ++sul.y, ++dul.y)
150 typename SrcIterator::row_iterator s = sul.rowIterator();
151 typename SrcIterator::row_iterator send = s + w;
152 typename DestIterator::row_iterator d = dul.rowIterator();
155 for(; s < send; ++s, ++d)
157 dest.setComponent(
sq(src.getComponent(s, 0)), d, 0);
158 dest.setComponent(-src.getComponent(s, 0)*src.getComponent(s, 1), d, 1);
160 dest.setComponent(
sq(src.getComponent(s, 1)), d, 2);
165 for(; s < send; ++s, ++d)
167 dest.setComponent(
sq(src.getComponent(s, 0)), d, 0);
168 dest.setComponent(src.getComponent(s, 0)*src.getComponent(s, 1), d, 1);
169 dest.setComponent(
sq(src.getComponent(s, 1)), d, 2);
175template <
class SrcIterator,
class SrcAccessor,
176 class DestIterator,
class DestAccessor>
178void vectorToTensor(SrcIterator sul, SrcIterator slr, SrcAccessor src,
179 DestIterator dul, DestAccessor dest)
184template <
class SrcIterator,
class SrcAccessor,
185 class DestIterator,
class DestAccessor>
188 pair<DestIterator, DestAccessor> d,
189 bool negateComponent2)
191 vectorToTensor(s.first, s.second, s.third, d.first, d.second, negateComponent2);
194template <
class SrcIterator,
class SrcAccessor,
195 class DestIterator,
class DestAccessor>
198 pair<DestIterator, DestAccessor> d)
200 vectorToTensor(s.first, s.second, s.third, d.first, d.second,
false);
203template <
class T1,
class S1,
208 bool negateComponent2 =
false)
210 vigra_precondition(src.shape() == dest.shape(),
211 "vectorToTensor(): shape mismatch between input and output.");
212 vectorToTensor(srcImageRange(src), destImage(dest), negateComponent2);
287template <
class SrcIterator,
class SrcAccessor,
288 class DestIterator,
class DestAccessor>
290 DestIterator dul, DestAccessor dest)
292 vigra_precondition(src.size(sul) == 3,
293 "tensorEigenRepresentation(): input image must have 3 bands.");
294 vigra_precondition(dest.size(dul) == 3,
295 "tensorEigenRepresentation(): output image must have 3 bands.");
297 int w = slr.x - sul.x;
298 int h = slr.y - sul.y;
300 for(
int y=0; y<h; ++y, ++sul.y, ++dul.y)
302 typename SrcIterator::row_iterator s = sul.rowIterator();
303 typename SrcIterator::row_iterator send = s + w;
304 typename DestIterator::row_iterator d = dul.rowIterator();
305 for(; s < send; ++s, ++d)
308 NumericTraits<typename SrcAccessor::component_type>::RealPromote TmpType;
309 TmpType d1 = src.getComponent(s,0) + src.getComponent(s,2);
310 TmpType d2 = src.getComponent(s,0) - src.getComponent(s,2);
311 TmpType d3 = TmpType(2.0) * src.getComponent(s,1);
312 TmpType d4 = (TmpType)
hypot(d2, d3);
314 dest.setComponent(0.5 * (d1 + d4), d, 0);
315 dest.setComponent(0.5 * (d1 - d4), d, 1);
316 if(d2==0.0 && d3==0.0)
318 dest.setComponent(0, d, 2);
322 dest.setComponent(0.5 * VIGRA_CSTD::atan2(d3, d2), d, 2);
328template <
class SrcIterator,
class SrcAccessor,
329 class DestIterator,
class DestAccessor>
332 pair<DestIterator, DestAccessor> dest)
337template <
class T1,
class S1,
343 vigra_precondition(src.shape() == dest.shape(),
344 "tensorEigenRepresentation(): shape mismatch between input and output.");
417template <
class SrcIterator,
class SrcAccessor,
418 class DestIterator,
class DestAccessor>
419void tensorTrace(SrcIterator sul, SrcIterator slr, SrcAccessor src,
420 DestIterator dul, DestAccessor dest)
422 vigra_precondition(src.size(sul) == 3,
423 "tensorTrace(): input image must have 3 bands.");
425 int w = slr.x - sul.x;
426 int h = slr.y - sul.y;
428 for(
int y=0; y<h; ++y, ++sul.y, ++dul.y)
430 typename SrcIterator::row_iterator s = sul.rowIterator();
431 typename SrcIterator::row_iterator send = s + w;
432 typename DestIterator::row_iterator d = dul.rowIterator();
433 for(; s < send; ++s, ++d)
435 dest.set(src.getComponent(s,0) + src.getComponent(s,2), d);
440template <
class SrcIterator,
class SrcAccessor,
441 class DestIterator,
class DestAccessor>
443tensorTrace(triple<SrcIterator, SrcIterator, SrcAccessor> src,
444 pair<DestIterator, DestAccessor> dest)
446 tensorTrace(src.first, src.second, src.third, dest.first, dest.second);
449template <
class T1,
class S1,
455 vigra_precondition(src.shape() == dest.shape(),
456 "tensorTrace(): shape mismatch between input and output.");
542template <
class SrcIterator,
class SrcAccessor,
543 class DestIterator1,
class DestAccessor1,
544 class DestIterator2,
class DestAccessor2>
546 DestIterator1 edgeul, DestAccessor1 edge,
547 DestIterator2 cornerul, DestAccessor2 corner)
549 vigra_precondition(src.size(sul) == 3,
550 "tensorToEdgeCorner(): input image must have 3 bands.");
551 vigra_precondition(edge.size(edgeul) == 2,
552 "tensorToEdgeCorner(): edge image must have 2 bands.");
554 int w = slr.x - sul.x;
555 int h = slr.y - sul.y;
557 for(
int y=0; y<h; ++y, ++sul.y, ++edgeul.y, ++cornerul.y)
559 typename SrcIterator::row_iterator s = sul.rowIterator();
560 typename SrcIterator::row_iterator send = s + w;
561 typename DestIterator1::row_iterator e = edgeul.rowIterator();
562 typename DestIterator2::row_iterator c = cornerul.rowIterator();
563 for(; s < send; ++s, ++e, ++c)
566 NumericTraits<typename SrcAccessor::component_type>::RealPromote TmpType;
567 TmpType d1 = src.getComponent(s,0) + src.getComponent(s,2);
568 TmpType d2 = src.getComponent(s,0) - src.getComponent(s,2);
569 TmpType d3 = 2.0 * src.getComponent(s,1);
570 TmpType d4 = (TmpType)
hypot(d2, d3);
572 edge.setComponent(d4, e, 0);
573 if(d2 == 0.0 && d3 == 0.0)
575 edge.setComponent(0.0, e, 1);
579 edge.setComponent(0.5 * VIGRA_CSTD::atan2(d3, d2), e, 1);
581 corner.set(d1 - d4, c);
586template <
class SrcIterator,
class SrcAccessor,
587 class DestIterator1,
class DestAccessor1,
588 class DestIterator2,
class DestAccessor2>
591 pair<DestIterator1, DestAccessor1> edge,
592 pair<DestIterator2, DestAccessor2> corner)
595 edge.first, edge.second, corner.first, corner.second);
598template <
class T1,
class S1,
599 class T21,
class S21,
600 class T22,
class S22>
606 vigra_precondition(src.shape() == edge.shape(),
607 "tensorToEdgeCorner(): shape mismatch between input and output.");
609 destImage(edge), destImage(corner));
Base class for, and view to, MultiArray.
Definition multi_array.hxx:705
void vectorToTensor(...)
Calculate the tensor (outer) product of a 2D vector with itself.
void tensorTrace(...)
Calculate the trace of a 2x2 tensor.
NumericTraits< T >::Promote sq(T t)
The square function.
Definition mathutil.hxx:382
void tensorToEdgeCorner(...)
Decompose a symmetric 2x2 tensor into its edge and corner parts.
void tensorEigenRepresentation(...)
Calculate eigen representation of a symmetric 2x2 tensor.
FixedPoint16< IntBits, OverflowHandling > hypot(FixedPoint16< IntBits, OverflowHandling > v1, FixedPoint16< IntBits, OverflowHandling > v2)
Length of hypotenuse.
Definition fixedpoint.hxx:1640