accessor.hxx   accessor.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 780 skipping to change at line 778
*/ */
template <class VECTOR> template <class VECTOR>
class VectorAccessor class VectorAccessor
: public SequenceAccessor<VECTOR> : public SequenceAccessor<VECTOR>
{ {
public: public:
/** the vector's value_type /** the vector's value_type
*/ */
typedef typename VECTOR::value_type component_type; typedef typename VECTOR::value_type component_type;
/** the vector element accessor associated with this vector accesso
r
(see \ref VectorElementAccessor)
*/
typedef VectorElementAccessor<VectorAccessor<VECTOR> > ElementAccessor;
/** Read the component data at given vector index /** Read the component data at given vector index
at given iterator position at given iterator position
*/ */
template <class ITERATOR> template <class ITERATOR>
component_type const & getComponent(ITERATOR const & i, int idx) const component_type const & getComponent(ITERATOR const & i, int idx) const
{ {
return (*i)[idx]; return (*i)[idx];
} }
/** Set the component data at given vector index /** Set the component data at given vector index
 End of changes. 4 change blocks. 
3 lines changed or deleted 7 lines changed or added


 affine_registration.hxx   affine_registration.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2005-2006 by Ullrich Koethe */ /* Copyright 2005-2006 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 46 skipping to change at line 44
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_AFFINE_REGISTRATION_HXX #ifndef VIGRA_AFFINE_REGISTRATION_HXX
#define VIGRA_AFFINE_REGISTRATION_HXX #define VIGRA_AFFINE_REGISTRATION_HXX
#include "mathutil.hxx" #include "mathutil.hxx"
#include "matrix.hxx" #include "matrix.hxx"
#include "linear_solve.hxx" #include "linear_solve.hxx"
#include "tinyvector.hxx" #include "tinyvector.hxx"
#include "splineimageview.hxx" #include "splineimageview.hxx"
#include "imagecontainer.hxx"
#include <cmath> #include <cmath>
namespace vigra { namespace vigra {
/** \addtogroup Registration Image Registration /** \addtogroup Registration Image Registration
*/ */
//@{ //@{
/********************************************************/ /********************************************************/
/* */ /* */
 End of changes. 4 change blocks. 
3 lines changed or deleted 2 lines changed or added


 affinegeometry.hxx   affinegeometry.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2005-2006 by Ullrich Koethe */ /* Copyright 2005-2006 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 256 skipping to change at line 254
DestIterator id, DestAccessor dest, DestIterator id, DestAccessor dest,
double angleInDegree, TinyVector<double, 2> const & center ) double angleInDegree, TinyVector<double, 2> const & center )
{ {
int w = src.width(); int w = src.width();
int h = src.height(); int h = src.height();
double angle = angleInDegree*M_PI/180.0; double angle = angleInDegree*M_PI/180.0;
double c = std::cos(angle); double c = std::cos(angle);
double s = std::sin(angle); double s = std::sin(angle);
// avoid round-off errors for simple rotations
if(closeAtTolerance(std::fmod(angleInDegree, 45.0), 0.0))
{
// convert angle into a multiple of pi/4
int ai = roundi(angleInDegree / 45.0) % 8;
if(ai < 0)
ai += 8;
static double sqrt2_2 = 0.5*M_SQRT2;
static double ss[8] = {0.0, sqrt2_2, 1.0, sqrt2_2, 0.0, -sqrt2_2,
-1.0, -sqrt2_2};
static double cc[8] = {1.0, sqrt2_2, 0.0, -sqrt2_2, -1.0, -sqrt2_2,
0.0, sqrt2_2};
s = ss[ai];
c = cc[ai];
}
for(int y = 0; y < h; ++y, ++id.y) for(int y = 0; y < h; ++y, ++id.y)
{ {
typename DestIterator::row_iterator rd = id.rowIterator(); typename DestIterator::row_iterator rd = id.rowIterator();
double sy = (y - center[1])*c - center[0]*s + center[1]; double sy = (y - center[1])*c - center[0]*s + center[1];
double sx = -(y - center[1])*s - center[0]*c + center[0]; double sx = -(y - center[1])*s - center[0]*c + center[0];
for(int x=0; x < w; ++x, ++rd, sx += c, sy += s) for(int x=0; x < w; ++x, ++rd, sx += c, sy += s)
{ {
if(src.isInside(sx, sy)) if(src.isInside(sx, sy))
dest.set(src(sx, sy), rd); dest.set(src(sx, sy), rd);
} }
 End of changes. 4 change blocks. 
3 lines changed or deleted 19 lines changed or added


 array_vector.hxx   array_vector.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2002-2004 by Ullrich Koethe */ /* Copyright 2002-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 41 skipping to change at line 39
/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_ARRAY_VECTOR_HXX #ifndef VIGRA_ARRAY_VECTOR_HXX
#define VIGRA_ARRAY_VECTOR_HXX #define VIGRA_ARRAY_VECTOR_HXX
#include "error.hxx"
#include "memory.hxx" #include "memory.hxx"
#include "numerictraits.hxx"
#include <memory> #include <memory>
#include <algorithm> #include <algorithm>
#include <iosfwd> #include <iosfwd>
#ifdef VIGRA_CHECK_BOUNDS
#define VIGRA_ASSERT_INSIDE(diff) \
vigra_precondition(diff >= 0, "Index out of bounds");\
vigra_precondition((unsigned int)diff < size_, "Index out of bounds");
#else
#define VIGRA_ASSERT_INSIDE(diff)
#endif
namespace vigra namespace vigra
{ {
template <class T, class Alloc = std::allocator<T> > template <class T, class Alloc = std::allocator<T> >
class ArrayVector; class ArrayVector;
/** Provide STL conforming interface for C-arrays. /** Provide STL conforming interface for C-arrays.
This template implements much of the functionality of <tt>std::vector</ tt> This template implements much of the functionality of <tt><a href="http ://www.sgi.com/tech/stl/Vector.html">std::vector</a></tt>
on top of a C-array. <tt>ArrayVectorView</tt> does not manage the memor y on top of a C-array. <tt>ArrayVectorView</tt> does not manage the memor y
it refers to (i.e. it does not allocate or deallocate any memory). it refers to (i.e. it does not allocate or deallocate any memory).
Thus, if the underlying memory changes, all dependent <tt>ArrayVectorVi ew</tt> Thus, if the underlying memory changes, all dependent <tt>ArrayVectorVi ew</tt>
objects are invalidated. This is especially important when <tt>ArrayVec torView</tt> objects are invalidated. This is especially important when <tt>ArrayVec torView</tt>
is used as a base class for <tt>ArrayVector</tt>, where several functio ns is used as a base class for <tt>ArrayVector</tt>, where several functio ns
(e.g. resize(), insert()) can allocate new memory and thus invalidate t he (e.g. resize(), insert()) can allocate new memory and thus invalidate t he
dependent views. The rules what operations invalidate view objects are the dependent views. The rules what operations invalidate view objects are the
same as the rules concerning standard iterators. same as the rules concerning standard iterators.
<b>\#include</b> \<<a href="array__vector_8hxx-source.html">vigra/array _vector.hxx</a>\><br> <b>\#include</b> \<<a href="array__vector_8hxx-source.html">vigra/array _vector.hxx</a>\><br>
skipping to change at line 82 skipping to change at line 90
public: public:
/** default constructor /** default constructor
*/ */
typedef T value_type; typedef T value_type;
typedef value_type & reference; typedef value_type & reference;
typedef value_type const & const_reference; typedef value_type const & const_reference;
typedef value_type * pointer; typedef value_type * pointer;
typedef value_type const * const_pointer; typedef value_type const * const_pointer;
typedef value_type * iterator; typedef value_type * iterator;
typedef value_type const * const_iterator; typedef value_type const * const_iterator;
typedef unsigned int size_type; typedef std::size_t size_type;
typedef int difference_type; typedef std::ptrdiff_t difference_type;
typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
public: public:
/** default constructor. /** default constructor.
View contains NULL pointer. View contains NULL pointer.
*/ */
ArrayVectorView() ArrayVectorView()
: size_(0), : size_(0),
data_(0) data_(0)
skipping to change at line 194 skipping to change at line 202
swapDataImpl(rhs); swapDataImpl(rhs);
} }
/** Construct <tt>ArrayVectorView</tt> refering to a subarray. /** Construct <tt>ArrayVectorView</tt> refering to a subarray.
\a begin and \a end must be a valid sub-range of the current ar ray. \a begin and \a end must be a valid sub-range of the current ar ray.
Otherwise, a <tt>PreconditionViolation</tt> Otherwise, a <tt>PreconditionViolation</tt>
exception is thrown. exception is thrown.
*/ */
this_type subarray (size_type begin, size_type end) const this_type subarray (size_type begin, size_type end) const
{ {
vigra_precondition(begin >= 0 && begin <= end && end <= size_, vigra_precondition(begin <= end && end <= size_,
"ArrayVectorView::subarray(): Limits out of range."); "ArrayVectorView::subarray(): Limits out of range.");
return this_type(end-begin, data_ + begin); return this_type(end-begin, data_ + begin);
} }
/** Get contained const pointer to the data. /** Get contained const pointer to the data.
*/ */
inline const_pointer data() const inline const_pointer data() const
{ {
return data_; return data_;
} }
skipping to change at line 301 skipping to change at line 309
*/ */
const_reference back() const const_reference back() const
{ {
return data_[size_-1]; return data_[size_-1];
} }
/** Access array element \a i. /** Access array element \a i.
*/ */
reference operator[]( difference_type i ) reference operator[]( difference_type i )
{ {
VIGRA_ASSERT_INSIDE(i);
return data()[i]; return data()[i];
} }
/** Read array element \a i. /** Read array element \a i.
*/ */
const_reference operator[]( difference_type i ) const const_reference operator[]( difference_type i ) const
{ {
VIGRA_ASSERT_INSIDE(i);
return data()[i]; return data()[i];
} }
/** Equivalent to <tt>size() == 0</tt>. /** Equivalent to <tt>size() == 0</tt>.
*/ */
bool empty() const bool empty() const
{ {
return size_ == 0; return size_ == 0;
} }
skipping to change at line 437 skipping to change at line 447
else else
{ {
ArrayVector<T> t(*this); ArrayVector<T> t(*this);
copyImpl(rhs); copyImpl(rhs);
rhs.copyImpl(*this); rhs.copyImpl(*this);
} }
} }
/** Replacement for <tt>std::vector</tt>. /** Replacement for <tt>std::vector</tt>.
This template implements the same functionality as <tt>std::vector</tt> . This template implements the same functionality as <tt>a href="http://w ww.sgi.com/tech/stl/Vector.html">std::vector</a></tt> (see there for detail ed documentation).
However, it gives two useful guarantees, that <tt>std::vector</tt> fail s However, it gives two useful guarantees, that <tt>std::vector</tt> fail s
to provide: to provide:
<ul> <ul>
<li>The memory is always allocated as one contiguous piece.</li> <li>The memory is always allocated as one contiguous piece.</li>
<li>The iterator is always a <TT>T *</TT> </li> <li>The iterator is always a <TT>T *</TT> </li>
</ul> </ul>
This means that memory managed by <tt>ArrayVector</tt> can be passed This means that memory managed by <tt>ArrayVector</tt> can be passed
to algorithms that expect raw memory. This is especially important to algorithms that expect raw memory. This is especially important
skipping to change at line 475 skipping to change at line 485
description of <tt>ArrayVector</tt> functionality. description of <tt>ArrayVector</tt> functionality.
<b>\#include</b> \<<a href="array__vector_8hxx-source.html">vigra/array _vector.hxx</a>\><br> <b>\#include</b> \<<a href="array__vector_8hxx-source.html">vigra/array _vector.hxx</a>\><br>
Namespace: vigra Namespace: vigra
*/ */
template <class T, class Alloc /* = std::allocator<T> */ > template <class T, class Alloc /* = std::allocator<T> */ >
class ArrayVector class ArrayVector
: public ArrayVectorView<T> : public ArrayVectorView<T>
{ {
typedef ArrayVector<T, Alloc> this_type; typedef ArrayVector<T, Alloc> this_type;
enum { minimumCapacity = 2 }; enum { minimumCapacity = 2, resizeFactor = 2 };
public: public:
typedef ArrayVectorView<T> view_type; typedef ArrayVectorView<T> view_type;
typedef typename view_type::value_type value_type; typedef typename view_type::value_type value_type;
typedef typename view_type::reference reference; typedef typename view_type::reference reference;
typedef typename view_type::const_reference const_reference; typedef typename view_type::const_reference const_reference;
typedef typename view_type::pointer pointer; typedef typename view_type::pointer pointer;
typedef typename view_type::const_pointer const_pointer; typedef typename view_type::const_pointer const_pointer;
typedef typename view_type::iterator iterator; typedef typename view_type::iterator iterator;
typedef typename view_type::const_iterator const_iterator; typedef typename view_type::const_iterator const_iterator;
skipping to change at line 510 skipping to change at line 520
explicit ArrayVector(Alloc const & alloc) explicit ArrayVector(Alloc const & alloc)
: view_type(), : view_type(),
capacity_(minimumCapacity), capacity_(minimumCapacity),
alloc_(alloc) alloc_(alloc)
{ {
this->data_ = reserve_raw(capacity_); this->data_ = reserve_raw(capacity_);
} }
explicit ArrayVector( size_type size, Alloc const & alloc = Alloc()) explicit ArrayVector( size_type size, Alloc const & alloc = Alloc())
: view_type(size, 0), : view_type(),
capacity_(size),
alloc_(alloc) alloc_(alloc)
{ {
this->data_ = reserve_raw(capacity_); initImpl(size, value_type(), VigraTrueType());
if(this->size_ > 0)
std::uninitialized_fill(this->data_, this->data_+this->size_, va
lue_type());
} }
ArrayVector( size_type size, value_type const & initial, Alloc const & alloc = Alloc()) ArrayVector( size_type size, value_type const & initial, Alloc const & alloc = Alloc())
: view_type(size, 0), : view_type(),
capacity_(size),
alloc_(alloc) alloc_(alloc)
{ {
this->data_ = reserve_raw(capacity_); initImpl(size, initial, VigraTrueType());
if(this->size_ > 0)
std::uninitialized_fill(this->data_, this->data_+this->size_, i
nitial);
} }
ArrayVector( this_type const & rhs ) ArrayVector( this_type const & rhs )
: view_type(rhs.size(), 0), : view_type(),
capacity_(rhs.capacity_),
alloc_(rhs.alloc_) alloc_(rhs.alloc_)
{ {
this->data_ = reserve_raw(capacity_); initImpl(rhs.begin(), rhs.end(), VigraFalseType());
if(this->size_ > 0)
std::uninitialized_copy(rhs.data_, rhs.data_+rhs.size_, this->d
ata_);
} }
template <class U> template <class U>
explicit ArrayVector( ArrayVectorView<U> const & rhs, Alloc const & all explicit ArrayVector( ArrayVectorView<U> const & rhs, Alloc const & all
oc = Alloc() ); oc = Alloc() )
: view_type(),
alloc_(alloc)
{
initImpl(rhs.begin(), rhs.end(), VigraFalseType());
}
template <class InputIterator> template <class InputIterator>
ArrayVector(InputIterator i, InputIterator end); ArrayVector(InputIterator i, InputIterator end)
{
initImpl(i, end, typename NumericTraits<InputIterator>::isIntegral(
));
}
template <class InputIterator> template <class InputIterator>
ArrayVector(InputIterator i, InputIterator end, Alloc const & alloc); ArrayVector(InputIterator i, InputIterator end, Alloc const & alloc)
: alloc_(alloc)
{
initImpl(i, end, typename NumericTraits<InputIterator>::isIntegral(
));
}
this_type & operator=( this_type const & rhs ) this_type & operator=( this_type const & rhs )
{ {
if(this == &rhs) if(this == &rhs)
return *this; return *this;
if(this->size_ == rhs.size_) if(this->size_ == rhs.size_)
this->copyImpl(rhs); this->copyImpl(rhs);
else else
{ {
ArrayVector t(rhs); ArrayVector t(rhs);
skipping to change at line 611 skipping to change at line 624
} }
void swap(this_type & rhs); void swap(this_type & rhs);
private: private:
void deallocate(pointer data, size_type size); void deallocate(pointer data, size_type size);
pointer reserve_raw(size_type capacity); pointer reserve_raw(size_type capacity);
size_type capacity_; void initImpl( size_type size, value_type const & initial, VigraTrueTyp
Alloc alloc_; e /*isIntegral*/);
};
template <class T, class Alloc> template <class Iter>
template <class U> void initImpl( Iter i, Iter end, VigraFalseType /*isIntegral*/);
ArrayVector<T, Alloc>::ArrayVector( ArrayVectorView<U> const & rhs, Alloc c
onst & alloc )
: view_type(rhs.size(), 0),
capacity_(rhs.size()),
alloc_(alloc)
{
this->data_ = reserve_raw(capacity_);
if(this->size_ > 0)
std::uninitialized_copy(rhs.data(), rhs.data()+rhs.size(), this->da
ta_);
}
template <class T, class Alloc> template <class Iter>
template <class InputIterator> void initImpl( Iter i, Iter end, Error_NumericTraits_not_specialized_fo
ArrayVector<T, Alloc>::ArrayVector(InputIterator i, InputIterator end) r_this_case)
: view_type(std::distance(i, end), 0), {
capacity_(view_type::size_), initImpl(i, end, VigraFalseType());
alloc_() }
{
this->data_ = reserve_raw(capacity_);
std::uninitialized_copy(i, end, this->data_);
}
template <class T, class Alloc> size_type capacity_;
template <class InputIterator> Alloc alloc_;
ArrayVector<T, Alloc>::ArrayVector(InputIterator i, InputIterator end, Allo };
c const & alloc)
: view_type(std::distance(i, end), 0),
capacity_(view_type::size_),
alloc_(alloc)
{
this->data_ = reserve_raw(capacity_);
std::uninitialized_copy(i, end, this->data_);
}
template <class T, class Alloc> template <class T, class Alloc>
template <class U> template <class U>
ArrayVector<T, Alloc> & ArrayVector<T, Alloc>::operator=( ArrayVectorView<U > const & rhs ) ArrayVector<T, Alloc> & ArrayVector<T, Alloc>::operator=( ArrayVectorView<U > const & rhs )
{ {
if(this->size_ == rhs.size()) if(this->size_ == rhs.size())
this->copyImpl(rhs); this->copyImpl(rhs);
else else
{ {
ArrayVector t(rhs); ArrayVector t(rhs);
skipping to change at line 713 skipping to change at line 703
} }
template <class T, class Alloc> template <class T, class Alloc>
typename ArrayVector<T, Alloc>::iterator typename ArrayVector<T, Alloc>::iterator
ArrayVector<T, Alloc>::insert(iterator p, size_type n, value_type const & v ) ArrayVector<T, Alloc>::insert(iterator p, size_type n, value_type const & v )
{ {
difference_type pos = p - this->begin(); difference_type pos = p - this->begin();
size_type new_size = this->size() + n; size_type new_size = this->size() + n;
if(new_size >= capacity_) if(new_size >= capacity_)
{ {
pointer new_data = reserve_raw(new_size); size_type new_capacity = std::max(new_size, resizeFactor*capacity_)
;
pointer new_data = reserve_raw(new_capacity);
std::uninitialized_copy(this->begin(), p, new_data); std::uninitialized_copy(this->begin(), p, new_data);
std::uninitialized_fill(new_data + pos, new_data + pos + n, v); std::uninitialized_fill(new_data + pos, new_data + pos + n, v);
std::uninitialized_copy(p, this->end(), new_data + pos + n); std::uninitialized_copy(p, this->end(), new_data + pos + n);
deallocate(this->data_, this->size_); deallocate(this->data_, this->size_);
capacity_ = new_size; capacity_ = new_capacity;
this->data_ = new_data; this->data_ = new_data;
} }
else if(pos + n >= this->size_) else if(pos + n >= this->size_)
{ {
size_type diff = pos + n - this->size_; size_type diff = pos + n - this->size_;
std::uninitialized_copy(p, this->end(), this->end() + diff); std::uninitialized_copy(p, this->end(), this->end() + diff);
std::uninitialized_fill(this->end(), this->end() + diff, v); std::uninitialized_fill(this->end(), this->end() + diff, v);
std::fill(p, this->end(), v); std::fill(p, this->end(), v);
} }
else else
skipping to change at line 749 skipping to change at line 740
template <class T, class Alloc> template <class T, class Alloc>
template <class InputIterator> template <class InputIterator>
typename ArrayVector<T, Alloc>::iterator typename ArrayVector<T, Alloc>::iterator
ArrayVector<T, Alloc>::insert(iterator p, InputIterator i, InputIterator ie nd) ArrayVector<T, Alloc>::insert(iterator p, InputIterator i, InputIterator ie nd)
{ {
size_type n = iend - i; size_type n = iend - i;
size_type pos = p - this->begin(); size_type pos = p - this->begin();
size_type new_size = this->size() + n; size_type new_size = this->size() + n;
if(new_size >= capacity_) if(new_size >= capacity_)
{ {
pointer new_data = reserve_raw(new_size); size_type new_capacity = std::max(new_size, resizeFactor*capacity_)
;
pointer new_data = reserve_raw(new_capacity);
std::uninitialized_copy(this->begin(), p, new_data); std::uninitialized_copy(this->begin(), p, new_data);
std::uninitialized_copy(i, iend, new_data + pos); std::uninitialized_copy(i, iend, new_data + pos);
std::uninitialized_copy(p, this->end(), new_data + pos + n); std::uninitialized_copy(p, this->end(), new_data + pos + n);
deallocate(this->data_, this->size_); deallocate(this->data_, this->size_);
capacity_ = new_size; capacity_ = new_capacity;
this->data_ = new_data; this->data_ = new_data;
} }
else if(pos + n >= this->size_) else if(pos + n >= this->size_)
{ {
size_type diff = pos + n - this->size_; size_type diff = pos + n - this->size_;
std::uninitialized_copy(p, this->end(), this->end() + diff); std::uninitialized_copy(p, this->end(), this->end() + diff);
std::uninitialized_copy(iend - diff, iend, this->end()); std::uninitialized_copy(iend - diff, iend, this->end());
std::copy(i, iend - diff, p); std::copy(i, iend - diff, p);
} }
else else
skipping to change at line 816 skipping to change at line 808
capacity_ = new_capacity; capacity_ = new_capacity;
} }
template <class T, class Alloc> template <class T, class Alloc>
inline void inline void
ArrayVector<T, Alloc>::reserve() ArrayVector<T, Alloc>::reserve()
{ {
if(capacity_ == 0) if(capacity_ == 0)
reserve(minimumCapacity); reserve(minimumCapacity);
else if(this->size_ == capacity_) else if(this->size_ == capacity_)
reserve(2*capacity_); reserve(resizeFactor*capacity_);
} }
template <class T, class Alloc> template <class T, class Alloc>
inline void inline void
ArrayVector<T, Alloc>::resize( size_type new_size, value_type const & initi al) ArrayVector<T, Alloc>::resize( size_type new_size, value_type const & initi al)
{ {
if(new_size < this->size_) if(new_size < this->size_)
erase(this->begin() + new_size, this->end()); erase(this->begin() + new_size, this->end());
else if(this->size_ < new_size) else if(this->size_ < new_size)
{ {
insert(this->end(), new_size - this->size(), initial); insert(this->end(), new_size - this->size(), initial);
} }
} }
template <class T, class Alloc> template <class T, class Alloc>
inline void inline void
ArrayVector<T, Alloc>::initImpl( size_type size, value_type const & initial
, VigraTrueType /*isIntegral*/)
{
this->size_ = size;
capacity_ = size;
this->data_ = reserve_raw(capacity_);
if(this->size_ > 0)
std::uninitialized_fill(this->data_, this->data_+this->size_, initi
al);
}
template <class T, class Alloc>
template <class Iter>
inline void
ArrayVector<T, Alloc>::initImpl( Iter i, Iter end, VigraFalseType /*isInteg
ral*/)
{
this->size_ = std::distance(i, end);
capacity_ = this->size_;
this->data_ = reserve_raw(capacity_);
if(this->size_ > 0)
std::uninitialized_copy(i, end, this->data_);
}
template <class T, class Alloc>
inline void
ArrayVector<T, Alloc>::swap(this_type & rhs) ArrayVector<T, Alloc>::swap(this_type & rhs)
{ {
std::swap(this->size_, rhs.size_); std::swap(this->size_, rhs.size_);
std::swap(capacity_, rhs.capacity_); std::swap(capacity_, rhs.capacity_);
std::swap(this->data_, rhs.data_); std::swap(this->data_, rhs.data_);
} }
template <class T, class Alloc> template <class T, class Alloc>
inline void inline void
ArrayVector<T, Alloc>::deallocate(pointer data, size_type size) ArrayVector<T, Alloc>::deallocate(pointer data, size_type size)
skipping to change at line 870 skipping to change at line 885
return data; return data;
} }
} // namespace vigra } // namespace vigra
namespace std { namespace std {
template <class T> template <class T>
ostream & operator<<(ostream & s, vigra::ArrayVectorView<T> const & a) ostream & operator<<(ostream & s, vigra::ArrayVectorView<T> const & a)
{ {
for(unsigned int k=0; k<a.size()-1; ++k) for(int k=0; k<(int)a.size()-1; ++k)
s << a[k] << ", "; s << a[k] << ", ";
if(a.size()) if(a.size())
s << a.back(); s << a.back();
return s; return s;
} }
} // namespace std } // namespace std
#undef VIGRA_ASSERT_INSIDE
#endif /* VIGRA_ARRAY_VECTOR_HXX */ #endif /* VIGRA_ARRAY_VECTOR_HXX */
 End of changes. 34 change blocks. 
75 lines changed or deleted 94 lines changed or added


 basicgeometry.hxx   basicgeometry.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 588 skipping to change at line 586
least 2x2. Destiniation pixels are directly copied from the appropriate least 2x2. Destiniation pixels are directly copied from the appropriate
source pixels. The size of the result image is the product of <tt>facto r</tt> source pixels. The size of the result image is the product of <tt>facto r</tt>
and the original size, where we round up if <tt>factor < 1.0</tt> and d own otherwise. and the original size, where we round up if <tt>factor < 1.0</tt> and d own otherwise.
This size calculation is the main difference to the convention used in the similar This size calculation is the main difference to the convention used in the similar
function \ref resizeImageNoInterpolation(): function \ref resizeImageNoInterpolation():
there, the result size is calculated as <tt>n*(old_width-1)+1</tt> and there, the result size is calculated as <tt>n*(old_width-1)+1</tt> and
<tt>n*(old_height-1)+1</tt>. This is because \ref resizeImageNoInterpol ation() <tt>n*(old_height-1)+1</tt>. This is because \ref resizeImageNoInterpol ation()
does not replicate the last pixel in every row/column in order to make it compatible does not replicate the last pixel in every row/column in order to make it compatible
with the other functions of the <tt>resizeImage...</tt> family. with the other functions of the <tt>resizeImage...</tt> family.
The function can be called with different resampling factors for x and
y, or
with a single factor to be used for both directions.
It should also be noted that resampleImage() is implemented so that an enlargement followed It should also be noted that resampleImage() is implemented so that an enlargement followed
by the corresponding shrinking reproduces the original image. The funct ion uses accessors. by the corresponding shrinking reproduces the original image. The funct ion uses accessors.
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa, resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
DestIterator id, DestAccessor ad, double factor); DestIterator id, DestAccessor ad, double factor);
template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor>
void
resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
DestIterator id, DestAccessor ad, double xfactor, dou
ble yfactor);
} }
\endcode \endcode
use argument objects in conjunction with \ref ArgumentObjectFactories : use argument objects in conjunction with \ref ArgumentObjectFactories :
\code \code
namespace vigra { namespace vigra {
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
class DestImageIterator, class DestAccessor> class DestImageIterator, class DestAccessor>
inline void inline void
resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccesso r> src, resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccesso r> src,
pair<DestImageIterator, DestAccessor> dest, double fa ctor); pair<DestImageIterator, DestAccessor> dest, double fa ctor);
template <class SrcImageIterator, class SrcAccessor,
class DestImageIterator, class DestAccessor>
inline void
resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccesso
r> src,
pair<DestImageIterator, DestAccessor> dest, double xf
actor, double yfactor);
} }
\endcode \endcode
<b> Usage:</b> <b> Usage:</b>
<b>\#include</b> \<<a href="basicgeometry_8hxx-source.html">vigra/b asicgeometry.hxx</a>\><br> <b>\#include</b> \<<a href="basicgeometry_8hxx-source.html">vigra/b asicgeometry.hxx</a>\><br>
Namespace: vigra Namespace: vigra
\code \code
double factor = 2.0; double factor = 2.0;
skipping to change at line 654 skipping to change at line 667
src_lowerright.y - src_upperleft.y > 1 src_lowerright.y - src_upperleft.y > 1
\endcode \endcode
*/ */
doxygen_overloaded_function(template <...> void resampleImage) doxygen_overloaded_function(template <...> void resampleImage)
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa, resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
DestIterator id, DestAccessor ad, double factor) DestIterator id, DestAccessor ad, double xfactor, double yfac tor)
{ {
int width_old = iend.x - is.x; int width_old = iend.x - is.x;
int height_old = iend.y - is.y; int height_old = iend.y - is.y;
//Bei Verkleinerung muss das dest-Bild ceiling(src*factor), da z.B. //Bei Verkleinerung muss das dest-Bild ceiling(src*factor), da z.B.
//aus 6x6 grossem Bild wird eins 18x18 grosses gemacht bei Vergroesseru ngsfaktor 3.1 //aus 6x6 grossem Bild wird eins 18x18 grosses gemacht bei Vergroesseru ngsfaktor 3.1
//umgekehrt damit wir vom 18x18 zu 6x6 (und nicht 5x5) bei Vergroesseru ng von 1/3.1 //umgekehrt damit wir vom 18x18 zu 6x6 (und nicht 5x5) bei Vergroesseru ng von 1/3.1
//muss das kleinste Integer das groesser als 18/3.1 ist genommen werden . //muss das kleinste Integer das groesser als 18/3.1 ist genommen werden .
int height_new = sizeForResamplingFactor(height_old, factor); int height_new = sizeForResamplingFactor(height_old, yfactor);
int width_new = sizeForResamplingFactor(width_old, factor); int width_new = sizeForResamplingFactor(width_old, xfactor);
vigra_precondition((width_old > 1) && (height_old > 1), vigra_precondition((width_old > 1) && (height_old > 1),
"resampleImage(): " "resampleImage(): "
"Source image to small.\n"); "Source image to small.\n");
vigra_precondition((width_new > 1) && (height_new > 1), vigra_precondition((width_new > 1) && (height_new > 1),
"resampleImage(): " "resampleImage(): "
"Destination image to small.\n"); "Destination image to small.\n");
typedef typename SrcAccessor::value_type SRCVT; typedef typename SrcAccessor::value_type SRCVT;
typedef BasicImage<SRCVT> TmpImage; typedef BasicImage<SRCVT> TmpImage;
skipping to change at line 687 skipping to change at line 700
BasicImage<SRCVT> tmp(width_old, height_new); BasicImage<SRCVT> tmp(width_old, height_new);
int x,y; int x,y;
typename BasicImage<SRCVT>::Iterator yt = tmp.upperLeft(); typename BasicImage<SRCVT>::Iterator yt = tmp.upperLeft();
for(x=0; x<width_old; ++x, ++is.x, ++yt.x) for(x=0; x<width_old; ++x, ++is.x, ++yt.x)
{ {
typename SrcIterator::column_iterator c1 = is.columnIterator(); typename SrcIterator::column_iterator c1 = is.columnIterator();
typename TmpImageIterator::column_iterator ct = yt.columnIterator() ; typename TmpImageIterator::column_iterator ct = yt.columnIterator() ;
resampleLine(c1, c1 + height_old, sa, ct, tmp.accessor(), factor); resampleLine(c1, c1 + height_old, sa, ct, tmp.accessor(), yfactor);
} }
yt = tmp.upperLeft(); yt = tmp.upperLeft();
for(y=0; y < height_new; ++y, ++yt.y, ++id.y) for(y=0; y < height_new; ++y, ++yt.y, ++id.y)
{ {
typename DestIterator::row_iterator rd = id.rowIterator(); typename DestIterator::row_iterator rd = id.rowIterator();
typename TmpImageIterator::row_iterator rt = yt.rowIterator(); typename TmpImageIterator::row_iterator rt = yt.rowIterator();
resampleLine(rt, rt + width_old, tmp.accessor(), rd, ad, factor); resampleLine(rt, rt + width_old, tmp.accessor(), rd, ad, xfactor);
} }
} }
template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor>
void
resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
DestIterator id, DestAccessor ad, double factor)
{
resampleImage(is, iend, sa, id, ad, factor, factor);
}
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
class DestImageIterator, class DestAccessor> class DestImageIterator, class DestAccessor>
inline void inline void
resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
pair<DestImageIterator, DestAccessor> dest, double factor) pair<DestImageIterator, DestAccessor> dest, double factor)
{ {
resampleImage(src.first, src.second, src.third, dest.first, dest.second resampleImage(src.first, src.second, src.third, dest.first, dest.second,
, factor); factor);
}
template <class SrcImageIterator, class SrcAccessor,
class DestImageIterator, class DestAccessor>
inline void
resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
pair<DestImageIterator, DestAccessor> dest, double xfactor, d
ouble yfactor)
{
resampleImage(src.first, src.second, src.third, dest.first, dest.second,
xfactor, yfactor);
} }
//@} //@}
} // namespace vigra } // namespace vigra
#endif /* VIGRA_BASICGEOMETRY_HXX */ #endif /* VIGRA_BASICGEOMETRY_HXX */
 End of changes. 12 change blocks. 
10 lines changed or deleted 47 lines changed or added


 basicimage.hxx   basicimage.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 46 skipping to change at line 44
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_BASICIMAGE_HXX #ifndef VIGRA_BASICIMAGE_HXX
#define VIGRA_BASICIMAGE_HXX #define VIGRA_BASICIMAGE_HXX
#include <memory> #include <memory>
#include <algorithm> #include <algorithm>
#include "utilities.hxx" #include "utilities.hxx"
#include "iteratortraits.hxx" #include "iteratortraits.hxx"
#include "accessor.hxx" #include "accessor.hxx"
#include "memory.hxx"
// Bounds checking Macro used if VIGRA_CHECK_BOUNDS is defined.
#ifdef VIGRA_CHECK_BOUNDS
#define VIGRA_ASSERT_INSIDE(diff) \
vigra_precondition(this->isInside(diff), "Index out of bounds")
#else
#define VIGRA_ASSERT_INSIDE(diff)
#endif
namespace vigra { namespace vigra {
template <class IMAGEITERATOR> template <class IMAGEITERATOR>
class LineBasedColumnIteratorPolicy class LineBasedColumnIteratorPolicy
{ {
public: public:
typedef IMAGEITERATOR ImageIterator; typedef IMAGEITERATOR ImageIterator;
typedef typename IMAGEITERATOR::LineStartIterator LineStartIterator; typedef typename IMAGEITERATOR::LineStartIterator LineStartIterator;
typedef typename IMAGEITERATOR::value_type value_type; typedef typename IMAGEITERATOR::value_type value_type;
skipping to change at line 175 skipping to change at line 182
{ {
IMAGEITERATOR ret(static_cast<IMAGEITERATOR const &>(*this)); IMAGEITERATOR ret(static_cast<IMAGEITERATOR const &>(*this));
ret -= s; ret -= s;
return ret; return ret;
} }
difference_type operator-(BasicImageIteratorBase const & rhs) const difference_type operator-(BasicImageIteratorBase const & rhs) const
{ {
return difference_type(x - rhs.x, y - rhs.y); return difference_type(difference_type::MoveX(x - rhs.x),
difference_type::MoveY(y - rhs.y));
} }
bool operator==(BasicImageIteratorBase const & rhs) const bool operator==(BasicImageIteratorBase const & rhs) const
{ {
return (x == rhs.x) && (y == rhs.y); return (x == rhs.x) && (y == rhs.y);
} }
bool operator!=(BasicImageIteratorBase const & rhs) const bool operator!=(BasicImageIteratorBase const & rhs) const
{ {
return (x != rhs.x) || (y != rhs.y); return (x != rhs.x) || (y != rhs.y);
skipping to change at line 642 skipping to change at line 650
allocator_(alloc), allocator_(alloc),
pallocator_(alloc) pallocator_(alloc)
{ {
vigra_precondition((width >= 0) && (height >= 0), vigra_precondition((width >= 0) && (height >= 0),
"BasicImage::BasicImage(int width, int height, value_type cons t & ): " "BasicImage::BasicImage(int width, int height, value_type cons t & ): "
"width and height must be >= 0.\n"); "width and height must be >= 0.\n");
resize(width, height, d); resize(width, height, d);
} }
/** construct image of size width*height and try to skip initializa
tion
of the memory (see BasicImage::resize for details).
Use the specified allocator.
*/
BasicImage(int width, int height, SkipInitializationTag, Alloc const &
alloc = Alloc())
: data_(0),
width_(0),
height_(0),
allocator_(alloc),
pallocator_(alloc)
{
vigra_precondition((width >= 0) && (height >= 0),
"BasicImage::BasicImage(int width, int height, value_type cons
t & ): "
"width and height must be >= 0.\n");
resize(width, height, SkipInitialization);
}
/** construct image of size size.x x size.y and initialize /** construct image of size size.x x size.y and initialize
every pixel with given data (use this constructor, if every pixel with given data (use this constructor, if
value_type doesn't have a default constructor). Use the specified a llocator. value_type doesn't have a default constructor). Use the specified a llocator.
*/ */
explicit BasicImage(difference_type const & size, value_type const & d, Alloc const & alloc = Alloc()) explicit BasicImage(difference_type const & size, value_type const & d, Alloc const & alloc = Alloc())
: data_(0), : data_(0),
width_(0), width_(0),
height_(0), height_(0),
allocator_(alloc), allocator_(alloc),
pallocator_(alloc) pallocator_(alloc)
{ {
vigra_precondition((size.x >= 0) && (size.y >= 0), vigra_precondition((size.x >= 0) && (size.y >= 0),
"BasicImage::BasicImage(Diff2D const & size, value_type const & v): " "BasicImage::BasicImage(Diff2D const & size, value_type const & v): "
"size.x and size.y must be >= 0.\n"); "size.x and size.y must be >= 0.\n");
resize(size.x, size.y, d); resize(size.x, size.y, d);
} }
/** construct image of size size.x x size.y and try to skip initial
ization
of the memory (see BasicImage::resize for details). Use the spe
cified allocator.
*/
explicit BasicImage(difference_type const & size, SkipInitializationTag
, Alloc const & alloc = Alloc())
: data_(0),
width_(0),
height_(0),
allocator_(alloc),
pallocator_(alloc)
{
vigra_precondition((size.x >= 0) && (size.y >= 0),
"BasicImage::BasicImage(Diff2D const & size, value_type const
& v): "
"size.x and size.y must be >= 0.\n");
resize(size.x, size.y, SkipInitialization);
}
/** construct image of size width*height and copy the data from the /** construct image of size width*height and copy the data from the
given C-style array \a d. Use the specified allocator. given C-style array \a d. Use the specified allocator.
*/ */
BasicImage(int width, int height, const_pointer d, Alloc const & alloc = Alloc()) BasicImage(int width, int height, const_pointer d, Alloc const & alloc = Alloc())
: data_(0), : data_(0),
width_(0), width_(0),
height_(0), height_(0),
allocator_(alloc), allocator_(alloc),
pallocator_(alloc) pallocator_(alloc)
{ {
skipping to change at line 750 skipping to change at line 793
{ {
resize(size.x, size.y, value_type()); resize(size.x, size.y, value_type());
} }
} }
/** reset image to specified size and initialize it with /** reset image to specified size and initialize it with
given data (use this if value_type doesn't have a default given data (use this if value_type doesn't have a default
constructor, dimensions must not be negative, constructor, dimensions must not be negative,
old data are kept if new size matches old size) old data are kept if new size matches old size)
*/ */
void resize(int width, int height, value_type const & d); void resize(int width, int height, value_type const & d)
{
resizeImpl(width, height, d, false);
}
/** reset image to specified size and skip initialization
if possible (use this if <tt>value_type</tt> is a built-in type
or <tt>TinyVector&lt;builtin&gt&</tt> and the data is
immediately overridden afterwards). If <tt>value_type</tt> requ
ires
initialization, <tt>SkipInitialization</tt> is ignored.
Usage:
\code
image.resize(new_width, new_height, SkipInitialization);
\endcode
*/
void resize(int width, int height, SkipInitializationTag)
{
resizeImpl(width, height, NumericTraits<value_type>::zero(),
CanSkipInitialization<value_type>::value);
}
/** resize image to given size and initialize by copying data /** resize image to given size and initialize by copying data
from the C-style arra \a data. from the C-style arra \a data.
*/ */
void resizeCopy(int width, int height, const_pointer data); void resizeCopy(int width, int height, const_pointer data);
/** resize image to size of other image and copy it's data /** resize image to size of other image and copy it's data
*/ */
void resizeCopy(const BasicImage & rhs) void resizeCopy(const BasicImage & rhs)
{ {
skipping to change at line 802 skipping to change at line 865
{ {
return d.x >= 0 && d.y >= 0 && return d.x >= 0 && d.y >= 0 &&
d.x < width() && d.y < height(); d.x < width() && d.y < height();
} }
/** access pixel at given location. <br> /** access pixel at given location. <br>
usage: <TT> value_type value = image[Diff2D(1,2)] </TT> usage: <TT> value_type value = image[Diff2D(1,2)] </TT>
*/ */
reference operator[](difference_type const & d) reference operator[](difference_type const & d)
{ {
VIGRA_ASSERT_INSIDE(d);
return lines_[d.y][d.x]; return lines_[d.y][d.x];
} }
/** read pixel at given location. <br> /** read pixel at given location. <br>
usage: <TT> value_type value = image[Diff2D(1,2)] </TT> usage: <TT> value_type value = image[Diff2D(1,2)] </TT>
*/ */
const_reference operator[](difference_type const & d) const const_reference operator[](difference_type const & d) const
{ {
VIGRA_ASSERT_INSIDE(d);
return lines_[d.y][d.x]; return lines_[d.y][d.x];
} }
/** access pixel at given location. <br> /** access pixel at given location. <br>
usage: <TT> value_type value = image(1,2) </TT> usage: <TT> value_type value = image(1,2) </TT>
*/ */
reference operator()(int dx, int dy) reference operator()(int dx, int dy)
{ {
VIGRA_ASSERT_INSIDE(difference_type(dx,dy));
return lines_[dy][dx]; return lines_[dy][dx];
} }
/** read pixel at given location. <br> /** read pixel at given location. <br>
usage: <TT> value_type value = image(1,2) </TT> usage: <TT> value_type value = image(1,2) </TT>
*/ */
const_reference operator()(int dx, int dy) const const_reference operator()(int dx, int dy) const
{ {
VIGRA_ASSERT_INSIDE(difference_type(dx,dy));
return lines_[dy][dx]; return lines_[dy][dx];
} }
/** access pixel at given location. /** access pixel at given location.
Note that the 'x' index is the trailing index. <br> Note that the 'x' index is the trailing index. <br>
usage: <TT> value_type value = image[2][1] </TT> usage: <TT> value_type value = image[2][1] </TT>
*/ */
pointer operator[](int dy) pointer operator[](int dy)
{ {
VIGRA_ASSERT_INSIDE(difference_type(0,dy));
return lines_[dy]; return lines_[dy];
} }
/** read pixel at given location. /** read pixel at given location.
Note that the 'x' index is the trailing index. <br> Note that the 'x' index is the trailing index. <br>
usage: <TT> value_type value = image[2][1] </TT> usage: <TT> value_type value = image[2][1] </TT>
*/ */
const_pointer operator[](int dy) const const_pointer operator[](int dy) const
{ {
VIGRA_ASSERT_INSIDE(difference_type(0,dy));
return lines_[dy]; return lines_[dy];
} }
/** init 2D random access iterator poining to upper left pixel /** init 2D random access iterator poining to upper left pixel
*/ */
traverser upperLeft() traverser upperLeft()
{ {
vigra_precondition(data_ != 0, vigra_precondition(data_ != 0,
"BasicImage::upperLeft(): image must have non-zero size."); "BasicImage::upperLeft(): image must have non-zero size.");
return traverser(lines_); return traverser(lines_);
skipping to change at line 1005 skipping to change at line 1074
/** return default const accessor /** return default const accessor
*/ */
ConstAccessor accessor() const ConstAccessor accessor() const
{ {
return ConstAccessor(); return ConstAccessor();
} }
private: private:
void deallocate(); void deallocate();
void resizeImpl(int width, int height, value_type const & d, bool skipI nit);
value_type ** initLineStartArray(value_type * data, int width, int heig ht); value_type ** initLineStartArray(value_type * data, int width, int heig ht);
PIXELTYPE * data_; PIXELTYPE * data_;
PIXELTYPE ** lines_; PIXELTYPE ** lines_;
int width_, height_; int width_, height_;
Alloc allocator_; Alloc allocator_;
LineAllocator pallocator_; LineAllocator pallocator_;
}; };
skipping to change at line 1064 skipping to change at line 1134
ScanOrderIterator i = begin(); ScanOrderIterator i = begin();
ScanOrderIterator iend = end(); ScanOrderIterator iend = end();
for(; i != iend; ++i) *i = pixel; for(; i != iend; ++i) *i = pixel;
return *this; return *this;
} }
template <class PIXELTYPE, class Alloc> template <class PIXELTYPE, class Alloc>
void void
BasicImage<PIXELTYPE, Alloc>::resize(int width, int height, value_type cons t & d) BasicImage<PIXELTYPE, Alloc>::resizeImpl(int width, int height, value_type const & d, bool skipInit)
{ {
vigra_precondition((width >= 0) && (height >= 0), vigra_precondition((width >= 0) && (height >= 0),
"BasicImage::resize(int width, int height, value_type const &): " "BasicImage::resize(int width, int height, value_type const &): "
"width and height must be >= 0.\n"); "width and height must be >= 0.\n");
vigra_precondition(width * height >= 0,
"BasicImage::resize(int width, int height, value_type const &): "
"width * height too large (integer overflow -> negative).\n");
if (width_ != width || height_ != height) // change size? if (width_ != width || height_ != height) // change size?
{ {
value_type * newdata = 0; value_type * newdata = 0;
value_type ** newlines = 0; value_type ** newlines = 0;
if(width*height > 0) if(width*height > 0)
{ {
if (width*height != width_*height_) // different sizes, must re allocate if (width*height != width_*height_) // different sizes, must re allocate
{ {
newdata = allocator_.allocate(typename Alloc::size_type(wid th*height)); newdata = allocator_.allocate(typename Alloc::size_type(wid th*height));
std::uninitialized_fill_n(newdata, width*height, d); if(!skipInit)
std::uninitialized_fill_n(newdata, width*height, d);
newlines = initLineStartArray(newdata, width, height); newlines = initLineStartArray(newdata, width, height);
deallocate(); deallocate();
} }
else // need only to reshape else // need only to reshape
{ {
newdata = data_; newdata = data_;
std::fill_n(newdata, width*height, d); if(!skipInit)
std::fill_n(newdata, width*height, d);
newlines = initLineStartArray(newdata, width, height); newlines = initLineStartArray(newdata, width, height);
pallocator_.deallocate(lines_, typename Alloc::size_type(he ight_)); pallocator_.deallocate(lines_, typename Alloc::size_type(he ight_));
} }
} }
else else
{ {
deallocate(); deallocate();
} }
data_ = newdata; data_ = newdata;
lines_ = newlines; lines_ = newlines;
width_ = width; width_ = width;
height_ = height; height_ = height;
} }
else if(width*height > 0) // keep size, re-init data else if(width*height > 0 && !skipInit) // keep size, re-init data
{ {
std::fill_n(data_, width*height, d); std::fill_n(data_, width*height, d);
} }
} }
template <class PIXELTYPE, class Alloc> template <class PIXELTYPE, class Alloc>
void void
BasicImage<PIXELTYPE, Alloc>::resizeCopy(int width, int height, const_point er data) BasicImage<PIXELTYPE, Alloc>::resizeCopy(int width, int height, const_point er data)
{ {
int newsize = width*height; int newsize = width*height;
skipping to change at line 1429 skipping to change at line 1504
maskImage(BasicImage<PixelType, Alloc> const & img, Point2D const & ul) maskImage(BasicImage<PixelType, Alloc> const & img, Point2D const & ul)
{ {
vigra_precondition(img.isInside(ul), vigra_precondition(img.isInside(ul),
"maskImage(): ROI rectangle outside image."); "maskImage(): ROI rectangle outside image.");
return pair<typename BasicImage<PixelType, Alloc>::const_traverser, return pair<typename BasicImage<PixelType, Alloc>::const_traverser,
typename BasicImage<PixelType, Alloc>::ConstAccessor>(img.u pperLeft() + ul, typename BasicImage<PixelType, Alloc>::ConstAccessor>(img.u pperLeft() + ul,
img.a ccessor()); img.a ccessor());
} }
} // namespace vigra } // namespace vigra
#undef VIGRA_ASSERT_INSIDE
#endif // VIGRA_BASICIMAGE_HXX #endif // VIGRA_BASICIMAGE_HXX
 End of changes. 21 change blocks. 
10 lines changed or deleted 93 lines changed or added


 basicimageview.hxx   basicimageview.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 44 skipping to change at line 42
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_BASICIMAGEVIEW_HXX #ifndef VIGRA_BASICIMAGEVIEW_HXX
#define VIGRA_BASICIMAGEVIEW_HXX #define VIGRA_BASICIMAGEVIEW_HXX
#include "imageiterator.hxx" #include "imageiterator.hxx"
#include "initimage.hxx" #include "initimage.hxx"
// Bounds checking Macro used if VIGRA_CHECK_BOUNDS is defined.
#ifdef VIGRA_CHECK_BOUNDS
#define VIGRA_ASSERT_INSIDE(diff) \
vigra_precondition(this->isInside(diff), "Index out of bounds")
#else
#define VIGRA_ASSERT_INSIDE(diff)
#endif
namespace vigra { namespace vigra {
/********************************************************/ /********************************************************/
/* */ /* */
/* BasicImageView */ /* BasicImageView */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief BasicImage using foreign memory. /** \brief BasicImage using foreign memory.
skipping to change at line 245 skipping to change at line 251
{ {
return d.x >= 0 && d.y >= 0 && return d.x >= 0 && d.y >= 0 &&
d.x < width() && d.y < height(); d.x < width() && d.y < height();
} }
/** access pixel at given location. <br> /** access pixel at given location. <br>
usage: <TT> value_type value = image[Diff2D(1,2)] </TT> usage: <TT> value_type value = image[Diff2D(1,2)] </TT>
*/ */
reference operator[](difference_type const & d) reference operator[](difference_type const & d)
{ {
VIGRA_ASSERT_INSIDE(d);
return data_[d.y*stride_ + d.x]; return data_[d.y*stride_ + d.x];
} }
/** read pixel at given location. <br> /** read pixel at given location. <br>
usage: <TT> value_type value = image[Diff2D(1,2)] </TT> usage: <TT> value_type value = image[Diff2D(1,2)] </TT>
*/ */
const_reference operator[](difference_type const & d) const const_reference operator[](difference_type const & d) const
{ {
VIGRA_ASSERT_INSIDE(difference_type(d));
return data_[d.y*stride_ + d.x]; return data_[d.y*stride_ + d.x];
} }
/** access pixel at given location. <br> /** access pixel at given location. <br>
usage: <TT> value_type value = image(1,2) </TT> usage: <TT> value_type value = image(1,2) </TT>
*/ */
reference operator()(int dx, int dy) reference operator()(int dx, int dy)
{ {
VIGRA_ASSERT_INSIDE(difference_type(dx,dy));
return data_[dy*stride_ + dx]; return data_[dy*stride_ + dx];
} }
/** read pixel at given location. <br> /** read pixel at given location. <br>
usage: <TT> value_type value = image(1,2) </TT> usage: <TT> value_type value = image(1,2) </TT>
*/ */
const_reference operator()(int dx, int dy) const const_reference operator()(int dx, int dy) const
{ {
VIGRA_ASSERT_INSIDE(difference_type(dx, dy));
return data_[dy*stride_ + dx]; return data_[dy*stride_ + dx];
} }
/** access pixel at given location. /** access pixel at given location.
Note that the 'x' index is the trailing index. <br> Note that the 'x' index is the trailing index. <br>
usage: <TT> value_type value = image[2][1] </TT> usage: <TT> value_type value = image[2][1] </TT>
*/ */
pointer operator[](int dy) pointer operator[](int dy)
{ {
VIGRA_ASSERT_INSIDE(difference_type(0, dy));
return data_ + dy*stride_; return data_ + dy*stride_;
} }
/** read pixel at given location. /** read pixel at given location.
Note that the 'x' index is the trailing index. <br> Note that the 'x' index is the trailing index. <br>
usage: <TT> value_type value = image[2][1] </TT> usage: <TT> value_type value = image[2][1] </TT>
*/ */
const_pointer operator[](int dy) const const_pointer operator[](int dy) const
{ {
VIGRA_ASSERT_INSIDE(difference_type(0,dy));
return data_ + dy*stride_; return data_ + dy*stride_;
} }
/** init 2D random access iterator poining to upper left pixel /** init 2D random access iterator poining to upper left pixel
*/ */
traverser upperLeft() traverser upperLeft()
{ {
return traverser(data_, stride_); return traverser(data_, stride_);
} }
skipping to change at line 692 skipping to change at line 704
maskImage(BasicImageView<PixelType> const & img, Point2D const & ul) maskImage(BasicImageView<PixelType> const & img, Point2D const & ul)
{ {
vigra_precondition(img.isInside(ul), vigra_precondition(img.isInside(ul),
"maskImage(): ROI rectangle outside image."); "maskImage(): ROI rectangle outside image.");
return pair<typename BasicImageView<PixelType>::const_traverser, return pair<typename BasicImageView<PixelType>::const_traverser,
typename BasicImageView<PixelType>::ConstAccessor>(img.uppe rLeft() + ul, typename BasicImageView<PixelType>::ConstAccessor>(img.uppe rLeft() + ul,
img.a ccessor()); img.a ccessor());
} }
} // namespace vigra } // namespace vigra
#undef VIGRA_ASSERT_INSIDE
#endif /* VIGRA_BASICIMAGEVIEW_HXX */ #endif /* VIGRA_BASICIMAGEVIEW_HXX */
 End of changes. 11 change blocks. 
4 lines changed or deleted 16 lines changed or added


 bordertreatment.hxx   bordertreatment.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 boundarytensor.hxx   boundarytensor.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2004 by Ullrich Koethe */ /* Copyright 1998-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 58 skipping to change at line 56
#include "convolution.hxx" #include "convolution.hxx"
namespace vigra { namespace vigra {
namespace detail { namespace detail {
/***********************************************************************/ /***********************************************************************/
typedef ArrayVector<Kernel1D<double> > KernelArray; typedef ArrayVector<Kernel1D<double> > KernelArray;
template <class KernelArray>
void void
initGaussianPolarFilters1(double std_dev, KernelArray & k) initGaussianPolarFilters1(double std_dev, KernelArray & k)
{ {
typedef KernelArray::value_type Kernel; typedef typename KernelArray::value_type Kernel;
typedef Kernel::iterator iterator; typedef typename Kernel::iterator iterator;
vigra_precondition(std_dev >= 0.0, vigra_precondition(std_dev >= 0.0,
"initGaussianPolarFilter1(): " "initGaussianPolarFilter1(): "
"Standard deviation must be >= 0."); "Standard deviation must be >= 0.");
k.resize(4); k.resize(4);
int radius = (int)(4.0*std_dev + 0.5); int radius = (int)(4.0*std_dev + 0.5);
std_dev *= 1.08179074376; std_dev *= 1.08179074376;
double f = 1.0 / VIGRA_CSTD::sqrt(2.0 * M_PI) / std_dev; // norm double f = 1.0 / VIGRA_CSTD::sqrt(2.0 * M_PI) / std_dev; // norm
skipping to change at line 114 skipping to change at line 113
} }
c = k[3].center(); c = k[3].center();
for(ix=-radius; ix<=radius; ++ix) for(ix=-radius; ix<=radius; ++ix)
{ {
double x = (double)ix; double x = (double)ix;
c[ix] = f * x * (b + a * x * x) * VIGRA_CSTD::exp(sigma22 * x * x); c[ix] = f * x * (b + a * x * x) * VIGRA_CSTD::exp(sigma22 * x * x);
} }
} }
template <class KernelArray>
void void
initGaussianPolarFilters2(double std_dev, KernelArray & k) initGaussianPolarFilters2(double std_dev, KernelArray & k)
{ {
typedef Kernel1D<double>::iterator iterator; typedef typename KernelArray::value_type Kernel;
typedef typename Kernel::iterator iterator;
vigra_precondition(std_dev >= 0.0, vigra_precondition(std_dev >= 0.0,
"initGaussianPolarFilter2(): " "initGaussianPolarFilter2(): "
"Standard deviation must be >= 0."); "Standard deviation must be >= 0.");
k.resize(3); k.resize(3);
int radius = (int)(4.0*std_dev + 0.5); int radius = (int)(4.0*std_dev + 0.5);
double f = 1.0 / VIGRA_CSTD::sqrt(2.0 * M_PI) / std_dev; // norm double f = 1.0 / VIGRA_CSTD::sqrt(2.0 * M_PI) / std_dev; // norm
double sigma2 = std_dev*std_dev; double sigma2 = std_dev*std_dev;
skipping to change at line 161 skipping to change at line 162
c = k[2].center(); c = k[2].center();
double f2 = f / (sigma2 * sigma2); double f2 = f / (sigma2 * sigma2);
for(ix=-radius; ix<=radius; ++ix) for(ix=-radius; ix<=radius; ++ix)
{ {
double x = (double)ix; double x = (double)ix;
c[ix] = f2 * (x * x - sigma2) * VIGRA_CSTD::exp(sigma22 * x * x); c[ix] = f2 * (x * x - sigma2) * VIGRA_CSTD::exp(sigma22 * x * x);
} }
} }
template <class KernelArray>
void void
initGaussianPolarFilters3(double std_dev, KernelArray & k) initGaussianPolarFilters3(double std_dev, KernelArray & k)
{ {
typedef Kernel1D<double>::iterator iterator; typedef typename KernelArray::value_type Kernel;
typedef typename Kernel::iterator iterator;
vigra_precondition(std_dev >= 0.0, vigra_precondition(std_dev >= 0.0,
"initGaussianPolarFilter3(): " "initGaussianPolarFilter3(): "
"Standard deviation must be >= 0."); "Standard deviation must be >= 0.");
k.resize(4); k.resize(4);
int radius = (int)(4.0*std_dev + 0.5); int radius = (int)(4.0*std_dev + 0.5);
std_dev *= 1.15470053838; std_dev *= 1.15470053838;
double sigma22 = -0.5 / std_dev / std_dev; double sigma22 = -0.5 / std_dev / std_dev;
skipping to change at line 262 skipping to change at line 265
TmpTraverser tlr(t.lowerRight()); TmpTraverser tlr(t.lowerRight());
for(; tul.y != tlr.y; ++tul.y, ++dupperleft.y) for(; tul.y != tlr.y; ++tul.y, ++dupperleft.y)
{ {
typename TmpTraverser::row_iterator tr = tul.rowIterator(); typename TmpTraverser::row_iterator tr = tul.rowIterator();
typename TmpTraverser::row_iterator trend = tr + w; typename TmpTraverser::row_iterator trend = tr + w;
typename DestIterator::row_iterator d = dupperleft.rowIterator(); typename DestIterator::row_iterator d = dupperleft.rowIterator();
if(noLaplacian) if(noLaplacian)
{ {
for(; tr != trend; ++tr, ++d) for(; tr != trend; ++tr, ++d)
{ {
TmpType v = 0.5*sq((*tr)[0]-(*tr)[2]) + 2.0*sq((*tr)[1]); TmpType v = detail::RequiresExplicitCast<TmpType>::cast(0.5 *sq((*tr)[0]-(*tr)[2]) + 2.0*sq((*tr)[1]));
dest.setComponent(v, d, 0); dest.setComponent(v, d, 0);
dest.setComponent(0, d, 1); dest.setComponent(0, d, 1);
dest.setComponent(v, d, 2); dest.setComponent(v, d, 2);
} }
} }
else else
{ {
for(; tr != trend; ++tr, ++d) for(; tr != trend; ++tr, ++d)
{ {
dest.setComponent(sq((*tr)[0]) + sq((*tr)[1]), d, 0); dest.setComponent(sq((*tr)[0]) + sq((*tr)[1]), d, 0);
skipping to change at line 543 skipping to change at line 546
/* */ /* */
/* boundaryTensor */ /* boundaryTensor */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Calculate the boundary tensor for a scalar valued image. /** \brief Calculate the boundary tensor for a scalar valued image.
These functions calculate a spatial domain approximation of These functions calculate a spatial domain approximation of
the boundary tensor as described in the boundary tensor as described in
U. K&ouml;the: <a href="http://kogs-www.informatik.uni-hamburg.de/~koet he/papers/abstracts/polarfilters.html"> U. K&ouml;the: <a href="http://hci.iwr.uni-heidelberg.de/people/ukoethe /papers/index.php#cite_polarfilters">
<i>"Integrated Edge and Junction Detection with the Boundary Tensor"</i ></a>, <i>"Integrated Edge and Junction Detection with the Boundary Tensor"</i ></a>,
in: ICCV 03, Proc. of 9th Intl. Conf. on Computer Vision, Nice 2003, v ol. 1, in: ICCV 03, Proc. of 9th Intl. Conf. on Computer Vision, Nice 2003, v ol. 1,
pp. 424-431, Los Alamitos: IEEE Computer Society, 2003 pp. 424-431, Los Alamitos: IEEE Computer Society, 2003
with the Laplacian of Gaussian as the underlying bandpass filter (see with the Laplacian of Gaussian as the underlying bandpass filter (see
\ref rieszTransformOfLOG()). The output image must have 3 bands which w ill hold the \ref rieszTransformOfLOG()). The output image must have 3 bands which w ill hold the
tensor components in the order t11, t12 (== t21), t22. The function tensor components in the order t11, t12 (== t21), t22. The function
\ref boundaryTensor1() with the same interface implements a variant of the \ref boundaryTensor1() with the same interface implements a variant of the
boundary tensor where the 0th-order Riesz transform has been dropped, s o that the boundary tensor where the 0th-order Riesz transform has been dropped, s o that the
tensor is no longer sensitive to blobs. tensor is no longer sensitive to blobs.
 End of changes. 11 change blocks. 
9 lines changed or deleted 12 lines changed or added


 codec.hxx   codec.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2001-2002 by Gunnar Kedenburg */ /* Copyright 2001-2002 by Gunnar Kedenburg */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 167 skipping to change at line 165
virtual unsigned int getNumExtraBands() const virtual unsigned int getNumExtraBands() const
{ {
return 0; return 0;
} }
virtual vigra::Diff2D getPosition() const virtual vigra::Diff2D getPosition() const
{ {
return vigra::Diff2D(); return vigra::Diff2D();
} }
virtual float getXResolution() const
{
return 0.0f;
}
virtual float getYResolution() const
{
return 0.0f;
}
virtual unsigned int getOffset() const = 0; virtual unsigned int getOffset() const = 0;
virtual const void * currentScanlineOfBand( unsigned int ) const = 0; virtual const void * currentScanlineOfBand( unsigned int ) const = 0;
virtual void nextScanline() = 0; virtual void nextScanline() = 0;
typedef ArrayVector<unsigned char> ICCProfile; typedef ArrayVector<unsigned char> ICCProfile;
const ICCProfile & getICCProfile() const const ICCProfile & getICCProfile() const
{ {
return iccProfile_; return iccProfile_;
 End of changes. 4 change blocks. 
3 lines changed or deleted 10 lines changed or added


 colorconversions.hxx   colorconversions.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 51 skipping to change at line 49
#include <cmath> #include <cmath>
#include "mathutil.hxx" #include "mathutil.hxx"
#include "rgbvalue.hxx" #include "rgbvalue.hxx"
#include "functortraits.hxx" #include "functortraits.hxx"
namespace vigra { namespace vigra {
namespace detail namespace detail
{ {
inline double gammaCorrection(double value, double gamma) template<class ValueType>
inline ValueType gammaCorrection(double value, double gamma)
{ {
return (value < 0.0) ? typedef typename NumericTraits<ValueType>::RealPromote Promote;
-VIGRA_CSTD::pow(-value, gamma) : return NumericTraits<ValueType>::fromRealPromote(
VIGRA_CSTD::pow(value, gamma); RequiresExplicitCast<Promote>::cast(
(value < 0.0)
? -std::pow(-value, gamma)
: std::pow(value, gamma)));
} }
inline double gammaCorrection(double value, double gamma, double norm) template<class ValueType>
inline ValueType gammaCorrection(double value, double gamma, double norm)
{ {
return (value < 0.0) ? typedef typename NumericTraits<ValueType>::RealPromote Promote;
-norm*VIGRA_CSTD::pow(-value/norm, gamma) : return NumericTraits<ValueType>::fromRealPromote(
norm*VIGRA_CSTD::pow(value/norm, gamma); RequiresExplicitCast<Promote>::cast(
(value < 0.0)
? -norm*std::pow(-value/norm, gamma)
: norm*std::pow(value/norm, gamma)));
} }
inline double sRGBCorrection(double value, double norm) template<class ValueType>
inline ValueType sRGBCorrection(double value, double norm)
{ {
value /= norm; value /= norm;
return (value <= 0.00304) typedef typename NumericTraits<ValueType>::RealPromote Promote;
? norm*12.92*value return NumericTraits<ValueType>::fromRealPromote(
: norm*(1.055*VIGRA_CSTD::pow(value, 0.41666666666666667) - RequiresExplicitCast<ValueType>::cast(
0.055); (value <= 0.0031308)
? norm*12.92*value
: norm*(1.055*std::pow(value, 0.41666666666666667) - 0.
055)));
} }
inline double inverse_sRGBCorrection(double value, double norm) template<class ValueType>
inline ValueType inverse_sRGBCorrection(double value, double norm)
{ {
value /= norm; value /= norm;
return (value <= 0.03928) typedef typename NumericTraits<ValueType>::RealPromote Promote;
? norm*value / 12.92 return NumericTraits<ValueType>::fromRealPromote(
: norm*VIGRA_CSTD::pow((value + 0.055)/1.055, 2.4); RequiresExplicitCast<ValueType>::cast(
(value <= 0.04045)
? norm*value / 12.92
: norm*VIGRA_CSTD::pow((value + 0.055)/1.055, 2.4)));
} }
} // namespace detail } // namespace detail
/** \defgroup ColorConversions Color Space Conversions /** \defgroup ColorConversions Color Space Conversions
Convert between RGB, sRGB, R'G'B', XYZ, L*a*b*, L*u*v*, Y'PbPr, Y'CbCr, Y'IQ, and Y'UV color spaces. Convert between RGB, sRGB, R'G'B', XYZ, L*a*b*, L*u*v*, Y'PbPr, Y'CbCr, Y'IQ, and Y'UV color spaces.
<b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br> <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br>
Namespace: vigra Namespace: vigra
skipping to change at line 269 skipping to change at line 283
class RGB2RGBPrimeFunctor class RGB2RGBPrimeFunctor
{ {
public: public:
/** the functor's argument type /** the functor's argument type
*/ */
typedef TinyVector<From, 3> argument_type; typedef TinyVector<From, 3> argument_type;
/** the functor's result type /** the functor's result type
*/ */
typedef RGBValue<To> result_type; typedef TinyVector<To, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef RGBValue<To> value_type; typedef TinyVector<To, 3> value_type;
/** the result component's promote type /** the result component's promote type
*/ */
typedef typename NumericTraits<To>::RealPromote component_type; typedef typename NumericTraits<To>::RealPromote component_type;
/** Default constructor. /** Default constructor.
The maximum value for each RGB component defaults to 255 The maximum value for each RGB component defaults to 255
*/ */
RGB2RGBPrimeFunctor() RGB2RGBPrimeFunctor()
: max_(255.0) : max_(255.0)
skipping to change at line 298 skipping to change at line 312
*/ */
RGB2RGBPrimeFunctor(component_type max) RGB2RGBPrimeFunctor(component_type max)
: max_(max) : max_(max)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & rgb) const result_type operator()(V const & rgb) const
{ {
return RGBValue<To>( return TinyVector<To, 3>(
NumericTraits<To>::fromRealPromote(detail::gammaCorrection(rgb[ detail::gammaCorrection<To>(rgb[0], 0.45, max_),
0], 0.45, max_)), detail::gammaCorrection<To>(rgb[1], 0.45, max_),
NumericTraits<To>::fromRealPromote(detail::gammaCorrection(rgb[ detail::gammaCorrection<To>(rgb[2], 0.45, max_));
1], 0.45, max_)),
NumericTraits<To>::fromRealPromote(detail::gammaCorrection(rgb[
2], 0.45, max_)));
} }
private: private:
component_type max_; component_type max_;
}; };
template <> template <>
class RGB2RGBPrimeFunctor<unsigned char, unsigned char> class RGB2RGBPrimeFunctor<unsigned char, unsigned char>
{ {
unsigned char lut_[256]; unsigned char lut_[256];
public: public:
typedef RGBValue<unsigned char> value_type; typedef TinyVector<unsigned char, 3> value_type;
RGB2RGBPrimeFunctor() RGB2RGBPrimeFunctor()
{ {
for(int i=0; i<256; ++i) for(int i=0; i<256; ++i)
{ {
lut_[i] = NumericTraits<unsigned char>::fromRealPromote(detail: :gammaCorrection(i, 0.45, 255.0)); lut_[i] = detail::gammaCorrection<unsigned char>(i, 0.45, 255.0 );
} }
} }
RGB2RGBPrimeFunctor(double max) RGB2RGBPrimeFunctor(double max)
{ {
for(int i=0; i<256; ++i) for(int i=0; i<256; ++i)
{ {
lut_[i] = NumericTraits<unsigned char>::fromRealPromote(detail: :gammaCorrection(i, 0.45, max)); lut_[i] = detail::gammaCorrection<unsigned char>(i, 0.45, max);
} }
} }
template <class V> template <class V>
RGBValue<unsigned char> operator()(V const & rgb) const TinyVector<unsigned char, 3> operator()(V const & rgb) const
{ {
return RGBValue<unsigned char>(lut_[rgb[0]], lut_[rgb[1]], lut_[rgb [2]]); return TinyVector<unsigned char, 3>(lut_[rgb[0]], lut_[rgb[1]], lut _[rgb[2]]);
} }
}; };
template <class From, class To> template <class From, class To>
class FunctorTraits<RGB2RGBPrimeFunctor<From, To> > class FunctorTraits<RGB2RGBPrimeFunctor<From, To> >
: public FunctorTraitsBase<RGB2RGBPrimeFunctor<From, To> > : public FunctorTraitsBase<RGB2RGBPrimeFunctor<From, To> >
{ {
public: public:
typedef VigraTrueType isUnaryFunctor; typedef VigraTrueType isUnaryFunctor;
}; };
skipping to change at line 359 skipping to change at line 373
<b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br> <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br>
Namespace: vigra Namespace: vigra
The sRGB color space is a slight improvement over the R'G'B' space. It is now a widely accepted The sRGB color space is a slight improvement over the R'G'B' space. It is now a widely accepted
international standard (IEC 61966-2.1) which is used by most consumer p roducts international standard (IEC 61966-2.1) which is used by most consumer p roducts
(digital cameras, printers, and screens). The functor realizes the tran sformation (digital cameras, printers, and screens). The functor realizes the tran sformation
\f[ \f[
C_{sRGB} = \left\{ \begin{array}{ll} C_{sRGB} = \left\{ \begin{array}{ll}
12.92\,C_{RGB} & \textrm{ if }\frac{C_{RGB}}{C_{max}} \le 0.00304 \ \ 12.92\,C_{RGB} & \textrm{ if }\frac{C_{RGB}}{C_{max}} \le 0.0031308 \\
C_{max}\left( 1.055 \left(\frac{C_{RGB}}{C_{max}}\right)^{1/2.4}-0. 055\right) & \textrm{ otherwise} C_{max}\left( 1.055 \left(\frac{C_{RGB}}{C_{max}}\right)^{1/2.4}-0. 055\right) & \textrm{ otherwise}
\end{array} \right. \end{array} \right.
\f] \f]
where C is any of the primaries R, G, and B. By default, \f$ C_{max} = 255 \f$ (this default can be where C is any of the primaries R, G, and B. By default, \f$ C_{max} = 255 \f$ (this default can be
overridden in the constructor). If both source and target color compone nts are stored overridden in the constructor). If both source and target color compone nts are stored
as <tt>unsigned char</tt>, a look-up-table will be used to speed up the transformation. as <tt>unsigned char</tt>, a look-up-table will be used to speed up the transformation.
<b> Traits defined:</b> <b> Traits defined:</b>
skipping to change at line 383 skipping to change at line 397
class RGB2sRGBFunctor class RGB2sRGBFunctor
{ {
public: public:
/** the functor's argument type /** the functor's argument type
*/ */
typedef TinyVector<From, 3> argument_type; typedef TinyVector<From, 3> argument_type;
/** the functor's result type /** the functor's result type
*/ */
typedef RGBValue<To> result_type; typedef TinyVector<To, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef RGBValue<To> value_type; typedef TinyVector<To, 3> value_type;
/** the result component's promote type /** the result component's promote type
*/ */
typedef typename NumericTraits<To>::RealPromote component_type; typedef typename NumericTraits<To>::RealPromote component_type;
/** Default constructor. /** Default constructor.
The maximum value for each RGB component defaults to 255 The maximum value for each RGB component defaults to 255
*/ */
RGB2sRGBFunctor() RGB2sRGBFunctor()
: max_(255.0) : max_(255.0)
skipping to change at line 412 skipping to change at line 426
*/ */
RGB2sRGBFunctor(component_type max) RGB2sRGBFunctor(component_type max)
: max_(max) : max_(max)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & rgb) const result_type operator()(V const & rgb) const
{ {
return RGBValue<To>( return TinyVector<To, 3>(
NumericTraits<To>::fromRealPromote(detail::sRGBCorrection(rgb[0 detail::sRGBCorrection<To>(rgb[0], max_),
], max_)), detail::sRGBCorrection<To>(rgb[1], max_),
NumericTraits<To>::fromRealPromote(detail::sRGBCorrection(rgb[1 detail::sRGBCorrection<To>(rgb[2], max_));
], max_)),
NumericTraits<To>::fromRealPromote(detail::sRGBCorrection(rgb[2
], max_)));
} }
private: private:
component_type max_; component_type max_;
}; };
template <> template <>
class RGB2sRGBFunctor<unsigned char, unsigned char> class RGB2sRGBFunctor<unsigned char, unsigned char>
{ {
unsigned char lut_[256]; unsigned char lut_[256];
public: public:
typedef RGBValue<unsigned char> value_type; typedef TinyVector<unsigned char, 3> value_type;
RGB2sRGBFunctor() RGB2sRGBFunctor()
{ {
for(int i=0; i<256; ++i) for(int i=0; i<256; ++i)
{ {
lut_[i] = NumericTraits<unsigned char>::fromRealPromote(detail: :sRGBCorrection(i, 255.0)); lut_[i] = detail::sRGBCorrection<unsigned char>(i, 255.0);
} }
} }
RGB2sRGBFunctor(double max) RGB2sRGBFunctor(double max)
{ {
for(int i=0; i<256; ++i) for(int i=0; i<256; ++i)
{ {
lut_[i] = NumericTraits<unsigned char>::fromRealPromote(detail: :sRGBCorrection(i, max)); lut_[i] = detail::sRGBCorrection<unsigned char>(i, max);
} }
} }
template <class V> template <class V>
RGBValue<unsigned char> operator()(V const & rgb) const TinyVector<unsigned char, 3> operator()(V const & rgb) const
{ {
return RGBValue<unsigned char>(lut_[rgb[0]], lut_[rgb[1]], lut_[rgb [2]]); return TinyVector<unsigned char, 3>(lut_[rgb[0]], lut_[rgb[1]], lut _[rgb[2]]);
} }
}; };
template <class From, class To> template <class From, class To>
class FunctorTraits<RGB2sRGBFunctor<From, To> > class FunctorTraits<RGB2sRGBFunctor<From, To> >
: public FunctorTraitsBase<RGB2sRGBFunctor<From, To> > : public FunctorTraitsBase<RGB2sRGBFunctor<From, To> >
{ {
public: public:
typedef VigraTrueType isUnaryFunctor; typedef VigraTrueType isUnaryFunctor;
}; };
skipping to change at line 494 skipping to change at line 508
class RGBPrime2RGBFunctor class RGBPrime2RGBFunctor
{ {
public: public:
/** the functor's argument type /** the functor's argument type
*/ */
typedef TinyVector<From, 3> argument_type; typedef TinyVector<From, 3> argument_type;
/** the functor's result type /** the functor's result type
*/ */
typedef RGBValue<To> result_type; typedef TinyVector<To, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef RGBValue<To> value_type; typedef TinyVector<To, 3> value_type;
/** the result component's promote type /** the result component's promote type
*/ */
typedef typename NumericTraits<To>::RealPromote component_type; typedef typename NumericTraits<To>::RealPromote component_type;
/** Default constructor. /** Default constructor.
The maximum value for each RGB component defaults to 255. The maximum value for each RGB component defaults to 255.
*/ */
RGBPrime2RGBFunctor() RGBPrime2RGBFunctor()
: max_(255.0), gamma_(1.0/0.45) : max_(255.0), gamma_(1.0/0.45)
skipping to change at line 522 skipping to change at line 536
\arg max - the maximum value for each RGB component \arg max - the maximum value for each RGB component
*/ */
RGBPrime2RGBFunctor(component_type max) RGBPrime2RGBFunctor(component_type max)
: max_(max), gamma_(1.0/0.45) : max_(max), gamma_(1.0/0.45)
{} {}
/** apply the transformation /** apply the transformation
*/ */
result_type operator()(argument_type const & rgb) const result_type operator()(argument_type const & rgb) const
{ {
return RGBValue<To>( return TinyVector<To, 3>(
NumericTraits<To>::fromRealPromote(detail::gammaCorrection(rgb[ detail::gammaCorrection<To>(rgb[0], gamma_, max_),
0], gamma_, max_)), detail::gammaCorrection<To>(rgb[1], gamma_, max_),
NumericTraits<To>::fromRealPromote(detail::gammaCorrection(rgb[ detail::gammaCorrection<To>(rgb[2], gamma_, max_));
1], gamma_, max_)),
NumericTraits<To>::fromRealPromote(detail::gammaCorrection(rgb[
2], gamma_, max_)));
} }
private: private:
component_type max_; component_type max_;
double gamma_; double gamma_;
}; };
template <> template <>
class RGBPrime2RGBFunctor<unsigned char, unsigned char> class RGBPrime2RGBFunctor<unsigned char, unsigned char>
{ {
unsigned char lut_[256]; unsigned char lut_[256];
public: public:
typedef RGBValue<unsigned char> value_type; typedef TinyVector<unsigned char, 3> value_type;
RGBPrime2RGBFunctor() RGBPrime2RGBFunctor()
{ {
for(int i=0; i<256; ++i) for(int i=0; i<256; ++i)
{ {
lut_[i] = NumericTraits<unsigned char>::fromRealPromote(detail: :gammaCorrection(i, 1.0/0.45, 255.0)); lut_[i] = detail::gammaCorrection<unsigned char>(i, 1.0/0.45, 2 55.0);
} }
} }
RGBPrime2RGBFunctor(double max) RGBPrime2RGBFunctor(double max)
{ {
for(int i=0; i<256; ++i) for(int i=0; i<256; ++i)
{ {
lut_[i] = NumericTraits<unsigned char>::fromRealPromote(detail: :gammaCorrection(i, 1.0/0.45, max)); lut_[i] = detail::gammaCorrection<unsigned char>(i, 1.0/0.45, m ax);
} }
} }
template <class V> template <class V>
RGBValue<unsigned char> operator()(V const & rgb) const TinyVector<unsigned char, 3> operator()(V const & rgb) const
{ {
return RGBValue<unsigned char>(lut_[rgb[0]], lut_[rgb[1]], lut_[rgb [2]]); return TinyVector<unsigned char, 3>(lut_[rgb[0]], lut_[rgb[1]], lut _[rgb[2]]);
} }
}; };
template <class From, class To> template <class From, class To>
class FunctorTraits<RGBPrime2RGBFunctor<From, To> > class FunctorTraits<RGBPrime2RGBFunctor<From, To> >
: public FunctorTraitsBase<RGBPrime2RGBFunctor<From, To> > : public FunctorTraitsBase<RGBPrime2RGBFunctor<From, To> >
{ {
public: public:
typedef VigraTrueType isUnaryFunctor; typedef VigraTrueType isUnaryFunctor;
}; };
skipping to change at line 584 skipping to change at line 598
<b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br> <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br>
Namespace: vigra Namespace: vigra
The sRGB color space is a slight improvement over the R'G'B' space. Is is now a widely accepted The sRGB color space is a slight improvement over the R'G'B' space. Is is now a widely accepted
international standard (IEC 61966-2.1) which is used by most consumer p roducts international standard (IEC 61966-2.1) which is used by most consumer p roducts
(digital cameras, printers, and screens). The functor realizes the tran sformation (digital cameras, printers, and screens). The functor realizes the tran sformation
\f[ \f[
C_{RGB} = \left\{\begin{array}{ll} C_{RGB} = \left\{\begin{array}{ll}
C_{sRGB} / 12.92 & \textrm{if }\frac{C_{sRGB}}{C_{max}} \le 0.03928 \\ C_{sRGB} / 12.92 & \textrm{if }\frac{C_{sRGB}}{C_{max}} \le 0.04045 \\
C_{max}\left( \frac{C_{sRGB}/C_{max}+0.055}{1.055}\right)^{2.4} & \ textrm{otherwise} C_{max}\left( \frac{C_{sRGB}/C_{max}+0.055}{1.055}\right)^{2.4} & \ textrm{otherwise}
\end{array}\right. \end{array}\right.
\f] \f]
where C is one of the color channels R, G, or B, and \f$ C_{max}\f$ equ als 255 by default (This default where C is one of the color channels R, G, or B, and \f$ C_{max}\f$ equ als 255 by default (This default
can be overridden in the constructor). If both source and target color components are stored can be overridden in the constructor). If both source and target color components are stored
as <tt>unsigned char</tt>, a look-up-table will be used to speed up the transformation. as <tt>unsigned char</tt>, a look-up-table will be used to speed up the transformation.
<b> Traits defined:</b> <b> Traits defined:</b>
skipping to change at line 608 skipping to change at line 622
class sRGB2RGBFunctor class sRGB2RGBFunctor
{ {
public: public:
/** the functor's argument type /** the functor's argument type
*/ */
typedef TinyVector<From, 3> argument_type; typedef TinyVector<From, 3> argument_type;
/** the functor's result type /** the functor's result type
*/ */
typedef RGBValue<To> result_type; typedef TinyVector<To, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef RGBValue<To> value_type; typedef TinyVector<To, 3> value_type;
/** the result component's promote type /** the result component's promote type
*/ */
typedef typename NumericTraits<To>::RealPromote component_type; typedef typename NumericTraits<To>::RealPromote component_type;
/** Default constructor. /** Default constructor.
The maximum value for each RGB component defaults to 255. The maximum value for each RGB component defaults to 255.
*/ */
sRGB2RGBFunctor() sRGB2RGBFunctor()
: max_(255.0) : max_(255.0)
skipping to change at line 636 skipping to change at line 650
\arg max - the maximum value for each RGB component \arg max - the maximum value for each RGB component
*/ */
sRGB2RGBFunctor(component_type max) sRGB2RGBFunctor(component_type max)
: max_(max) : max_(max)
{} {}
/** apply the transformation /** apply the transformation
*/ */
result_type operator()(argument_type const & rgb) const result_type operator()(argument_type const & rgb) const
{ {
return RGBValue<To>( return TinyVector<To, 3>(
NumericTraits<To>::fromRealPromote(detail::inverse_sRGBCorrecti detail::inverse_sRGBCorrection<To>(rgb[0], max_),
on(rgb[0], max_)), detail::inverse_sRGBCorrection<To>(rgb[1], max_),
NumericTraits<To>::fromRealPromote(detail::inverse_sRGBCorrecti detail::inverse_sRGBCorrection<To>(rgb[2], max_));
on(rgb[1], max_)),
NumericTraits<To>::fromRealPromote(detail::inverse_sRGBCorrecti
on(rgb[2], max_)));
} }
private: private:
component_type max_; component_type max_;
}; };
template <> template <>
class sRGB2RGBFunctor<unsigned char, unsigned char> class sRGB2RGBFunctor<unsigned char, unsigned char>
{ {
unsigned char lut_[256]; unsigned char lut_[256];
public: public:
typedef RGBValue<unsigned char> value_type; typedef TinyVector<unsigned char, 3> value_type;
sRGB2RGBFunctor() sRGB2RGBFunctor()
{ {
for(int i=0; i<256; ++i) for(int i=0; i<256; ++i)
{ {
lut_[i] = NumericTraits<unsigned char>::fromRealPromote(detail: :inverse_sRGBCorrection(i, 255.0)); lut_[i] = detail::inverse_sRGBCorrection<unsigned char>(i, 255. 0);
} }
} }
sRGB2RGBFunctor(double max) sRGB2RGBFunctor(double max)
{ {
for(int i=0; i<256; ++i) for(int i=0; i<256; ++i)
{ {
lut_[i] = NumericTraits<unsigned char>::fromRealPromote(detail: :inverse_sRGBCorrection(i, max)); lut_[i] = detail::inverse_sRGBCorrection<unsigned char>(i, max) ;
} }
} }
template <class V> template <class V>
RGBValue<unsigned char> operator()(V const & rgb) const TinyVector<unsigned char, 3> operator()(V const & rgb) const
{ {
return RGBValue<unsigned char>(lut_[rgb[0]], lut_[rgb[1]], lut_[rgb [2]]); return TinyVector<unsigned char, 3>(lut_[rgb[0]], lut_[rgb[1]], lut _[rgb[2]]);
} }
}; };
template <class From, class To> template <class From, class To>
class FunctorTraits<sRGB2RGBFunctor<From, To> > class FunctorTraits<sRGB2RGBFunctor<From, To> >
: public FunctorTraitsBase<sRGB2RGBFunctor<From, To> > : public FunctorTraitsBase<sRGB2RGBFunctor<From, To> >
{ {
public: public:
typedef VigraTrueType isUnaryFunctor; typedef VigraTrueType isUnaryFunctor;
}; };
skipping to change at line 704 skipping to change at line 718
\begin{array}{rcl} \begin{array}{rcl}
X & = & 0.412453\enspace R / R_{max} + 0.357580\enspace G / G_{max} + 0.180423\enspace B / B_{max}\\ X & = & 0.412453\enspace R / R_{max} + 0.357580\enspace G / G_{max} + 0.180423\enspace B / B_{max}\\
Y & = & 0.212671\enspace R / R_{max} + 0.715160\enspace G / G_{max} + 0.072169\enspace B / B_{max} \\ Y & = & 0.212671\enspace R / R_{max} + 0.715160\enspace G / G_{max} + 0.072169\enspace B / B_{max} \\
Z & = & 0.019334\enspace R / R_{max} + 0.119193\enspace G / G_{max} + 0.950227\enspace B / B_{max} Z & = & 0.019334\enspace R / R_{max} + 0.119193\enspace G / G_{max} + 0.950227\enspace B / B_{max}
\end{array} \end{array}
\f] \f]
By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden
in the constructor. X, Y, and Z are always positive and reach their max imum for white. in the constructor. X, Y, and Z are always positive and reach their max imum for white.
The white point is obtained by transforming RGB(255, 255, 255). It corr esponds to the The white point is obtained by transforming RGB(255, 255, 255). It corr esponds to the
D65 illuminant. Y represents the <em>luminance</em> ("brightness") of t D65 illuminant. Y represents the <em>luminance</em> ("brightness") of t
he color. he color. The above
transformation is officially defined in connection with the sRGB color
space (i.e. when the RGB values
are obtained by inverse gamma correction of sRGB), other color spaces u
se slightly different numbers
or another standard illuminant (which gives raise to significantly diff
erent numbers).
<b> Traits defined:</b> <b> Traits defined:</b>
<tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
*/ */
template <class T> template <class T>
class RGB2XYZFunctor class RGB2XYZFunctor
{ {
public: public:
skipping to change at line 749 skipping to change at line 766
\arg max - the maximum value for each RGB component \arg max - the maximum value for each RGB component
*/ */
RGB2XYZFunctor(component_type max) RGB2XYZFunctor(component_type max)
: max_(max) : max_(max)
{} {}
/** apply the transformation /** apply the transformation
*/ */
result_type operator()(argument_type const & rgb) const result_type operator()(argument_type const & rgb) const
{ {
typedef detail::RequiresExplicitCast<component_type> Convert;
component_type red = rgb[0] / max_; component_type red = rgb[0] / max_;
component_type green = rgb[1] / max_; component_type green = rgb[1] / max_;
component_type blue = rgb[2] / max_; component_type blue = rgb[2] / max_;
result_type result; result_type result;
result[0] = 0.412453*red + 0.357580*green + 0.180423*blue; result[0] = Convert::cast(0.412453*red + 0.357580*green + 0.180423*
result[1] = 0.212671*red + 0.715160*green + 0.072169*blue; blue);
result[2] = 0.019334*red + 0.119193*green + 0.950227*blue; result[1] = Convert::cast(0.212671*red + 0.715160*green + 0.072169*
blue);
result[2] = Convert::cast(0.019334*red + 0.119193*green + 0.950227*
blue);
return result; return result;
} }
private: private:
component_type max_; component_type max_;
}; };
template <class T> template <class T>
class FunctorTraits<RGB2XYZFunctor<T> > class FunctorTraits<RGB2XYZFunctor<T> >
: public FunctorTraitsBase<RGB2XYZFunctor<T> > : public FunctorTraitsBase<RGB2XYZFunctor<T> >
skipping to change at line 814 skipping to change at line 832
typedef TinyVector<component_type, 3> result_type; typedef TinyVector<component_type, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef TinyVector<component_type, 3> value_type; typedef TinyVector<component_type, 3> value_type;
/** default constructor /** default constructor
The maximum value for each RGB component defaults to 255. The maximum value for each RGB component defaults to 255.
*/ */
RGBPrime2XYZFunctor() RGBPrime2XYZFunctor()
: max_(255.0), gamma_(1.0/ 0.45) : max_(component_type(255.0)), gamma_(1.0/ 0.45)
{} {}
/** constructor /** constructor
\arg max - the maximum value for each RGB component \arg max - the maximum value for each RGB component
*/ */
RGBPrime2XYZFunctor(component_type max) RGBPrime2XYZFunctor(component_type max)
: max_(max), gamma_(1.0/ 0.45) : max_(max), gamma_(1.0/ 0.45)
{} {}
/** apply the transformation /** apply the transformation
*/ */
result_type operator()(argument_type const & rgb) const result_type operator()(argument_type const & rgb) const
{ {
component_type red = detail::gammaCorrection(rgb[0]/max_, gamma_); typedef detail::RequiresExplicitCast<component_type> Convert;
component_type green = detail::gammaCorrection(rgb[1]/max_, gamma_) component_type red = detail::gammaCorrection<component_type>(rgb[0]
; /max_, gamma_);
component_type blue = detail::gammaCorrection(rgb[2]/max_, gamma_); component_type green = detail::gammaCorrection<component_type>(rgb[
1]/max_, gamma_);
component_type blue = detail::gammaCorrection<component_type>(rgb[2
]/max_, gamma_);
result_type result; result_type result;
result[0] = 0.412453*red + 0.357580*green + 0.180423*blue; result[0] = Convert::cast(0.412453*red + 0.357580*green + 0.180423*
result[1] = 0.212671*red + 0.715160*green + 0.072169*blue; blue);
result[2] = 0.019334*red + 0.119193*green + 0.950227*blue; result[1] = Convert::cast(0.212671*red + 0.715160*green + 0.072169*
blue);
result[2] = Convert::cast(0.019334*red + 0.119193*green + 0.950227*
blue);
return result; return result;
} }
private: private:
component_type max_, gamma_; double gamma_;
component_type max_;
}; };
template <class T> template <class T>
class FunctorTraits<RGBPrime2XYZFunctor<T> > class FunctorTraits<RGBPrime2XYZFunctor<T> >
: public FunctorTraitsBase<RGBPrime2XYZFunctor<T> > : public FunctorTraitsBase<RGBPrime2XYZFunctor<T> >
{ {
public: public:
typedef VigraTrueType isUnaryFunctor; typedef VigraTrueType isUnaryFunctor;
}; };
skipping to change at line 888 skipping to change at line 908
public: public:
/** the functor's argument type. (Actually, the argument type /** the functor's argument type. (Actually, the argument type
is more general: <TT>V</TT> with arbitrary is more general: <TT>V</TT> with arbitrary
<TT>V</TT>. But this cannot be expressed in a typedef.) <TT>V</TT>. But this cannot be expressed in a typedef.)
*/ */
typedef TinyVector<T, 3> argument_type; typedef TinyVector<T, 3> argument_type;
/** the functor's result type /** the functor's result type
*/ */
typedef RGBValue<T> result_type; typedef TinyVector<T, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef RGBValue<T> value_type; typedef TinyVector<T, 3> value_type;
/** default constructor. /** default constructor.
The maximum value for each RGB component defaults to 255. The maximum value for each RGB component defaults to 255.
*/ */
XYZ2RGBFunctor() XYZ2RGBFunctor()
: max_(255.0) : max_(255.0)
{} {}
/** constructor /** constructor
\arg max - the maximum value for each RGB component \arg max - the maximum value for each RGB component
*/ */
XYZ2RGBFunctor(component_type max) XYZ2RGBFunctor(component_type max)
: max_(max) : max_(max)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & xyz) const result_type operator()(V const & xyz) const
{ {
component_type red = 3.2404813432*xyz[0] - 1.5371515163*xyz[1] - typedef detail::RequiresExplicitCast<component_type> Convert;
0.4985363262*xyz[2]; component_type red = Convert::cast( 3.2404813432*xyz[0] - 1.53715
component_type green = -0.9692549500*xyz[0] + 1.8759900015*xyz[1] + 15163*xyz[1] - 0.4985363262*xyz[2]);
0.0415559266*xyz[2]; component_type green = Convert::cast(-0.9692549500*xyz[0] + 1.87599
component_type blue = 0.0556466391*xyz[0] - 0.2040413384*xyz[1] + 00015*xyz[1] + 0.0415559266*xyz[2]);
1.0573110696*xyz[2]; component_type blue = Convert::cast( 0.0556466391*xyz[0] - 0.20404
13384*xyz[1] + 1.0573110696*xyz[2]);
return value_type(NumericTraits<T>::fromRealPromote(red * max_), return value_type(NumericTraits<T>::fromRealPromote(red * max_),
NumericTraits<T>::fromRealPromote(green * max_), NumericTraits<T>::fromRealPromote(green * max_),
NumericTraits<T>::fromRealPromote(blue * max_)); NumericTraits<T>::fromRealPromote(blue * max_));
} }
}; };
template <class T> template <class T>
class FunctorTraits<XYZ2RGBFunctor<T> > class FunctorTraits<XYZ2RGBFunctor<T> >
: public FunctorTraitsBase<XYZ2RGBFunctor<T> > : public FunctorTraitsBase<XYZ2RGBFunctor<T> >
{ {
skipping to change at line 953 skipping to change at line 974
<b> Traits defined:</b> <b> Traits defined:</b>
<tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
*/ */
template <class T> template <class T>
class XYZ2RGBPrimeFunctor class XYZ2RGBPrimeFunctor
{ {
typedef typename NumericTraits<T>::RealPromote component_type; typedef typename NumericTraits<T>::RealPromote component_type;
component_type max_, gamma_; double gamma_;
component_type max_;
public: public:
public: public:
/** the functor's argument type. (actually, the argument type /** the functor's argument type. (actually, the argument type
can be any vector type with the same interface. can be any vector type with the same interface.
But this cannot be expressed in a typedef.) But this cannot be expressed in a typedef.)
*/ */
typedef TinyVector<T, 3> argument_type; typedef TinyVector<T, 3> argument_type;
/** the functor's result type /** the functor's result type
*/ */
typedef RGBValue<T> result_type; typedef TinyVector<T, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef RGBValue<T> value_type; typedef TinyVector<T, 3> value_type;
/** default constructor. /** default constructor.
The maximum value for each RGB component defaults to 255. The maximum value for each RGB component defaults to 255.
*/ */
XYZ2RGBPrimeFunctor() XYZ2RGBPrimeFunctor()
: max_(255.0), gamma_(0.45) : max_(component_type(255.0)), gamma_(0.45)
{} {}
/** constructor /** constructor
\arg max - the maximum value for each RGB component \arg max - the maximum value for each RGB component
*/ */
XYZ2RGBPrimeFunctor(component_type max) XYZ2RGBPrimeFunctor(component_type max)
: max_(max), gamma_(0.45) : max_(max), gamma_(0.45)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & xyz) const result_type operator()(V const & xyz) const
{ {
component_type red = 3.2404813432*xyz[0] - 1.5371515163*xyz[1] - typedef detail::RequiresExplicitCast<component_type> Convert;
0.4985363262*xyz[2]; component_type red = Convert::cast( 3.2404813432*xyz[0] - 1.53715
component_type green = -0.9692549500*xyz[0] + 1.8759900015*xyz[1] + 15163*xyz[1] - 0.4985363262*xyz[2]);
0.0415559266*xyz[2]; component_type green = Convert::cast(-0.9692549500*xyz[0] + 1.87599
component_type blue = 0.0556466391*xyz[0] - 0.2040413384*xyz[1] + 00015*xyz[1] + 0.0415559266*xyz[2]);
1.0573110696*xyz[2]; component_type blue = Convert::cast( 0.0556466391*xyz[0] - 0.20404
return value_type(NumericTraits<T>::fromRealPromote(detail::gammaCo 13384*xyz[1] + 1.0573110696*xyz[2]);
rrection(red, gamma_) * max_), return value_type(NumericTraits<T>::fromRealPromote(detail::gammaCo
NumericTraits<T>::fromRealPromote(detail::gammaCo rrection<component_type>(red, gamma_) * max_),
rrection(green, gamma_) * max_), NumericTraits<T>::fromRealPromote(detail::gammaCo
NumericTraits<T>::fromRealPromote(detail::gammaCo rrection<component_type>(green, gamma_) * max_),
rrection(blue, gamma_) * max_)); NumericTraits<T>::fromRealPromote(detail::gammaCo
rrection<component_type>(blue, gamma_) * max_));
} }
}; };
template <class T> template <class T>
class FunctorTraits<XYZ2RGBPrimeFunctor<T> > class FunctorTraits<XYZ2RGBPrimeFunctor<T> >
: public FunctorTraitsBase<XYZ2RGBPrimeFunctor<T> > : public FunctorTraitsBase<XYZ2RGBPrimeFunctor<T> >
{ {
public: public:
typedef VigraTrueType isUnaryFunctor; typedef VigraTrueType isUnaryFunctor;
}; };
skipping to change at line 1029 skipping to change at line 1052
L^{*} & = & 903.3\enspace \frac{Y}{Y_n} \quad \mbox{otherwise} \\ L^{*} & = & 903.3\enspace \frac{Y}{Y_n} \quad \mbox{otherwise} \\
& & \\ & & \\
u' & = & \frac{4 X}{X+15 Y + 3 Z}, \quad u' & = & \frac{4 X}{X+15 Y + 3 Z}, \quad
v' = \frac{9 Y}{X+15 Y + 3 Z}\\ v' = \frac{9 Y}{X+15 Y + 3 Z}\\
& & \\ & & \\
u^{*} & = & 13 L^{*} (u' - u_n'), \quad v^{*} = 13 L^{*} (v' - v_n' ) u^{*} & = & 13 L^{*} (u' - u_n'), \quad v^{*} = 13 L^{*} (v' - v_n' )
\end{array} \end{array}
\f] \f]
where \f$(X_n, Y_n, Z_n)\f$ is the reference white point, and where \f$(X_n, Y_n, Z_n) = (0.950456, 1.0, 1.088754)\f$ is the referenc
\f$u_n' = 0.197839, v_n'=0.468342\f$ are the quantities \f$u', v'\f$ ca e white point of standard illuminant D65,
lculated for this and \f$u_n' = 0.197839, v_n'=0.468342\f$ are the quantities \f$u', v'\f
point. \f$L^{*}\f$ represents the $ calculated for this point.
<em>lighness</em> ("brightness") of the color, and \f$u^{*}, v^{*}\f$ c \f$L^{*}\f$ represents the <em>lightness</em> ("brightness") of the col
ode the or, and \f$u^{*}, v^{*}\f$ code the
chromaticity. chromaticity. (Instead of the rationals \f$\frac{216}{24389}\f$ and \f$
\frac{24389}{27}\f$, the original standard gives the
rounded values 0.008856 and 903.3. As <a href="http://www.brucelindbloo
m.com/index.html?LContinuity.html">Bruce Lindbloom</a>
points out, the rounded values give raise to a discontinuity which is r
emoved by the accurate rationals. This bug will be fixed
in future versions of the CIE Luv standard.)
<b> Traits defined:</b> <b> Traits defined:</b>
<tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
*/ */
template <class T> template <class T>
class XYZ2LuvFunctor class XYZ2LuvFunctor
{ {
public: public:
skipping to change at line 1061 skipping to change at line 1086
/** the functor's result type /** the functor's result type
*/ */
typedef TinyVector<component_type, 3> result_type; typedef TinyVector<component_type, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef TinyVector<component_type, 3> value_type; typedef TinyVector<component_type, 3> value_type;
XYZ2LuvFunctor() XYZ2LuvFunctor()
: gamma_(1.0/3.0) : gamma_(1.0/3.0),
kappa_(24389.0/27.0),
epsilon_(216.0/24389.0)
{} {}
template <class V> template <class V>
result_type operator()(V const & xyz) const result_type operator()(V const & xyz) const
{ {
result_type result; result_type result;
if(xyz[1] == NumericTraits<T>::zero()) if(xyz[1] == NumericTraits<T>::zero())
{ {
result[0] = NumericTraits<component_type>::zero(); result[0] = NumericTraits<component_type>::zero();
result[1] = NumericTraits<component_type>::zero(); result[1] = NumericTraits<component_type>::zero();
result[2] = NumericTraits<component_type>::zero(); result[2] = NumericTraits<component_type>::zero();
} }
else else
{ {
component_type L = xyz[1] < 0.008856 ? typedef detail::RequiresExplicitCast<component_type> Convert;
903.3 * xyz[1] : component_type L = Convert::cast(
116.0 * VIGRA_CSTD::pow((double)xyz[1], g xyz[1] < epsilon_
amma_) - 16.0; ? kappa_ * xyz[1]
component_type denom = xyz[0] + 15.0*xyz[1] + 3.0*xyz[2]; : 116.0 * VIGRA_CSTD::pow((double)xyz
component_type uprime = 4.0 * xyz[0] / denom; [1], gamma_) - 16.0);
component_type vprime = 9.0 * xyz[1] / denom; component_type denom = Convert::cast(xyz[0] + 15.0*xyz[1] + 3.0
*xyz[2]);
component_type uprime = Convert::cast(4.0 * xyz[0] / denom);
component_type vprime = Convert::cast(9.0 * xyz[1] / denom);
result[0] = L; result[0] = L;
result[1] = 13.0*L*(uprime - 0.197839); result[1] = Convert::cast(13.0*L*(uprime - 0.197839));
result[2] = 13.0*L*(vprime - 0.468342); result[2] = Convert::cast(13.0*L*(vprime - 0.468342));
} }
return result; return result;
} }
private: private:
double gamma_; double gamma_, kappa_, epsilon_;
}; };
template <class T> template <class T>
class FunctorTraits<XYZ2LuvFunctor<T> > class FunctorTraits<XYZ2LuvFunctor<T> >
: public FunctorTraitsBase<XYZ2LuvFunctor<T> > : public FunctorTraitsBase<XYZ2LuvFunctor<T> >
{ {
public: public:
typedef VigraTrueType isUnaryFunctor; typedef VigraTrueType isUnaryFunctor;
}; };
skipping to change at line 1134 skipping to change at line 1163
/** the functor's result type /** the functor's result type
*/ */
typedef TinyVector<component_type, 3> result_type; typedef TinyVector<component_type, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef TinyVector<component_type, 3> value_type; typedef TinyVector<component_type, 3> value_type;
Luv2XYZFunctor() Luv2XYZFunctor()
: gamma_(3.0) : gamma_(3.0),
ikappa_(27.0/24389.0)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & luv) const result_type operator()(V const & luv) const
{ {
result_type result; result_type result;
if(luv[0] == NumericTraits<T>::zero()) if(luv[0] == NumericTraits<T>::zero())
{ {
result[0] = NumericTraits<component_type>::zero(); result[0] = NumericTraits<component_type>::zero();
result[1] = NumericTraits<component_type>::zero(); result[1] = NumericTraits<component_type>::zero();
result[2] = NumericTraits<component_type>::zero(); result[2] = NumericTraits<component_type>::zero();
} }
else else
{ {
component_type uprime = luv[1] / 13.0 / luv[0] + 0.197839; typedef detail::RequiresExplicitCast<component_type> Convert;
component_type vprime = luv[2] / 13.0 / luv[0] + 0.468342; component_type uprime = Convert::cast(luv[1] / 13.0 / luv[0] +
0.197839);
component_type vprime = Convert::cast(luv[2] / 13.0 / luv[0] +
0.468342);
result[1] = luv[0] < 8.0 ? result[1] = Convert::cast(
luv[0] / 903.3 : luv[0] < 8.0
VIGRA_CSTD::pow((luv[0] + 16.0) / 116.0, ? luv[0] * ikappa_
gamma_); : VIGRA_CSTD::pow((luv[0] + 16.0) / 116.0,
result[0] = 9.0*uprime*result[1] / 4.0 / vprime; gamma_));
result[2] = ((9.0 / vprime - 15.0)*result[1] - result[0])/ 3.0; result[0] = Convert::cast(9.0*uprime*result[1] / 4.0 / vprime);
result[2] = Convert::cast(((9.0 / vprime - 15.0)*result[1] - re
sult[0])/ 3.0);
} }
return result; return result;
} }
private: private:
double gamma_; double gamma_, ikappa_;
}; };
template <class T> template <class T>
class FunctorTraits<Luv2XYZFunctor<T> > class FunctorTraits<Luv2XYZFunctor<T> >
: public FunctorTraitsBase<Luv2XYZFunctor<T> > : public FunctorTraitsBase<Luv2XYZFunctor<T> >
{ {
public: public:
typedef VigraTrueType isUnaryFunctor; typedef VigraTrueType isUnaryFunctor;
}; };
/** \brief Convert standardized tri-stimulus XYZ into perceptual uniform CI E L*a*b*. /** \brief Convert standardized tri-stimulus XYZ into perceptual uniform CI E L*a*b*.
<b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br> <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br>
Namespace: vigra Namespace: vigra
The functor realizes the transformation The functor realizes the transformation
\f[ \f[
\begin{array}{rcl} \begin{array}{rcl}
L^{*} & = & 116 \left( \frac{Y}{Y_n} \right)^\frac{1}{3}-16 \quad \ mbox{if} \quad 0.008856 < \frac{Y}{Y_n}\\ L^{*} & = & 116 \left( \frac{Y}{Y_n} \right)^\frac{1}{3}-16 \quad \ mbox{if} \quad \frac{216}{24389} < \frac{Y}{Y_n}\\
& & \\ & & \\
L^{*} & = & 903.3\enspace \frac{Y}{Y_n} \quad \mbox{otherwise} \\ L^{*} & = & \frac{24389}{27} \enspace \frac{Y}{Y_n} \quad \mbox{oth erwise} \\
& & \\ & & \\
a^{*} & = & 500 \left[ \left( \frac{X}{X_n} \right)^\frac{1}{3} - \ left( \frac{Y}{Y_n} \right)^\frac{1}{3} \right] \\ a^{*} & = & 500 \left[ \left( \frac{X}{X_n} \right)^\frac{1}{3} - \ left( \frac{Y}{Y_n} \right)^\frac{1}{3} \right] \\
& & \\ & & \\
b^{*} & = & 200 \left[ \left( \frac{Y}{Y_n} \right)^\frac{1}{3} - \ left( \frac{Z}{Z_n} \right)^\frac{1}{3} \right] \\ b^{*} & = & 200 \left[ \left( \frac{Y}{Y_n} \right)^\frac{1}{3} - \ left( \frac{Z}{Z_n} \right)^\frac{1}{3} \right] \\
\end{array} \end{array}
\f] \f]
where \f$(X_n, Y_n, Z_n)\f$ is the reference white point. \f$L^{*}\f$ r where \f$(X_n, Y_n, Z_n) = (0.950456, 1.0, 1.088754)\f$ is the referenc
epresents the e white point of standard illuminant D65.
<em>lighness</em> ("brightness") of the color, and \f$a^{*}, b^{*}\f$ c \f$L^{*}\f$ represents the <em>lightness</em> ("brightness") of the col
ode the or, and \f$a^{*}, b^{*}\f$ code the
chromaticity. chromaticity. (Instead of the rationals \f$\frac{216}{24389}\f$ and \f$
\frac{24389}{27}\f$, the original standard gives the
rounded values 0.008856 and 903.3. As <a href="http://www.brucelindbloo
m.com/index.html?LContinuity.html">Bruce Lindbloom</a>
points out, the rounded values give raise to a discontinuity which is r
emoved by the accurate rationals. This bug will be fixed
in future versions of the CIE Lab standard.)
<b> Traits defined:</b> <b> Traits defined:</b>
<tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
*/ */
template <class T> template <class T>
class XYZ2LabFunctor class XYZ2LabFunctor
{ {
public: public:
skipping to change at line 1224 skipping to change at line 1259
/** the functor's result type /** the functor's result type
*/ */
typedef TinyVector<component_type, 3> result_type; typedef TinyVector<component_type, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef TinyVector<component_type, 3> value_type; typedef TinyVector<component_type, 3> value_type;
XYZ2LabFunctor() XYZ2LabFunctor()
: gamma_(1.0/3.0) : gamma_(1.0/3.0),
kappa_(24389.0/27.0),
epsilon_(216.0/24389.0)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & xyz) const result_type operator()(V const & xyz) const
{ {
component_type xgamma = VIGRA_CSTD::pow(xyz[0] / 0.950456, gamma_); typedef detail::RequiresExplicitCast<component_type> Convert;
component_type ygamma = VIGRA_CSTD::pow((double)xyz[1], gamma_); component_type xgamma = Convert::cast(std::pow(xyz[0] / 0.950456, g
component_type zgamma = VIGRA_CSTD::pow(xyz[2] / 1.088754, gamma_); amma_));
component_type L = xyz[1] < 0.008856 ? component_type ygamma = Convert::cast(std::pow((double)xyz[1], gamm
903.3 * xyz[1] : a_));
116.0 * ygamma - 16.0; component_type zgamma = Convert::cast(std::pow(xyz[2] / 1.088754, g
amma_));
component_type L = Convert::cast(
xyz[1] < epsilon_
? kappa_ * xyz[1]
: 116.0 * ygamma - 16.0);
result_type result; result_type result;
result[0] = L; result[0] = L;
result[1] = 500.0*(xgamma - ygamma); result[1] = Convert::cast(500.0*(xgamma - ygamma));
result[2] = 200.0*(ygamma - zgamma); result[2] = Convert::cast(200.0*(ygamma - zgamma));
return result; return result;
} }
private: private:
double gamma_; double gamma_, kappa_, epsilon_;
}; };
template <class T> template <class T>
class FunctorTraits<XYZ2LabFunctor<T> > class FunctorTraits<XYZ2LabFunctor<T> >
: public FunctorTraitsBase<XYZ2LabFunctor<T> > : public FunctorTraitsBase<XYZ2LabFunctor<T> >
{ {
public: public:
typedef VigraTrueType isUnaryFunctor; typedef VigraTrueType isUnaryFunctor;
}; };
skipping to change at line 1292 skipping to change at line 1331
*/ */
typedef TinyVector<component_type, 3> result_type; typedef TinyVector<component_type, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef TinyVector<component_type, 3> value_type; typedef TinyVector<component_type, 3> value_type;
/** the functor's value type /** the functor's value type
*/ */
Lab2XYZFunctor() Lab2XYZFunctor()
: gamma_(3.0) : gamma_(3.0),
ikappa_(27.0/24389.0)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & lab) const result_type operator()(V const & lab) const
{ {
component_type Y = lab[0] < 8.0 ? typedef detail::RequiresExplicitCast<component_type> Convert;
lab[0] / 903.3 : component_type Y = Convert::cast(
VIGRA_CSTD::pow((lab[0] + 16.0) / 116.0, gamm lab[0] < 8.0
a_); ? lab[0] * ikappa_
component_type ygamma = VIGRA_CSTD::pow((double)Y, 1.0 / gamma_); : std::pow((lab[0] + 16.0) / 116.0, gamma
component_type X = VIGRA_CSTD::pow(lab[1] / 500.0 + ygamma, gamma_) _));
* 0.950456; component_type ygamma = Convert::cast(std::pow((double)Y, 1.0 / gam
component_type Z = VIGRA_CSTD::pow(-lab[2] / 200.0 + ygamma, gamma_ ma_));
) * 1.088754; component_type X = Convert::cast(std::pow(lab[1] / 500.0 + ygamma,
gamma_) * 0.950456);
component_type Z = Convert::cast(std::pow(-lab[2] / 200.0 + ygamma,
gamma_) * 1.088754);
result_type result; result_type result;
result[0] = X; result[0] = X;
result[1] = Y; result[1] = Y;
result[2] = Z; result[2] = Z;
return result; return result;
} }
private: private:
double gamma_; double gamma_, ikappa_;
}; };
template <class T> template <class T>
class FunctorTraits<Lab2XYZFunctor<T> > class FunctorTraits<Lab2XYZFunctor<T> >
: public FunctorTraitsBase<Lab2XYZFunctor<T> > : public FunctorTraitsBase<Lab2XYZFunctor<T> >
{ {
public: public:
typedef VigraTrueType isUnaryFunctor; typedef VigraTrueType isUnaryFunctor;
}; };
skipping to change at line 2003 skipping to change at line 2045
*/ */
RGBPrime2YPrimePbPrFunctor(component_type max) RGBPrime2YPrimePbPrFunctor(component_type max)
: max_(max) : max_(max)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & rgb) const result_type operator()(V const & rgb) const
{ {
typedef detail::RequiresExplicitCast<component_type> Convert;
component_type red = rgb[0] / max_; component_type red = rgb[0] / max_;
component_type green = rgb[1] / max_; component_type green = rgb[1] / max_;
component_type blue = rgb[2] / max_; component_type blue = rgb[2] / max_;
result_type result; result_type result;
result[0] = 0.299*red + 0.587*green + 0.114*blue; result[0] = Convert::cast(0.299*red + 0.587*green + 0.114*blue);
result[1] = -0.1687358916*red - 0.3312641084*green + 0.5*blue; result[1] = Convert::cast(-0.1687358916*red - 0.3312641084*green +
result[2] = 0.5*red - 0.4186875892*green - 0.0813124108*blue; 0.5*blue);
result[2] = Convert::cast(0.5*red - 0.4186875892*green - 0.08131241
08*blue);
return result; return result;
} }
private: private:
component_type max_; component_type max_;
}; };
template <class T> template <class T>
class FunctorTraits<RGBPrime2YPrimePbPrFunctor<T> > class FunctorTraits<RGBPrime2YPrimePbPrFunctor<T> >
: public FunctorTraitsBase<RGBPrime2YPrimePbPrFunctor<T> > : public FunctorTraitsBase<RGBPrime2YPrimePbPrFunctor<T> >
skipping to change at line 2054 skipping to change at line 2097
public: public:
/** the functor's argument type. (Actually, the argument type /** the functor's argument type. (Actually, the argument type
can be any vector type with the same interface. can be any vector type with the same interface.
But this cannot be expressed in a typedef.) But this cannot be expressed in a typedef.)
*/ */
typedef TinyVector<T, 3> argument_type; typedef TinyVector<T, 3> argument_type;
/** the functor's result type /** the functor's result type
*/ */
typedef RGBValue<T> result_type; typedef TinyVector<T, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef RGBValue<T> value_type; typedef TinyVector<T, 3> value_type;
/** default constructor. /** default constructor.
The maximum value for each RGB component defaults to 255. The maximum value for each RGB component defaults to 255.
*/ */
YPrimePbPr2RGBPrimeFunctor() YPrimePbPr2RGBPrimeFunctor()
: max_(255.0) : max_(255.0)
{} {}
/** constructor /** constructor
\arg max - the maximum value for each RGB component \arg max - the maximum value for each RGB component
*/ */
YPrimePbPr2RGBPrimeFunctor(component_type max) YPrimePbPr2RGBPrimeFunctor(component_type max)
: max_(max) : max_(max)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & ypbpr) const result_type operator()(V const & ypbpr) const
{ {
component_type nred = ypbpr[0] + 1.402*ypbpr[2]; typedef detail::RequiresExplicitCast<component_type> Convert;
component_type ngreen = ypbpr[0] - 0.3441362862*ypbpr[1] - 0.714136 component_type nred = Convert::cast(ypbpr[0] + 1.402*ypbpr[2]);
2862*ypbpr[2]; component_type ngreen = Convert::cast(ypbpr[0] - 0.3441362862*ypbpr
component_type nblue = ypbpr[0] + 1.772*ypbpr[1]; [1] - 0.7141362862*ypbpr[2]);
component_type nblue = Convert::cast(ypbpr[0] + 1.772*ypbpr[1]);
return result_type(NumericTraits<T>::fromRealPromote(nred * max_), return result_type(NumericTraits<T>::fromRealPromote(nred * max_),
NumericTraits<T>::fromRealPromote(ngreen * max_) , NumericTraits<T>::fromRealPromote(ngreen * max_) ,
NumericTraits<T>::fromRealPromote(nblue * max_)) ; NumericTraits<T>::fromRealPromote(nblue * max_)) ;
} }
}; };
template <class T> template <class T>
class FunctorTraits<YPrimePbPr2RGBPrimeFunctor<T> > class FunctorTraits<YPrimePbPr2RGBPrimeFunctor<T> >
: public FunctorTraitsBase<YPrimePbPr2RGBPrimeFunctor<T> > : public FunctorTraitsBase<YPrimePbPr2RGBPrimeFunctor<T> >
{ {
skipping to change at line 2174 skipping to change at line 2218
*/ */
RGBPrime2YPrimeIQFunctor(component_type max) RGBPrime2YPrimeIQFunctor(component_type max)
: max_(max) : max_(max)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & rgb) const result_type operator()(V const & rgb) const
{ {
typedef detail::RequiresExplicitCast<component_type> Convert;
component_type red = rgb[0] / max_; component_type red = rgb[0] / max_;
component_type green = rgb[1] / max_; component_type green = rgb[1] / max_;
component_type blue = rgb[2] / max_; component_type blue = rgb[2] / max_;
result_type result; result_type result;
result[0] = 0.299*red + 0.587*green + 0.114*blue; result[0] = Convert::cast(0.299*red + 0.587*green + 0.114*blue);
result[1] = 0.596*red - 0.274*green - 0.322*blue; result[1] = Convert::cast(0.596*red - 0.274*green - 0.322*blue);
result[2] = 0.212*red - 0.523*green + 0.311*blue; result[2] = Convert::cast(0.212*red - 0.523*green + 0.311*blue);
return result; return result;
} }
private: private:
component_type max_; component_type max_;
}; };
template <class T> template <class T>
class FunctorTraits<RGBPrime2YPrimeIQFunctor<T> > class FunctorTraits<RGBPrime2YPrimeIQFunctor<T> >
: public FunctorTraitsBase<RGBPrime2YPrimeIQFunctor<T> > : public FunctorTraitsBase<RGBPrime2YPrimeIQFunctor<T> >
skipping to change at line 2225 skipping to change at line 2270
public: public:
/** the functor's argument type. (Actually, the argument type /** the functor's argument type. (Actually, the argument type
can be any vector type with the same interface. can be any vector type with the same interface.
But this cannot be expressed in a typedef.) But this cannot be expressed in a typedef.)
*/ */
typedef TinyVector<T, 3> argument_type; typedef TinyVector<T, 3> argument_type;
/** the functor's result type /** the functor's result type
*/ */
typedef RGBValue<T> result_type; typedef TinyVector<T, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef RGBValue<T> value_type; typedef TinyVector<T, 3> value_type;
/** default constructor. /** default constructor.
The maximum value for each RGB component defaults to 255. The maximum value for each RGB component defaults to 255.
*/ */
YPrimeIQ2RGBPrimeFunctor() YPrimeIQ2RGBPrimeFunctor()
: max_(255.0) : max_(255.0)
{} {}
/** constructor /** constructor
\arg max - the maximum value for each RGB component \arg max - the maximum value for each RGB component
*/ */
YPrimeIQ2RGBPrimeFunctor(component_type max) YPrimeIQ2RGBPrimeFunctor(component_type max)
: max_(max) : max_(max)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & yiq) const result_type operator()(V const & yiq) const
{ {
component_type nred = yiq[0] + 0.9548892043*yiq[1] + 0.6221039350 typedef detail::RequiresExplicitCast<component_type> Convert;
*yiq[2]; component_type nred = Convert::cast(yiq[0] + 0.9548892043*yiq[1]
component_type ngreen = yiq[0] - 0.2713547827*yiq[1] - 0.6475120259 + 0.6221039350*yiq[2]);
*yiq[2]; component_type ngreen = Convert::cast(yiq[0] - 0.2713547827*yiq[1]
component_type nblue = yiq[0] - 1.1072510054*yiq[1] + 1.7024603738 - 0.6475120259*yiq[2]);
*yiq[2]; component_type nblue = Convert::cast(yiq[0] - 1.1072510054*yiq[1]
+ 1.7024603738*yiq[2]);
return result_type(NumericTraits<T>::fromRealPromote(nred * max_), return result_type(NumericTraits<T>::fromRealPromote(nred * max_),
<span class="insert">1.7024603738*yiq[2]);</span>
NumericTraits<T>::fromRealPromote(ngreen * max_) , NumericTraits<T>::fromRealPromote(ngreen * max_) ,
NumericTraits<T>::fromRealPromote(nblue * max_)) ; NumericTraits<T>::fromRealPromote(nblue * max_)) ;
} }
}; };
template <class T> template <class T>
class FunctorTraits<YPrimeIQ2RGBPrimeFunctor<T> > class FunctorTraits<YPrimeIQ2RGBPrimeFunctor<T> >
: public FunctorTraitsBase<YPrimeIQ2RGBPrimeFunctor<T> > : public FunctorTraitsBase<YPrimeIQ2RGBPrimeFunctor<T> >
{ {
skipping to change at line 2345 skipping to change at line 2391
*/ */
RGBPrime2YPrimeUVFunctor(component_type max) RGBPrime2YPrimeUVFunctor(component_type max)
: max_(max) : max_(max)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & rgb) const result_type operator()(V const & rgb) const
{ {
typedef detail::RequiresExplicitCast<component_type> Convert;
component_type red = rgb[0] / max_; component_type red = rgb[0] / max_;
component_type green = rgb[1] / max_; component_type green = rgb[1] / max_;
component_type blue = rgb[2] / max_; component_type blue = rgb[2] / max_;
result_type result; result_type result;
result[0] = 0.299*red + 0.587*green + 0.114*blue; result[0] = Convert::cast(0.299*red + 0.587*green + 0.114*blue);
result[1] = -0.1471376975*red - 0.2888623025*green + 0.436*blue; result[1] = Convert::cast(-0.1471376975*red - 0.2888623025*green +
result[2] = 0.6149122807*red - 0.5149122807*green - 0.100*blue; 0.436*blue);
result[2] = Convert::cast(0.6149122807*red - 0.5149122807*green - 0
.100*blue);
return result; return result;
} }
private: private:
component_type max_; component_type max_;
}; };
template <class T> template <class T>
class FunctorTraits<RGBPrime2YPrimeUVFunctor<T> > class FunctorTraits<RGBPrime2YPrimeUVFunctor<T> >
: public FunctorTraitsBase<RGBPrime2YPrimeUVFunctor<T> > : public FunctorTraitsBase<RGBPrime2YPrimeUVFunctor<T> >
skipping to change at line 2396 skipping to change at line 2443
public: public:
/** the functor's argument type. (Actually, the argument type /** the functor's argument type. (Actually, the argument type
can be any vector type with the same interface. can be any vector type with the same interface.
But this cannot be expressed in a typedef.) But this cannot be expressed in a typedef.)
*/ */
typedef TinyVector<T, 3> argument_type; typedef TinyVector<T, 3> argument_type;
/** the functor's result type /** the functor's result type
*/ */
typedef RGBValue<T> result_type; typedef TinyVector<T, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef RGBValue<T> value_type; typedef TinyVector<T, 3> value_type;
/** default constructor. /** default constructor.
The maximum value for each RGB component defaults to 255. The maximum value for each RGB component defaults to 255.
*/ */
YPrimeUV2RGBPrimeFunctor() YPrimeUV2RGBPrimeFunctor()
: max_(255.0) : max_(255.0)
{} {}
/** constructor /** constructor
\arg max - the maximum value for each RGB component \arg max - the maximum value for each RGB component
*/ */
YPrimeUV2RGBPrimeFunctor(component_type max) YPrimeUV2RGBPrimeFunctor(component_type max)
: max_(max) : max_(max)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & yuv) const result_type operator()(V const & yuv) const
{ {
component_type nred = yuv[0] + 1.140*yuv[2]; typedef detail::RequiresExplicitCast<component_type> Convert;
component_type ngreen = yuv[0] - 0.3946517044*yuv[1] - 0.580681431* component_type nred = Convert::cast(yuv[0] + 1.140*yuv[2]);
yuv[2]; component_type ngreen = Convert::cast(yuv[0] - 0.3946517044*yuv[1]
component_type nblue = yuv[0] + 2.0321100920*yuv[1]; - 0.580681431*yuv[2]);
component_type nblue = Convert::cast(yuv[0] + 2.0321100920*yuv[1])
;
return result_type(NumericTraits<T>::fromRealPromote(nred * max_), return result_type(NumericTraits<T>::fromRealPromote(nred * max_),
NumericTraits<T>::fromRealPromote(ngreen * max_) , NumericTraits<T>::fromRealPromote(ngreen * max_) ,
NumericTraits<T>::fromRealPromote(nblue * max_)) ; NumericTraits<T>::fromRealPromote(nblue * max_)) ;
} }
}; };
template <class T> template <class T>
class FunctorTraits<YPrimeUV2RGBPrimeFunctor<T> > class FunctorTraits<YPrimeUV2RGBPrimeFunctor<T> >
: public FunctorTraitsBase<YPrimeUV2RGBPrimeFunctor<T> > : public FunctorTraitsBase<YPrimeUV2RGBPrimeFunctor<T> >
{ {
skipping to change at line 2506 skipping to change at line 2554
*/ */
RGBPrime2YPrimeCbCrFunctor(component_type max) RGBPrime2YPrimeCbCrFunctor(component_type max)
: max_(max) : max_(max)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & rgb) const result_type operator()(V const & rgb) const
{ {
typedef detail::RequiresExplicitCast<component_type> Convert;
component_type red = rgb[0] / max_; component_type red = rgb[0] / max_;
component_type green = rgb[1] / max_; component_type green = rgb[1] / max_;
component_type blue = rgb[2] / max_; component_type blue = rgb[2] / max_;
result_type result; result_type result;
result[0] = 16.0 + 65.481*red + 128.553*green + 24.966*blue; result[0] = Convert::cast(16.0 + 65.481*red + 128.553*green + 24.96
result[1] = 128.0 - 37.79683972*red - 74.20316028*green + 112.0*blu 6*blue);
e; result[1] = Convert::cast(128.0 - 37.79683972*red - 74.20316028*gre
result[2] = 128.0 + 112.0*red - 93.78601998*green - 18.21398002*blu en + 112.0*blue);
e; result[2] = Convert::cast(128.0 + 112.0*red - 93.78601998*green - 1
8.21398002*blue);
return result; return result;
} }
private: private:
component_type max_; component_type max_;
}; };
template <class T> template <class T>
class FunctorTraits<RGBPrime2YPrimeCbCrFunctor<T> > class FunctorTraits<RGBPrime2YPrimeCbCrFunctor<T> >
: public FunctorTraitsBase<RGBPrime2YPrimeCbCrFunctor<T> > : public FunctorTraitsBase<RGBPrime2YPrimeCbCrFunctor<T> >
skipping to change at line 2557 skipping to change at line 2606
public: public:
/** the functor's argument type. (Actually, the argument type /** the functor's argument type. (Actually, the argument type
can be any vector type with the same interface. can be any vector type with the same interface.
But this cannot be expressed in a typedef.) But this cannot be expressed in a typedef.)
*/ */
typedef TinyVector<T, 3> argument_type; typedef TinyVector<T, 3> argument_type;
/** the functor's result type /** the functor's result type
*/ */
typedef RGBValue<T> result_type; typedef TinyVector<T, 3> result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef RGBValue<T> value_type; typedef TinyVector<T, 3> value_type;
/** default constructor. /** default constructor.
The maximum value for each RGB component defaults to 255. The maximum value for each RGB component defaults to 255.
*/ */
YPrimeCbCr2RGBPrimeFunctor() YPrimeCbCr2RGBPrimeFunctor()
: max_(255.0) : max_(255.0)
{} {}
/** constructor /** constructor
\arg max - the maximum value for each RGB component \arg max - the maximum value for each RGB component
*/ */
YPrimeCbCr2RGBPrimeFunctor(component_type max) YPrimeCbCr2RGBPrimeFunctor(component_type max)
: max_(max) : max_(max)
{} {}
/** apply the transformation /** apply the transformation
*/ */
template <class V> template <class V>
result_type operator()(V const & ycbcr) const result_type operator()(V const & ycbcr) const
{ {
component_type y = ycbcr[0] - 16.0; typedef detail::RequiresExplicitCast<component_type> Convert;
component_type cb = ycbcr[1] - 128.0; component_type y = Convert::cast(ycbcr[0] - 16.0);
component_type cr = ycbcr[2] - 128.0; component_type cb = Convert::cast(ycbcr[1] - 128.0);
component_type cr = Convert::cast(ycbcr[2] - 128.0);
component_type nred = 0.00456621*y + 0.006258928571*cr; component_type nred = Convert::cast(0.00456621*y + 0.006258928571
component_type ngreen = 0.00456621*y - 0.001536322706*cb - 0.003188 *cr);
108420*cr; component_type ngreen = Convert::cast(0.00456621*y - 0.001536322706
component_type nblue = 0.00456621*y + 0.007910714286*cb; *cb - 0.003188108420*cr);
component_type nblue = Convert::cast(0.00456621*y + 0.007910714286
*cb);
return result_type(NumericTraits<T>::fromRealPromote(nred * max_), return result_type(NumericTraits<T>::fromRealPromote(nred * max_),
NumericTraits<T>::fromRealPromote(ngreen * max_) , NumericTraits<T>::fromRealPromote(ngreen * max_) ,
NumericTraits<T>::fromRealPromote(nblue * max_)) ; NumericTraits<T>::fromRealPromote(nblue * max_)) ;
} }
}; };
template <class T> template <class T>
class FunctorTraits<YPrimeCbCr2RGBPrimeFunctor<T> > class FunctorTraits<YPrimeCbCr2RGBPrimeFunctor<T> >
: public FunctorTraitsBase<YPrimeCbCr2RGBPrimeFunctor<T> > : public FunctorTraitsBase<YPrimeCbCr2RGBPrimeFunctor<T> >
{ {
skipping to change at line 2713 skipping to change at line 2763
magenta = [288.237, 0.603235, 0.863482] magenta = [288.237, 0.603235, 0.863482]
\endcode \endcode
*/ */
inline TinyVector<float, 3> inline TinyVector<float, 3>
polar2Lab(double color, double brightness, double saturation) polar2Lab(double color, double brightness, double saturation)
{ {
double angle = (color+39.9977)/180.0*M_PI; double angle = (color+39.9977)/180.0*M_PI;
double normsat = saturation*133.809; double normsat = saturation*133.809;
TinyVector<float, 3> result; TinyVector<float, 3> result;
result[0] = 100.0*brightness; result[0] = float(100.0*brightness);
result[1] = normsat*VIGRA_CSTD::cos(angle); result[1] = float(normsat*VIGRA_CSTD::cos(angle));
result[2] = normsat*VIGRA_CSTD::sin(angle); result[2] = float(normsat*VIGRA_CSTD::sin(angle));
return result; return result;
} }
template <class V> template <class V>
TinyVector<float, 3> TinyVector<float, 3>
polar2Lab(V const & polar) polar2Lab(V const & polar)
{ {
return polar2Lab(polar[0], polar[1], polar[2]); return polar2Lab(polar[0], polar[1], polar[2]);
} }
skipping to change at line 2747 skipping to change at line 2797
Namespace: vigra Namespace: vigra
This realizes the inverse of the transformation described in This realizes the inverse of the transformation described in
\ref polar2Lab(). \ref polar2Lab().
*/ */
template <class V> template <class V>
TinyVector<float, 3> TinyVector<float, 3>
lab2Polar(V const & lab) lab2Polar(V const & lab)
{ {
TinyVector<float, 3> result; TinyVector<float, 3> result;
result[1] = lab[0]/100.0; result[1] = float(lab[0]/100.0);
double angle = (lab[1] == 0.0 && lab[2] == 0.0) double angle = (lab[1] == 0.0 && lab[2] == 0.0)
? 0.0 ? 0.0
: VIGRA_CSTD::atan2(lab[2], lab[1])/M_PI*180.0-39.9977; : VIGRA_CSTD::atan2(lab[2], lab[1])/M_PI*180.0-39.9977;
result[0] = angle < 0.0 ? result[0] = angle < 0.0 ?
angle + 360.0 : float(angle + 360.0) :
angle; float(angle);
result[2] = VIGRA_CSTD::sqrt(lab[1]*lab[1] + lab[2]*lab[2])/133.809; result[2] = float(VIGRA_CSTD::sqrt(lab[1]*lab[1] + lab[2]*lab[2])/133.8
09);
return result; return result;
} }
/** \brief Init L*u*v* color triple from polar representation. /** \brief Init L*u*v* color triple from polar representation.
<b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br> <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br>
Namespace: vigra Namespace: vigra
<b> Declarations:</b> <b> Declarations:</b>
skipping to change at line 2798 skipping to change at line 2848
magenta = [295.553, 0.603235, 0.767457] magenta = [295.553, 0.603235, 0.767457]
\endcode \endcode
*/ */
inline TinyVector<float, 3> inline TinyVector<float, 3>
polar2Luv(double color, double brightness, double saturation) polar2Luv(double color, double brightness, double saturation)
{ {
double angle = (color+12.1727)/180.0*M_PI; double angle = (color+12.1727)/180.0*M_PI;
double normsat = saturation*179.04; double normsat = saturation*179.04;
TinyVector<float, 3> result; TinyVector<float, 3> result;
result[0] = 100.0*brightness; result[0] = float(100.0*brightness);
result[1] = normsat*VIGRA_CSTD::cos(angle); result[1] = float(normsat*VIGRA_CSTD::cos(angle));
result[2] = normsat*VIGRA_CSTD::sin(angle); result[2] = float(normsat*VIGRA_CSTD::sin(angle));
return result; return result;
} }
template <class V> template <class V>
TinyVector<float, 3> TinyVector<float, 3>
polar2Luv(V const & polar) polar2Luv(V const & polar)
{ {
return polar2Luv(polar[0], polar[1], polar[2]); return polar2Luv(polar[0], polar[1], polar[2]);
} }
skipping to change at line 2832 skipping to change at line 2882
Namespace: vigra Namespace: vigra
This realizes the inverse of the transformation described in This realizes the inverse of the transformation described in
\ref polar2Luv(). \ref polar2Luv().
*/ */
template <class V> template <class V>
TinyVector<float, 3> TinyVector<float, 3>
luv2Polar(V const & luv) luv2Polar(V const & luv)
{ {
TinyVector<float, 3> result; TinyVector<float, 3> result;
result[1] = luv[0]/100.0; result[1] = float(luv[0]/100.0);
double angle = (luv[1] == 0.0 && luv[2] == 0.0) double angle = (luv[1] == 0.0 && luv[2] == 0.0)
? 0.0 ? 0.0
: VIGRA_CSTD::atan2(luv[2], luv[1])/M_PI*180.0-12.1727; : VIGRA_CSTD::atan2(luv[2], luv[1])/M_PI*180.0-12.1727;
result[0] = angle < 0.0 ? result[0] = angle < 0.0 ?
angle + 360.0 : float(angle + 360.0) :
angle; float(angle);
result[2] = VIGRA_CSTD::sqrt(luv[1]*luv[1] + luv[2]*luv[2])/179.04; result[2] = float(VIGRA_CSTD::sqrt(luv[1]*luv[1] + luv[2]*luv[2])/179.0
4);
return result; return result;
} }
/** \brief Init Y'PbPr color triple from polar representation. /** \brief Init Y'PbPr color triple from polar representation.
<b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br> <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br>
Namespace: vigra Namespace: vigra
<b> Declarations:</b> <b> Declarations:</b>
skipping to change at line 2883 skipping to change at line 2933
magenta = [303.001, 0.413, 1] magenta = [303.001, 0.413, 1]
\endcode \endcode
*/ */
inline TinyVector<float, 3> inline TinyVector<float, 3>
polar2YPrimePbPr(double color, double brightness, double saturation) polar2YPrimePbPr(double color, double brightness, double saturation)
{ {
double angle = (color+18.6481)/180.0*M_PI; double angle = (color+18.6481)/180.0*M_PI;
double normsat = saturation*0.533887; double normsat = saturation*0.533887;
TinyVector<float, 3> result; TinyVector<float, 3> result;
result[0] = brightness; result[0] = float(brightness);
result[1] = -normsat*VIGRA_CSTD::sin(angle); result[1] = float(-normsat*VIGRA_CSTD::sin(angle));
result[2] = normsat*VIGRA_CSTD::cos(angle); result[2] = float(normsat*VIGRA_CSTD::cos(angle));
return result; return result;
} }
template <class V> template <class V>
TinyVector<float, 3> TinyVector<float, 3>
polar2YPrimePbPr(V const & polar) polar2YPrimePbPr(V const & polar)
{ {
return polar2YPrimePbPr(polar[0], polar[1], polar[2]); return polar2YPrimePbPr(polar[0], polar[1], polar[2]);
} }
skipping to change at line 2917 skipping to change at line 2967
Namespace: vigra Namespace: vigra
This realizes the inverse of the transformation described in This realizes the inverse of the transformation described in
\ref polar2YPrimePbPr(). \ref polar2YPrimePbPr().
*/ */
template <class V> template <class V>
TinyVector<float, 3> TinyVector<float, 3>
yPrimePbPr2Polar(V const & ypbpr) yPrimePbPr2Polar(V const & ypbpr)
{ {
TinyVector<float, 3> result; TinyVector<float, 3> result;
result[1] = ypbpr[0]; result[1] = float(ypbpr[0]);
double angle = (ypbpr[1] == 0.0 && ypbpr[2] == 0.0) double angle = (ypbpr[1] == 0.0 && ypbpr[2] == 0.0)
? 0.0 ? 0.0
: VIGRA_CSTD::atan2(-ypbpr[1], ypbpr[2])/M_PI*180.0-18.6481; : VIGRA_CSTD::atan2(-ypbpr[1], ypbpr[2])/M_PI*180.0-18.6481;
result[0] = angle < 0.0 ? result[0] = angle < 0.0 ?
angle + 360.0 : float(angle + 360.0) :
angle; float(angle);
result[2] = VIGRA_CSTD::sqrt(ypbpr[1]*ypbpr[1] + ypbpr[2]*ypbpr[2])/0.5 result[2] = float(VIGRA_CSTD::sqrt(ypbpr[1]*ypbpr[1] + ypbpr[2]*ypbpr[2
33887; ])/0.533887);
return result; return result;
} }
/** \brief Init Y'CbCr color triple from polar representation. /** \brief Init Y'CbCr color triple from polar representation.
<b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br> <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br>
Namespace: vigra Namespace: vigra
<b> Declarations:</b> <b> Declarations:</b>
skipping to change at line 2968 skipping to change at line 3018
magenta = [303.001, 0.413, 1] magenta = [303.001, 0.413, 1]
\endcode \endcode
*/ */
inline TinyVector<float, 3> inline TinyVector<float, 3>
polar2YPrimeCbCr(double color, double brightness, double saturation) polar2YPrimeCbCr(double color, double brightness, double saturation)
{ {
double angle = (color+18.6482)/180.0*M_PI; double angle = (color+18.6482)/180.0*M_PI;
double normsat = saturation*119.591; double normsat = saturation*119.591;
TinyVector<float, 3> result; TinyVector<float, 3> result;
result[0] = brightness*219.0 + 16.0; result[0] = float(brightness*219.0 + 16.0);
result[1] = -normsat*VIGRA_CSTD::sin(angle)+128.0; result[1] = float(-normsat*VIGRA_CSTD::sin(angle)+128.0);
result[2] = normsat*VIGRA_CSTD::cos(angle)+128.0; result[2] = float(normsat*VIGRA_CSTD::cos(angle)+128.0);
return result; return result;
} }
template <class V> template <class V>
TinyVector<float, 3> TinyVector<float, 3>
polar2YPrimeCbCr(V const & polar) polar2YPrimeCbCr(V const & polar)
{ {
return polar2YPrimeCbCr(polar[0], polar[1], polar[2]); return polar2YPrimeCbCr(polar[0], polar[1], polar[2]);
} }
skipping to change at line 3002 skipping to change at line 3052
Namespace: vigra Namespace: vigra
This realizes the inverse of the transformation described in This realizes the inverse of the transformation described in
\ref polar2YPrimeCbCr(). \ref polar2YPrimeCbCr().
*/ */
template <class V> template <class V>
TinyVector<float, 3> TinyVector<float, 3>
yPrimeCbCr2Polar(V const & ycbcr) yPrimeCbCr2Polar(V const & ycbcr)
{ {
TinyVector<float, 3> result; TinyVector<float, 3> result;
result[1] = (ycbcr[0]-16.0)/219.0; result[1] = float((ycbcr[0]-16.0)/219.0);
double cb = ycbcr[1]-128.0; double cb = ycbcr[1]-128.0;
double cr = ycbcr[2]-128.0; double cr = ycbcr[2]-128.0;
double angle = (cb == 0.0 && cr == 0.0) double angle = (cb == 0.0 && cr == 0.0)
? 0.0 ? 0.0
: VIGRA_CSTD::atan2(-cb, cr)/M_PI*180.0-18.6482; : VIGRA_CSTD::atan2(-cb, cr)/M_PI*180.0-18.6482;
result[0] = angle < 0.0 ? result[0] = angle < 0.0 ?
angle + 360.0 : float(angle + 360.0) :
angle; float(angle);
result[2] = VIGRA_CSTD::sqrt(cb*cb + cr*cr)/119.591; result[2] = float(VIGRA_CSTD::sqrt(cb*cb + cr*cr)/119.591);
return result; return result;
} }
/** \brief Init Y'IQ color triple from polar representation. /** \brief Init Y'IQ color triple from polar representation.
<b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br> <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br>
Namespace: vigra Namespace: vigra
<b> Declarations:</b> <b> Declarations:</b>
skipping to change at line 3055 skipping to change at line 3105
magenta = [317.231, 0.413, 0.933362] magenta = [317.231, 0.413, 0.933362]
\endcode \endcode
*/ */
inline TinyVector<float, 3> inline TinyVector<float, 3>
polar2YPrimeIQ(double color, double brightness, double saturation) polar2YPrimeIQ(double color, double brightness, double saturation)
{ {
double angle = (color-19.5807)/180.0*M_PI; double angle = (color-19.5807)/180.0*M_PI;
double normsat = saturation*0.632582; double normsat = saturation*0.632582;
TinyVector<float, 3> result; TinyVector<float, 3> result;
result[0] = brightness; result[0] = float(brightness);
result[1] = normsat*VIGRA_CSTD::cos(angle); result[1] = float(normsat*VIGRA_CSTD::cos(angle));
result[2] = -normsat*VIGRA_CSTD::sin(angle); result[2] = float(-normsat*VIGRA_CSTD::sin(angle));
return result; return result;
} }
template <class V> template <class V>
TinyVector<float, 3> TinyVector<float, 3>
polar2YPrimeIQ(V const & polar) polar2YPrimeIQ(V const & polar)
{ {
return polar2YPrimeIQ(polar[0], polar[1], polar[2]); return polar2YPrimeIQ(polar[0], polar[1], polar[2]);
} }
skipping to change at line 3089 skipping to change at line 3139
Namespace: vigra Namespace: vigra
This realizes the inverse of the transformation described in This realizes the inverse of the transformation described in
\ref polar2YPrimeIQ(). \ref polar2YPrimeIQ().
*/ */
template <class V> template <class V>
TinyVector<float, 3> TinyVector<float, 3>
yPrimeIQ2Polar(V const & yiq) yPrimeIQ2Polar(V const & yiq)
{ {
TinyVector<float, 3> result; TinyVector<float, 3> result;
result[1] = yiq[0]; result[1] = float(yiq[0]);
double angle = (yiq[1] == 0.0 && yiq[2] == 0.0) double angle = (yiq[1] == 0.0 && yiq[2] == 0.0)
? 0.0 ? 0.0
: VIGRA_CSTD::atan2(-yiq[2], yiq[1])/M_PI*180.0+19.5807; : VIGRA_CSTD::atan2(-yiq[2], yiq[1])/M_PI*180.0+19.5807;
result[0] = angle < 0.0 ? result[0] = angle < 0.0 ?
angle + 360.0 : float(angle + 360.0) :
angle; float(angle);
result[2] = VIGRA_CSTD::sqrt(yiq[1]*yiq[1] + yiq[2]*yiq[2])/0.632582; result[2] = float(VIGRA_CSTD::sqrt(yiq[1]*yiq[1] + yiq[2]*yiq[2])/0.632
582);
return result; return result;
} }
/** \brief Init Y'UV color triple from polar representation. /** \brief Init Y'UV color triple from polar representation.
<b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br> <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/co lorconversions.hxx</a>\><br>
Namespace: vigra Namespace: vigra
<b> Declarations:</b> <b> Declarations:</b>
skipping to change at line 3140 skipping to change at line 3190
magenta = [317.231, 0.413, 0.933362] magenta = [317.231, 0.413, 0.933362]
\endcode \endcode
*/ */
inline TinyVector<float, 3> inline TinyVector<float, 3>
polar2YPrimeUV(double color, double brightness, double saturation) polar2YPrimeUV(double color, double brightness, double saturation)
{ {
double angle = (color+13.4569)/180.0*M_PI; double angle = (color+13.4569)/180.0*M_PI;
double normsat = saturation*0.632324; double normsat = saturation*0.632324;
TinyVector<float, 3> result; TinyVector<float, 3> result;
result[0] = brightness; result[0] = float(brightness);
result[1] = -normsat*VIGRA_CSTD::sin(angle); result[1] = float(-normsat*VIGRA_CSTD::sin(angle));
result[2] = normsat*VIGRA_CSTD::cos(angle); result[2] = float(normsat*VIGRA_CSTD::cos(angle));
return result; return result;
} }
template <class V> template <class V>
TinyVector<float, 3> TinyVector<float, 3>
polar2YPrimeUV(V const & polar) polar2YPrimeUV(V const & polar)
{ {
return polar2YPrimeUV(polar[0], polar[1], polar[2]); return polar2YPrimeUV(polar[0], polar[1], polar[2]);
} }
skipping to change at line 3174 skipping to change at line 3224
Namespace: vigra Namespace: vigra
This realizes the inverse of the transformation described in This realizes the inverse of the transformation described in
\ref polar2YPrimeUV(). \ref polar2YPrimeUV().
*/ */
template <class V> template <class V>
TinyVector<float, 3> TinyVector<float, 3>
yPrimeUV2Polar(V const & yuv) yPrimeUV2Polar(V const & yuv)
{ {
TinyVector<float, 3> result; TinyVector<float, 3> result;
result[1] = yuv[0]; result[1] = float(yuv[0]);
double angle = (yuv[1] == 0.0 && yuv[2] == 0.0) double angle = (yuv[1] == 0.0 && yuv[2] == 0.0)
? 0.0 ? 0.0
: VIGRA_CSTD::atan2(-yuv[1], yuv[2])/M_PI*180.0-13.4569; : VIGRA_CSTD::atan2(-yuv[1], yuv[2])/M_PI*180.0-13.4569;
result[0] = angle < 0.0 ? result[0] = angle < 0.0 ?
angle + 360.0 : float(angle + 360.0) :
angle; float(angle);
result[2] = VIGRA_CSTD::sqrt(yuv[1]*yuv[1] + yuv[2]*yuv[2])/0.632324; result[2] = float(VIGRA_CSTD::sqrt(yuv[1]*yuv[1] + yuv[2]*yuv[2])/0.632
324);
return result; return result;
} }
//@} //@}
} // namespace vigra } // namespace vigra
#endif /* VIGRA_COLORCONVERSIONS_HXX */ #endif /* VIGRA_COLORCONVERSIONS_HXX */
 End of changes. 119 change blocks. 
258 lines changed or deleted 335 lines changed or added


 combineimages.hxx   combineimages.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 config.hxx   config.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 41 skipping to change at line 39
/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_CONFIG_HXX #ifndef VIGRA_CONFIG_HXX
#define VIGRA_CONFIG_HXX #define VIGRA_CONFIG_HXX
#include <vigra/configVersion.hxx>
#include <stdexcept> #include <stdexcept>
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// // // //
// VisualC++ 5.0 // // VisualC++ 5.0 //
// // // //
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
#ifdef _MSC_VER #ifdef _MSC_VER
#if(_MSC_VER < 1100) // before VisualC++ 5.0 #if(_MSC_VER < 1100) // before VisualC++ 5.0
#error "Need VisualC++ 5.0, Service Pack 2, or later" #error "Need VisualC++ 5.0, Service Pack 2, or later"
#endif // _MSC_VER < 1100 #endif // _MSC_VER < 1100
#pragma warning( disable : 4786 4250 4244 4305)
#if (_MSC_VER < 1300) #if (_MSC_VER < 1300)
#define NO_TYPENAME // no 'typename' keyword #define NO_TYPENAME // no 'typename' keyword
#define TEMPLATE_COPY_CONSTRUCTOR_BUG #define TEMPLATE_COPY_CONSTRUCTOR_BUG
#define NO_STL_MEMBER_TEMPLATES #define NO_STL_MEMBER_TEMPLATES
#define NO_INLINE_STATIC_CONST_DEFINITION #define NO_INLINE_STATIC_CONST_DEFINITION
#define CMATH_NOT_IN_STD #define CMATH_NOT_IN_STD
#define NO_COVARIANT_RETURN_TYPES #define NO_COVARIANT_RETURN_TYPES
#ifdef VIGRA_NO_STD_MINMAX // activate if necessary #ifdef VIGRA_NO_STD_MINMAX // activate if necessary
namespace std { namespace std {
skipping to change at line 87 skipping to change at line 84
{ {
return (x < y) return (x < y)
? y ? y
: x; : x;
} }
} }
#endif // VIGRA_NO_STD_MINMAX #endif // VIGRA_NO_STD_MINMAX
#endif // (_MSC_VER < 1300) #endif // (_MSC_VER < 1300)
#if _MSC_VER < 1310 #if _MSC_VER < 1310
#pragma warning( disable : 4786 4250 4244 4305)
#define NO_PARTIAL_TEMPLATE_SPECIALIZATION #define NO_PARTIAL_TEMPLATE_SPECIALIZATION
#define NO_OUT_OF_LINE_MEMBER_TEMPLATES #define NO_OUT_OF_LINE_MEMBER_TEMPLATES
#include <cmath> #include <cmath>
#ifdef _MSC_EXTENSIONS #ifdef _MSC_EXTENSIONS
#ifndef CMATH_NOT_IN_STD #ifndef CMATH_NOT_IN_STD
namespace std { namespace std {
#endif // CMATH_NOT_IN_STD #endif // CMATH_NOT_IN_STD
inline double abs(double v) { return fabs(v); } inline double abs(double v) { return fabs(v); }
inline float abs(float v) { return fabs(v); } inline float abs(float v) { return fabs(v); }
 End of changes. 6 change blocks. 
5 lines changed or deleted 4 lines changed or added


 contourcirculator.hxx   contourcirculator.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 convolution.hxx   convolution.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 262 skipping to change at line 260
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class T> class T>
void convolveImage(SrcIterator supperleft, void convolveImage(SrcIterator supperleft,
SrcIterator slowerright, SrcAccessor sa, SrcIterator slowerright, SrcAccessor sa,
DestIterator dupperleft, DestAccessor da, DestIterator dupperleft, DestAccessor da,
Kernel1D<T> const & kx, Kernel1D<T> const & ky) Kernel1D<T> const & kx, Kernel1D<T> const & ky)
{ {
typedef typename typedef typename
NumericTraits<typename SrcAccessor::value_type>::RealPromote NumericTraits<typename SrcAccessor::value_type>::RealPromote
TmpType; TmpType;
BasicImage<TmpType> tmp(slowerright - supperleft); BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
separableConvolveX(srcIterRange(supperleft, slowerright, sa), separableConvolveX(srcIterRange(supperleft, slowerright, sa),
destImage(tmp), kernel1d(kx)); destImage(tmp), kernel1d(kx));
separableConvolveY(srcImageRange(tmp), separableConvolveY(srcImageRange(tmp),
destIter(dupperleft, da), kernel1d(ky)); destIter(dupperleft, da), kernel1d(ky));
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class T> class T>
skipping to change at line 290 skipping to change at line 288
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* simpleSharpening */ /* simpleSharpening */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Perform simple sharpening function. /** \brief Perform simple sharpening function.
This function use \ref convolveImage() with following filter: This function uses \ref convolveImage() with the following filter:
\code \code
-sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_fact or/16.0, -sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_fact or/16.0,
-sharpening_factor/8.0, 1.0+sharpening_factor*0.75, -sharpening_fact or/8.0, -sharpening_factor/8.0, 1.0+sharpening_factor*0.75, -sharpening_fact or/8.0,
-sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_fact or/16.0; -sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_fact or/16.0;
\endcode \endcode
and use <TT>BORDER_TREATMENT_REFLECT</TT> as border treatment mode. and uses <TT>BORDER_TREATMENT_REFLECT</TT> as border treatment mode.
<b> Preconditions:</b> <b> Preconditions:</b>
\code \code
1. sharpening_factor >= 0 1. sharpening_factor >= 0
2. scale >= 0 2. scale >= 0
\endcode \endcode
<b> Declarations:</b> <b> Declarations:</b>
<b> Declarations:</b> <b> Declarations:</b>
skipping to change at line 391 skipping to change at line 389
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* gaussianSharpening */ /* gaussianSharpening */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Perform sharpening function with gaussian filter. /** \brief Perform sharpening function with gaussian filter.
This function use the \ref gaussianSmoothing() This function uses \ref gaussianSmoothing() at the given scale to creat
at first and scale the source image e a
(\code src \endcode) with the \code scale \endcode temporary image 'smooth' and than blends the original and smoothed imag
factor in an temporary image (\code tmp \endcode). At second the new e
pixel in the destination image will be with following according to the formula
formel calculate:
\code \code
dest = (1 + sharpening_factor)*src - sharpening_factor*tmp dest = (1 + sharpening_factor)*src - sharpening_factor*smooth
\endcode \endcode
<b> Preconditions:</b> <b> Preconditions:</b>
\code \code
1. sharpening_factor >= 0 1. sharpening_factor >= 0
2. scale >= 0 2. scale >= 0
\endcode \endcode
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void gaussianSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAc cessor src_acc, void gaussianSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAc cessor src_acc,
DestIterator dest_ul, DestAccessor dest_acc DestIterator dest_ul, DestAccessor dest_acc,
, double sharpening_factor, double sharpening_factor, double scale)
double scale)
} }
\endcode \endcode
use argument objects in conjunction with \ref ArgumentObjectFactories : use argument objects in conjunction with \ref ArgumentObjectFactories :
\code \code
namespace vigra { namespace vigra {
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void gaussianSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src, void gaussianSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src,
pair<DestIterator, DestAccessor> dest, doubl pair<DestIterator, DestAccessor> dest,
e sharpening_factor, double sharpening_factor, double scale)
double scale)
} }
\endcode \endcode
<b> Usage:</b> <b> Usage:</b>
<b>\#include</b> \<<a href="convolution_8hxx-source.html">vigra/convolu tion.hxx</a>\> <b>\#include</b> \<<a href="convolution_8hxx-source.html">vigra/convolu tion.hxx</a>\>
\code \code
vigra::FImage src(w,h), dest(w,h); vigra::FImage src(w,h), dest(w,h);
... ...
skipping to change at line 461 skipping to change at line 457
DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor, DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor,
double scale) double scale)
{ {
vigra_precondition(sharpening_factor >= 0.0, vigra_precondition(sharpening_factor >= 0.0,
"gaussianSharpening(): amount of sharpening must be >= 0"); "gaussianSharpening(): amount of sharpening must be >= 0");
vigra_precondition(scale >= 0.0, vigra_precondition(scale >= 0.0,
"gaussianSharpening(): scale parameter should be >= 0."); "gaussianSharpening(): scale parameter should be >= 0.");
typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP romote ValueType; typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP romote ValueType;
BasicImage<ValueType> tmp(src_lr - src_ul); BasicImage<ValueType> tmp(src_lr - src_ul, SkipInitialization);
gaussianSmoothing(src_ul, src_lr, src_acc, tmp.upperLeft(), tmp.accesso r(), scale); gaussianSmoothing(src_ul, src_lr, src_acc, tmp.upperLeft(), tmp.accesso r(), scale);
SrcIterator i_src = src_ul; SrcIterator i_src = src_ul;
DestIterator i_dest = dest_ul; DestIterator i_dest = dest_ul;
typename BasicImage<ValueType>::traverser tmp_ul = tmp.upperLeft(); typename BasicImage<ValueType>::traverser tmp_ul = tmp.upperLeft();
typename BasicImage<ValueType>::traverser i_tmp = tmp_ul; typename BasicImage<ValueType>::traverser i_tmp = tmp_ul;
typename BasicImage<ValueType>::Accessor tmp_acc = tmp.accessor(); typename BasicImage<ValueType>::Accessor tmp_acc = tmp.accessor();
for(; i_src.y != src_lr.y ; i_src.y++, i_dest.y++, i_tmp.y++ ) for(; i_src.y != src_lr.y ; i_src.y++, i_dest.y++, i_tmp.y++ )
skipping to change at line 559 skipping to change at line 555
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void gaussianSmoothing(SrcIterator supperleft, void gaussianSmoothing(SrcIterator supperleft,
SrcIterator slowerright, SrcAccessor sa, SrcIterator slowerright, SrcAccessor sa,
DestIterator dupperleft, DestAccessor da, DestIterator dupperleft, DestAccessor da,
double scale) double scale)
{ {
typedef typename typedef typename
NumericTraits<typename SrcAccessor::value_type>::RealPromote NumericTraits<typename SrcAccessor::value_type>::RealPromote
TmpType; TmpType;
BasicImage<TmpType> tmp(slowerright - supperleft); BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
Kernel1D<double> smooth; Kernel1D<double> smooth;
smooth.initGaussian(scale); smooth.initGaussian(scale);
smooth.setBorderTreatment(BORDER_TREATMENT_REFLECT); smooth.setBorderTreatment(BORDER_TREATMENT_REFLECT);
separableConvolveX(srcIterRange(supperleft, slowerright, sa), separableConvolveX(srcIterRange(supperleft, slowerright, sa),
destImage(tmp), kernel1d(smooth)); destImage(tmp), kernel1d(smooth));
separableConvolveY(srcImageRange(tmp), separableConvolveY(srcImageRange(tmp),
destIter(dupperleft, da), kernel1d(smooth)); destIter(dupperleft, da), kernel1d(smooth));
} }
skipping to change at line 674 skipping to change at line 670
class DestIteratorY, class DestAccessorY> class DestIteratorY, class DestAccessorY>
void gaussianGradient(SrcIterator supperleft, void gaussianGradient(SrcIterator supperleft,
SrcIterator slowerright, SrcAccessor sa, SrcIterator slowerright, SrcAccessor sa,
DestIteratorX dupperleftx, DestAccessorX dax, DestIteratorX dupperleftx, DestAccessorX dax,
DestIteratorY dupperlefty, DestAccessorY day, DestIteratorY dupperlefty, DestAccessorY day,
double scale) double scale)
{ {
typedef typename typedef typename
NumericTraits<typename SrcAccessor::value_type>::RealPromote NumericTraits<typename SrcAccessor::value_type>::RealPromote
TmpType; TmpType;
BasicImage<TmpType> tmp(slowerright - supperleft); BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
Kernel1D<double> smooth, grad; Kernel1D<double> smooth, grad;
smooth.initGaussian(scale); smooth.initGaussian(scale);
grad.initGaussianDerivative(scale, 1); grad.initGaussianDerivative(scale, 1);
separableConvolveX(srcIterRange(supperleft, slowerright, sa), separableConvolveX(srcIterRange(supperleft, slowerright, sa),
destImage(tmp), kernel1d(grad)); destImage(tmp), kernel1d(grad));
separableConvolveY(srcImageRange(tmp), separableConvolveY(srcImageRange(tmp),
destIter(dupperleftx, dax), kernel1d(smooth)); destIter(dupperleftx, dax), kernel1d(smooth));
separableConvolveX(srcIterRange(supperleft, slowerright, sa), separableConvolveX(srcIterRange(supperleft, slowerright, sa),
skipping to change at line 784 skipping to change at line 780
doxygen_overloaded_function(template <...> void gaussianGradientMagnitude) doxygen_overloaded_function(template <...> void gaussianGradientMagnitude)
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void gaussianGradientMagnitude(SrcIterator sul, void gaussianGradientMagnitude(SrcIterator sul,
SrcIterator slr, SrcAccessor src, SrcIterator slr, SrcAccessor src,
DestIterator dupperleft, DestAccessor dest, DestIterator dupperleft, DestAccessor dest,
double scale) double scale)
{ {
typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP romote TmpType; typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP romote TmpType;
BasicImage<TmpType> gradx(slr-sul), grady(slr-sul); BasicImage<TmpType> gradx(slr-sul, SkipInitialization), grady(slr-sul, SkipInitialization);
gaussianGradient(srcIterRange(sul, slr, src), gaussianGradient(srcIterRange(sul, slr, src),
destImage(gradx), destImage(grady), scale); destImage(gradx), destImage(grady), scale);
combineTwoImages(srcImageRange(gradx), srcImage(grady), destIter(dupper left, dest), combineTwoImages(srcImageRange(gradx), srcImage(grady), destIter(dupper left, dest),
MagnitudeFunctor<TmpType>()); MagnitudeFunctor<TmpType>());
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline void inline void
skipping to change at line 868 skipping to change at line 864
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void laplacianOfGaussian(SrcIterator supperleft, void laplacianOfGaussian(SrcIterator supperleft,
SrcIterator slowerright, SrcAccessor sa, SrcIterator slowerright, SrcAccessor sa,
DestIterator dupperleft, DestAccessor da, DestIterator dupperleft, DestAccessor da,
double scale) double scale)
{ {
typedef typename typedef typename
NumericTraits<typename SrcAccessor::value_type>::RealPromote NumericTraits<typename SrcAccessor::value_type>::RealPromote
TmpType; TmpType;
BasicImage<TmpType> tmp(slowerright - supperleft), BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization),
tmpx(slowerright - supperleft), tmpx(slowerright - supperleft, SkipInitialization),
tmpy(slowerright - supperleft); tmpy(slowerright - supperleft, SkipInitialization);
Kernel1D<double> smooth, deriv; Kernel1D<double> smooth, deriv;
smooth.initGaussian(scale); smooth.initGaussian(scale);
deriv.initGaussianDerivative(scale, 2); deriv.initGaussianDerivative(scale, 2);
separableConvolveX(srcIterRange(supperleft, slowerright, sa), separableConvolveX(srcIterRange(supperleft, slowerright, sa),
destImage(tmp), kernel1d(deriv)); destImage(tmp), kernel1d(deriv));
separableConvolveY(srcImageRange(tmp), separableConvolveY(srcImageRange(tmp),
destImage(tmpx), kernel1d(smooth)); destImage(tmpx), kernel1d(smooth));
separableConvolveX(srcIterRange(supperleft, slowerright, sa), separableConvolveX(srcIterRange(supperleft, slowerright, sa),
skipping to change at line 993 skipping to change at line 989
void hessianMatrixOfGaussian(SrcIterator supperleft, void hessianMatrixOfGaussian(SrcIterator supperleft,
SrcIterator slowerright, SrcAccessor sa, SrcIterator slowerright, SrcAccessor sa,
DestIteratorX dupperleftx, DestAccessorX dax, DestIteratorX dupperleftx, DestAccessorX dax,
DestIteratorXY dupperleftxy, DestAccessorXY daxy, DestIteratorXY dupperleftxy, DestAccessorXY daxy,
DestIteratorY dupperlefty, DestAccessorY day, DestIteratorY dupperlefty, DestAccessorY day,
double scale) double scale)
{ {
typedef typename typedef typename
NumericTraits<typename SrcAccessor::value_type>::RealPromote NumericTraits<typename SrcAccessor::value_type>::RealPromote
TmpType; TmpType;
BasicImage<TmpType> tmp(slowerright - supperleft); BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization);
Kernel1D<double> smooth, deriv1, deriv2; Kernel1D<double> smooth, deriv1, deriv2;
smooth.initGaussian(scale); smooth.initGaussian(scale);
deriv1.initGaussianDerivative(scale, 1); deriv1.initGaussianDerivative(scale, 1);
deriv2.initGaussianDerivative(scale, 2); deriv2.initGaussianDerivative(scale, 2);
separableConvolveX(srcIterRange(supperleft, slowerright, sa), separableConvolveX(srcIterRange(supperleft, slowerright, sa),
destImage(tmp), kernel1d(deriv2)); destImage(tmp), kernel1d(deriv2));
separableConvolveY(srcImageRange(tmp), separableConvolveY(srcImageRange(tmp),
destIter(dupperleftx, dax), kernel1d(smooth)); destIter(dupperleftx, dax), kernel1d(smooth));
skipping to change at line 1156 skipping to change at line 1152
void structureTensor(SrcIterator supperleft, void structureTensor(SrcIterator supperleft,
SrcIterator slowerright, SrcAccessor sa, SrcIterator slowerright, SrcAccessor sa,
DestIteratorX dupperleftx, DestAccessorX dax, DestIteratorX dupperleftx, DestAccessorX dax,
DestIteratorXY dupperleftxy, DestAccessorXY daxy, DestIteratorXY dupperleftxy, DestAccessorXY daxy,
DestIteratorY dupperlefty, DestAccessorY day, DestIteratorY dupperlefty, DestAccessorY day,
double inner_scale, double outer_scale) double inner_scale, double outer_scale)
{ {
typedef typename typedef typename
NumericTraits<typename SrcAccessor::value_type>::RealPromote NumericTraits<typename SrcAccessor::value_type>::RealPromote
TmpType; TmpType;
BasicImage<TmpType> tmp(slowerright - supperleft), BasicImage<TmpType> tmp(slowerright - supperleft, SkipInitialization),
tmpx(slowerright - supperleft), tmpx(slowerright - supperleft, SkipInitialization),
tmpy(slowerright - supperleft); tmpy(slowerright - supperleft, SkipInitialization);
gaussianGradient(srcIterRange(supperleft, slowerright, sa), gaussianGradient(srcIterRange(supperleft, slowerright, sa),
destImage(tmpx), destImage(tmpy), inner_scale); destImage(tmpx), destImage(tmpy), inner_scale);
combineTwoImages(srcImageRange(tmpx), srcImage(tmpx), combineTwoImages(srcImageRange(tmpx), srcImage(tmpx),
destImage(tmp), std::multiplies<TmpType>()); destImage(tmp), std::multiplies<TmpType>());
gaussianSmoothing(srcImageRange(tmp), gaussianSmoothing(srcImageRange(tmp),
destIter(dupperleftx, dax), outer_scale); destIter(dupperleftx, dax), outer_scale);
combineTwoImages(srcImageRange(tmpy), srcImage(tmpy), combineTwoImages(srcImageRange(tmpy), srcImage(tmpy),
destImage(tmp), std::multiplies<TmpType>()); destImage(tmp), std::multiplies<TmpType>());
gaussianSmoothing(srcImageRange(tmp), gaussianSmoothing(srcImageRange(tmp),
skipping to change at line 1228 skipping to change at line 1224
VigraFalseType /* isScalar */) VigraFalseType /* isScalar */)
{ {
int bands = src.size(supperleft); int bands = src.size(supperleft);
typedef VectorElementAccessor<SrcAccessor> SA; typedef VectorElementAccessor<SrcAccessor> SA;
structureTensor(supperleft, slowerright, SA(0, src), structureTensor(supperleft, slowerright, SA(0, src),
dupperleft, dest, dupperleft, dest,
inner_scale, outer_scale, inner_scale, outer_scale,
VigraTrueType() /* isScalar */); VigraTrueType() /* isScalar */);
BasicImage<typename DestAccessor::value_type> st(slowerright - supperle ft); BasicImage<typename DestAccessor::value_type> st(slowerright - supperle ft, SkipInitialization);
for(int k=1; k < bands; ++k) for(int k=1; k < bands; ++k)
{ {
structureTensor(supperleft, slowerright, SA(k, src), structureTensor(supperleft, slowerright, SA(k, src),
st.upperLeft(), st.accessor(), st.upperLeft(), st.accessor(),
inner_scale, outer_scale, inner_scale, outer_scale,
VigraTrueType() /* isScalar */); VigraTrueType() /* isScalar */);
combineTwoImages(srcImageRange(st), srcIter(dupperleft, dest), dest Iter(dupperleft, dest), combineTwoImages(srcImageRange(st), srcIter(dupperleft, dest), dest Iter(dupperleft, dest),
std::plus<typename DestAccessor::value_type>()); std::plus<typename DestAccessor::value_type>());
} }
} }
 End of changes. 18 change blocks. 
31 lines changed or deleted 27 lines changed or added


 copyimage.hxx   copyimage.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 81 skipping to change at line 79
copyLineIf(SrcIterator s, copyLineIf(SrcIterator s,
SrcIterator send, SrcAccessor src, SrcIterator send, SrcAccessor src,
MaskIterator m, MaskAccessor mask, MaskIterator m, MaskAccessor mask,
DestIterator d, DestAccessor dest) DestIterator d, DestAccessor dest)
{ {
for(; s != send; ++s, ++d, ++m) for(; s != send; ++s, ++d, ++m)
if(mask(m)) if(mask(m))
dest.set(src(s), d); dest.set(src(s), d);
} }
template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor>
void
swapLine(SrcIterator s,
SrcIterator send, SrcAccessor src,
DestIterator d, DestAccessor dest)
{
for(; s != send; ++s, ++d)
{
typename SrcAccessor::value_type t = src(s);
src.set(dest(d), s);
dest.set(t, d);
}
}
/********************************************************/ /********************************************************/
/* */ /* */
/* copyImage */ /* copyImage */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Copy source image into destination image. /** \brief Copy source image into destination image.
If necessary, type conversion takes place. If necessary, type conversion takes place.
The function uses accessors to access the pixel data. The function uses accessors to access the pixel data.
skipping to change at line 173 skipping to change at line 186
class DestImageIterator, class DestAccessor> class DestImageIterator, class DestAccessor>
inline inline
void void
copyImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, copyImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
pair<DestImageIterator, DestAccessor> dest) pair<DestImageIterator, DestAccessor> dest)
{ {
copyImage(src.first, src.second, src.third, copyImage(src.first, src.second, src.third,
dest.first, dest.second); dest.first, dest.second);
} }
template <class SrcImageIterator, class SrcAccessor,
class DestImageIterator, class DestAccessor>
void
swapImageData(SrcImageIterator src_upperleft,
SrcImageIterator src_lowerright, SrcAccessor sa,
DestImageIterator dest_upperleft, DestAccessor da)
{
int w = src_lowerright.x - src_upperleft.x;
for(; src_upperleft.y<src_lowerright.y; ++src_upperleft.y, ++dest_upper
left.y)
{
swapLine(src_upperleft.rowIterator(),
src_upperleft.rowIterator() + w, sa,
dest_upperleft.rowIterator(), da);
}
}
template <class SrcImageIterator, class SrcAccessor,
class DestImageIterator, class DestAccessor>
inline
void
swapImageData(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
pair<DestImageIterator, DestAccessor> dest)
{
swapImageData(src.first, src.second, src.third,
dest.first, dest.second);
}
/********************************************************/ /********************************************************/
/* */ /* */
/* copyImageIf */ /* copyImageIf */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Copy source ROI into destination image. /** \brief Copy source ROI into destination image.
Pixel values are copied whenever the return value of the mask's Pixel values are copied whenever the return value of the mask's
accessor is not zero. accessor is not zero.
 End of changes. 5 change blocks. 
3 lines changed or deleted 45 lines changed or added


 cornerdetection.hxx   cornerdetection.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2004 by Ullrich Koethe */ /* Copyright 1998-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 59 skipping to change at line 57
template <class SrcType> template <class SrcType>
struct CornerResponseFunctor struct CornerResponseFunctor
{ {
typedef typename NumericTraits<SrcType>::RealPromote argument_type; typedef typename NumericTraits<SrcType>::RealPromote argument_type;
typedef argument_type result_type; typedef argument_type result_type;
result_type operator()(argument_type a1, result_type operator()(argument_type a1,
argument_type a2, argument_type a3) const argument_type a2, argument_type a3) const
{ {
return (a1*a2 - a3*a3) - 0.04 * (a1 + a2) * (a1 + a2); return detail::RequiresExplicitCast<result_type>::cast((a1*a2 - a3*a3 ) - 0.04 * (a1 + a2) * (a1 + a2));
} }
}; };
template <class T> template <class T>
class FunctorTraits<CornerResponseFunctor<T> > class FunctorTraits<CornerResponseFunctor<T> >
: public FunctorTraitsBase<CornerResponseFunctor<T> > : public FunctorTraitsBase<CornerResponseFunctor<T> >
{ {
public: public:
typedef VigraTrueType isTernaryFunctor; typedef VigraTrueType isTernaryFunctor;
}; };
 End of changes. 4 change blocks. 
4 lines changed or deleted 2 lines changed or added


 diff2d.hxx   diff2d.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2003 by Hans Meine */ /* Copyright 1998-2003 by Hans Meine */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 1129 skipping to change at line 1127
/** Return whether this rectangle contains the given /** Return whether this rectangle contains the given
* one. <tt>r1.contains(r2)</tt> returns the same as * one. <tt>r1.contains(r2)</tt> returns the same as
* <tt>r1 == (r1|r2)</tt> (but is of course more * <tt>r1 == (r1|r2)</tt> (but is of course more
* efficient). That also means, a rectangle (even an empty one!) * efficient). That also means, a rectangle (even an empty one!)
* contains() any empty rectangle. * contains() any empty rectangle.
*/ */
bool contains(Rect2D const &r) const bool contains(Rect2D const &r) const
{ {
return r.isEmpty() || return r.isEmpty() ||
contains(r.upperLeft()) && contains(r.lowerRight()-Diff2D(1,1)) ; (contains(r.upperLeft()) && contains(r.lowerRight()-Diff2D(1,1) ));
} }
/** Return whether this rectangle overlaps with the given /** Return whether this rectangle overlaps with the given
* one. <tt>r1.intersects(r2)</tt> returns the same as * one. <tt>r1.intersects(r2)</tt> returns the same as
* <tt>!(r1&r2).isEmpty()</tt> (but is of course much more * <tt>!(r1&r2).isEmpty()</tt> (but is of course much more
* efficient). * efficient).
*/ */
bool intersects(Rect2D const &r) const bool intersects(Rect2D const &r) const
{ {
return ((r.upperLeft_.x < lowerRight_.x) && return ((r.upperLeft_.x < lowerRight_.x) &&
skipping to change at line 1271 skipping to change at line 1269
upperLeft_.x = r.upperLeft_.x; upperLeft_.x = r.upperLeft_.x;
if(upperLeft_.y < r.upperLeft_.y) if(upperLeft_.y < r.upperLeft_.y)
upperLeft_.y = r.upperLeft_.y; upperLeft_.y = r.upperLeft_.y;
if(r.lowerRight_.x < lowerRight_.x) if(r.lowerRight_.x < lowerRight_.x)
lowerRight_.x = r.lowerRight_.x; lowerRight_.x = r.lowerRight_.x;
if(r.lowerRight_.y < lowerRight_.y) if(r.lowerRight_.y < lowerRight_.y)
lowerRight_.y = r.lowerRight_.y; lowerRight_.y = r.lowerRight_.y;
return *this; return *this;
} }
/** Scale this rectangle by the given factor.
* To be specific, both upperLeft() and lowerRight() are
* multiplicated by `factor`.
*/
Rect2D & operator*=(int factor)
{
upperLeft_ *= factor;
lowerRight_ *= factor;
return *this;
}
/** Scale this rectangle by the given factor.
* To be specific, both upperLeft() and lowerRight() are
* multiplicated by `factor`.
*/
Rect2D & operator*=(double factor)
{
upperLeft_ *= factor;
lowerRight_ *= factor;
return *this;
}
/** Return rectangle scaled by the given factor.
* To be specific, both upperLeft() and lowerRight() are
* multiplicated by `factor`.
*/
Rect2D operator*(int factor) const
{
return Rect2D(*this)*=factor;
}
/** Return rectangle scaled by the given factor.
* To be specific, both upperLeft() and lowerRight() are
* multiplicated by `factor`.
*/
Rect2D operator*(double factor) const
{
return Rect2D(*this)*=factor;
}
/** Intersects this rectangle with the given one. The result /** Intersects this rectangle with the given one. The result
* is the maximal rectangle contained in both original ones. * is the maximal rectangle contained in both original ones.
* Intersecting with an empty rectangle will yield again an * Intersecting with an empty rectangle will yield again an
* empty rectangle. * empty rectangle.
*/ */
Rect2D operator&(Rect2D const &r) const Rect2D operator&(Rect2D const &r) const
{ {
Rect2D result(*this); Rect2D result(*this);
result &= r; result &= r;
return result; return result;
skipping to change at line 1340 skipping to change at line 1378
operator Diff2D() operator Diff2D()
{ return Diff2D(width, height); } { return Diff2D(width, height); }
int width; int width;
int height; int height;
}; };
//@} //@}
} // namespace vigra
namespace std {
/** /**
* Output a \ref vigra::Diff2D as a tuple. * Output a \ref vigra::Diff2D as a tuple.
* Example Diff2D(-12, 13) -> "(-12, 13)" * Example Diff2D(-12, 13) -> "(-12, 13)"
*/ */
inline inline
std::ostream & operator<<(std::ostream & o, vigra::Diff2D const & d) ostream & operator<<(ostream & o, vigra::Diff2D const & d)
{ {
o << '(' << d.x << ", " << d.y << ')'; o << '(' << d.x << ", " << d.y << ')';
return o; return o;
} }
/** /**
* Output a \ref vigra::Size2D. * Output a \ref vigra::Size2D.
* Example Size2D(100, 200) -> "(100x200)" * Example Size2D(100, 200) -> "(100x200)"
*/ */
inline inline
std::ostream &operator <<(std::ostream &s, vigra::Size2D const &d) ostream &operator <<(ostream &s, vigra::Size2D const &d)
{ {
s << '(' << d.x << 'x' << d.y << ')'; s << '(' << d.x << 'x' << d.y << ')';
return s; return s;
} }
/** /**
* Output a description of a \ref vigra::Rect2D. * Output a description of a \ref vigra::Rect2D.
* Example Rect2D(10, 10, 30, 20) -> "[(10, 10) to (30, 20) = (20x10)]" * Example Rect2D(10, 10, 30, 20) -> "[(10, 10) to (30, 20) = (20x10)]"
*/ */
inline inline
std::ostream &operator <<(std::ostream &s, vigra::Rect2D const &r) ostream &operator <<(ostream &s, vigra::Rect2D const &r)
{ {
s << "[" << r.upperLeft() << " to " << r.lowerRight() s << "[" << r.upperLeft() << " to " << r.lowerRight()
<< " = " << r.size() << "]"; << " = " << r.size() << "]";
return s; return s;
} }
} // namespace vigra } // namespace std
#endif // VIGRA_DIFF2D_HXX #endif // VIGRA_DIFF2D_HXX
 End of changes. 10 change blocks. 
8 lines changed or deleted 50 lines changed or added


 distancetransform.hxx   distancetransform.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 93 skipping to change at line 91
internalDistanceTransform(SrcImageIterator src_upperleft, internalDistanceTransform(SrcImageIterator src_upperleft,
SrcImageIterator src_lowerright, SrcAccessor sa, SrcImageIterator src_lowerright, SrcAccessor sa,
DestImageIterator dest_upperleft, DestAccessor da, DestImageIterator dest_upperleft, DestAccessor da,
ValueType background, NormFunctor norm) ValueType background, NormFunctor norm)
{ {
int w = src_lowerright.x - src_upperleft.x; int w = src_lowerright.x - src_upperleft.x;
int h = src_lowerright.y - src_upperleft.y; int h = src_lowerright.y - src_upperleft.y;
FImage xdist(w,h), ydist(w,h); FImage xdist(w,h), ydist(w,h);
xdist = w; // init x and xdist = (FImage::value_type)w; // init x and
ydist = h; // y distances with 'large' values ydist = (FImage::value_type)h; // y distances with 'large' values
SrcImageIterator sy = src_upperleft; SrcImageIterator sy = src_upperleft;
DestImageIterator ry = dest_upperleft; DestImageIterator ry = dest_upperleft;
FImage::Iterator xdy = xdist.upperLeft(); FImage::Iterator xdy = xdist.upperLeft();
FImage::Iterator ydy = ydist.upperLeft(); FImage::Iterator ydy = ydist.upperLeft();
SrcImageIterator sx = sy; SrcImageIterator sx = sy;
DestImageIterator rx = ry; DestImageIterator rx = ry;
FImage::Iterator xdx = xdy; FImage::Iterator xdx = xdy;
FImage::Iterator ydx = ydy; FImage::Iterator ydx = ydy;
skipping to change at line 134 skipping to change at line 132
++x, ++xdx.x, ++ydx.x, ++sx.x, ++rx.x) // first row left to right ++x, ++xdx.x, ++ydx.x, ++sx.x, ++rx.x) // first row left to right
{ {
if(sa(sx) != background) if(sa(sx) != background)
{ {
*xdx = 0.0; *xdx = 0.0;
*ydx = 0.0; *ydx = 0.0;
da.set(0.0, rx); da.set(0.0, rx);
} }
else else
{ {
*xdx = xdx[left] + 1.0; // propagate x and *xdx = xdx[left] + 1.0f; // propagate x and
*ydx = ydx[left]; // y components of distance from lef t pixel *ydx = ydx[left]; // y components of distance from lef t pixel
da.set(norm(*xdx, *ydx), rx); // calculate distance from x and y components da.set(norm(*xdx, *ydx), rx); // calculate distance from x and y components
} }
} }
for(x=w-2, xdx.x -= 2, ydx.x -= 2, sx.x -= 2, rx.x -= 2; for(x=w-2, xdx.x -= 2, ydx.x -= 2, sx.x -= 2, rx.x -= 2;
x>=0; x>=0;
--x, --xdx.x, --ydx.x, --sx.x, --rx.x) // first row right to left --x, --xdx.x, --ydx.x, --sx.x, --rx.x) // first row right to left
{ {
float d = norm(xdx[right] + 1.0, ydx[right]); float d = norm(xdx[right] + 1.0f, ydx[right]);
if(da(rx) < d) continue; if(da(rx) < d) continue;
*xdx = xdx[right] + 1.0; *xdx = xdx[right] + 1.0f;
*ydx = ydx[right]; *ydx = ydx[right];
da.set(d, rx); da.set(d, rx);
} }
for(y=1, ++xdy.y, ++ydy.y, ++sy.y, ++ry.y; for(y=1, ++xdy.y, ++ydy.y, ++sy.y, ++ry.y;
y<h; y<h;
++y, ++xdy.y, ++ydy.y, ++sy.y, ++ry.y) // top to bottom ++y, ++xdy.y, ++ydy.y, ++sy.y, ++ry.y) // top to bottom
{ {
sx = sy; sx = sy;
rx = ry; rx = ry;
xdx = xdy; xdx = xdy;
ydx = ydy; ydx = ydy;
if(sa(sx) != background) // first pixel of current row if(sa(sx) != background) // first pixel of current row
{ {
*xdx = 0.0; *xdx = 0.0f;
*ydx = 0.0; *ydx = 0.0f;
da.set(0.0, rx); da.set(0.0, rx);
} }
else else
{ {
*xdx = xdx[top]; *xdx = xdx[top];
*ydx = ydx[top] + 1.0; *ydx = ydx[top] + 1.0f;
da.set(norm(*xdx, *ydx), rx); da.set(norm(*xdx, *ydx), rx);
} }
for(x=1, ++xdx.x, ++ydx.x, ++sx.x, ++rx.x; for(x=1, ++xdx.x, ++ydx.x, ++sx.x, ++rx.x;
x<w; x<w;
++x, ++xdx.x, ++ydx.x, ++sx.x, ++rx.x) // current row left to right ++x, ++xdx.x, ++ydx.x, ++sx.x, ++rx.x) // current row left to right
{ {
if(sa(sx) != background) if(sa(sx) != background)
{ {
*xdx = 0.0; *xdx = 0.0f;
*ydx = 0.0; *ydx = 0.0f;
da.set(0.0, rx); da.set(0.0, rx);
} }
else else
{ {
float d1 = norm(xdx[left] + 1.0, ydx[left]); float d1 = norm(xdx[left] + 1.0f, ydx[left]);
float d2 = norm(xdx[top], ydx[top] + 1.0); float d2 = norm(xdx[top], ydx[top] + 1.0f);
if(d1 < d2) if(d1 < d2)
{ {
*xdx = xdx[left] + 1.0; *xdx = xdx[left] + 1.0f;
*ydx = ydx[left]; *ydx = ydx[left];
da.set(d1, rx); da.set(d1, rx);
} }
else else
{ {
*xdx = xdx[top]; *xdx = xdx[top];
*ydx = ydx[top] + 1.0; *ydx = ydx[top] + 1.0f;
da.set(d2, rx); da.set(d2, rx);
} }
} }
} }
for(x=w-2, xdx.x -= 2, ydx.x -= 2, sx.x -= 2, rx.x -= 2; for(x=w-2, xdx.x -= 2, ydx.x -= 2, sx.x -= 2, rx.x -= 2;
x>=0; x>=0;
--x, --xdx.x, --ydx.x, --sx.x, --rx.x) // current row right to left --x, --xdx.x, --ydx.x, --sx.x, --rx.x) // current row right to left
{ {
float d1 = norm(xdx[right] + 1.0, ydx[right]); float d1 = norm(xdx[right] + 1.0f, ydx[right]);
if(da(rx) < d1) continue; if(da(rx) < d1) continue;
*xdx = xdx[right] + 1.0; *xdx = xdx[right] + 1.0f;
*ydx = ydx[right]; *ydx = ydx[right];
da.set(d1, rx); da.set(d1, rx);
} }
} }
for(y=h-2, xdy.y -= 2, ydy.y -= 2, sy.y -= 2, ry.y -= 2; for(y=h-2, xdy.y -= 2, ydy.y -= 2, sy.y -= 2, ry.y -= 2;
y>=0; y>=0;
--y, --xdy.y, --ydy.y, --sy.y, --ry.y) // bottom to top --y, --xdy.y, --ydy.y, --sy.y, --ry.y) // bottom to top
{ {
sx = sy; sx = sy;
rx = ry; rx = ry;
xdx = xdy; xdx = xdy;
ydx = ydy; ydx = ydy;
float d = norm(xdx[bottom], ydx[bottom] + 1.0); float d = norm(xdx[bottom], ydx[bottom] + 1.0f);
if(d < da(rx)) // first pixel of current row if(d < da(rx)) // first pixel of current row
{ {
*xdx = xdx[bottom]; *xdx = xdx[bottom];
*ydx = ydx[bottom] + 1.0; *ydx = ydx[bottom] + 1.0f;
da.set(d, rx); da.set(d, rx);
} }
for(x=1, ++xdx.x, ++ydx.x, ++sx.x, ++rx.x; for(x=1, ++xdx.x, ++ydx.x, ++sx.x, ++rx.x;
x<w; x<w;
++x, ++xdx.x, ++ydx.x, ++sx.x, ++rx.x) // current row left to right ++x, ++xdx.x, ++ydx.x, ++sx.x, ++rx.x) // current row left to right
{ {
float d1 = norm(xdx[left] + 1.0, ydx[left]); float d1 = norm(xdx[left] + 1.0f, ydx[left]);
float d2 = norm(xdx[bottom], ydx[bottom] + 1.0); float d2 = norm(xdx[bottom], ydx[bottom] + 1.0f);
if(d1 < d2) if(d1 < d2)
{ {
if(da(rx) < d1) continue; if(da(rx) < d1) continue;
*xdx = xdx[left] + 1.0; *xdx = xdx[left] + 1.0f;
*ydx = ydx[left]; *ydx = ydx[left];
da.set(d1, rx); da.set(d1, rx);
} }
else else
{ {
if(da(rx) < d2) continue; if(da(rx) < d2) continue;
*xdx = xdx[bottom]; *xdx = xdx[bottom];
*ydx = ydx[bottom] + 1.0; *ydx = ydx[bottom] + 1.0f;
da.set(d2, rx); da.set(d2, rx);
} }
} }
for(x=w-2, xdx.x -= 2, ydx.x -= 2, sx.x -= 2, rx.x -= 2; for(x=w-2, xdx.x -= 2, ydx.x -= 2, sx.x -= 2, rx.x -= 2;
x>=0; x>=0;
--x, --xdx.x, --ydx.x, --sx.x, --rx.x) // current row right to left --x, --xdx.x, --ydx.x, --sx.x, --rx.x) // current row right to left
{ {
float d1 = norm(xdx[right] + 1.0, ydx[right]); float d1 = norm(xdx[right] + 1.0f, ydx[right]);
if(da(rx) < d1) continue; if(da(rx) < d1) continue;
*xdx = xdx[right] + 1.0; *xdx = xdx[right] + 1.0f;
*ydx = ydx[right]; *ydx = ydx[right];
da.set(d1, rx); da.set(d1, rx);
} }
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* distanceTransform */ /* distanceTransform */
/* */ /* */
 End of changes. 22 change blocks. 
27 lines changed or deleted 25 lines changed or added


 edgedetection.hxx   edgedetection.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 50 skipping to change at line 48
#include <vector> #include <vector>
#include <queue> #include <queue>
#include <cmath> // sqrt(), abs() #include <cmath> // sqrt(), abs()
#include "utilities.hxx" #include "utilities.hxx"
#include "numerictraits.hxx" #include "numerictraits.hxx"
#include "stdimage.hxx" #include "stdimage.hxx"
#include "stdimagefunctions.hxx" #include "stdimagefunctions.hxx"
#include "recursiveconvolution.hxx" #include "recursiveconvolution.hxx"
#include "separableconvolution.hxx" #include "separableconvolution.hxx"
#include "convolution.hxx"
#include "labelimage.hxx" #include "labelimage.hxx"
#include "mathutil.hxx" #include "mathutil.hxx"
#include "pixelneighborhood.hxx" #include "pixelneighborhood.hxx"
#include "linear_solve.hxx" #include "linear_solve.hxx"
#include "functorexpression.hxx"
namespace vigra { namespace vigra {
/** \addtogroup EdgeDetection Edge Detection /** \addtogroup EdgeDetection Edge Detection
Edge detectors based on first and second derivatives, Edge detectors based on first and second derivatives,
and related post-processing. and related post-processing.
*/ */
//@{ //@{
/********************************************************/ /********************************************************/
skipping to change at line 220 skipping to change at line 220
recursiveSmoothX(srcImageRange(tmp), destImage(smooth), scale); recursiveSmoothX(srcImageRange(tmp), destImage(smooth), scale);
recursiveSmoothY(srcImageRange(smooth), destImage(smooth), scale); recursiveSmoothY(srcImageRange(smooth), destImage(smooth), scale);
typename TMPIMG::Iterator iy = smooth.upperLeft(); typename TMPIMG::Iterator iy = smooth.upperLeft();
typename TMPIMG::Iterator ty = tmp.upperLeft(); typename TMPIMG::Iterator ty = tmp.upperLeft();
DestIterator dy = dul; DestIterator dy = dul;
static const Diff2D right(1, 0); static const Diff2D right(1, 0);
static const Diff2D bottom(0, 1); static const Diff2D bottom(0, 1);
TMPTYPE thresh = (gradient_threshold * gradient_threshold) * TMPTYPE thresh = detail::RequiresExplicitCast<TMPTYPE>::cast((gradient_
NumericTraits<TMPTYPE>::one(); threshold * gradient_threshold) *
NumericTraits<TMPTYPE>::one());
TMPTYPE zero = NumericTraits<TMPTYPE>::zero(); TMPTYPE zero = NumericTraits<TMPTYPE>::zero();
for(y=0; y<h-1; ++y, ++iy.y, ++ty.y, ++dy.y) for(y=0; y<h-1; ++y, ++iy.y, ++ty.y, ++dy.y)
{ {
typename TMPIMG::Iterator ix = iy; typename TMPIMG::Iterator ix = iy;
typename TMPIMG::Iterator tx = ty; typename TMPIMG::Iterator tx = ty;
DestIterator dx = dy; DestIterator dx = dy;
for(x=0; x<w-1; ++x, ++ix.x, ++tx.x, ++dx.x) for(x=0; x<w-1; ++x, ++ix.x, ++tx.x, ++dx.x)
{ {
skipping to change at line 509 skipping to change at line 509
recursiveSmoothX(srcIterRange(sul, slr, sa), destImage(tmp), scale / 2. 0); recursiveSmoothX(srcIterRange(sul, slr, sa), destImage(tmp), scale / 2. 0);
recursiveSmoothY(srcImageRange(tmp), destImage(tmp), scale / 2.0); recursiveSmoothY(srcImageRange(tmp), destImage(tmp), scale / 2.0);
recursiveSmoothX(srcImageRange(tmp), destImage(smooth), scale); recursiveSmoothX(srcImageRange(tmp), destImage(smooth), scale);
recursiveSmoothY(srcImageRange(smooth), destImage(smooth), scale); recursiveSmoothY(srcImageRange(smooth), destImage(smooth), scale);
typename TMPIMG::Iterator iy = smooth.upperLeft(); typename TMPIMG::Iterator iy = smooth.upperLeft();
typename TMPIMG::Iterator ty = tmp.upperLeft(); typename TMPIMG::Iterator ty = tmp.upperLeft();
DestIterator dy = dul; DestIterator dy = dul;
TMPTYPE thresh = (gradient_threshold * gradient_threshold) * TMPTYPE thresh = detail::RequiresExplicitCast<TMPTYPE>::cast((gradient_
NumericTraits<TMPTYPE>::one(); threshold * gradient_threshold) *
NumericTraits<TMPTYPE>::one());
// find zero crossings above threshold // find zero crossings above threshold
for(y=0; y<h-1; ++y, ++iy.y, ++ty.y, dy.y+=2) for(y=0; y<h-1; ++y, ++iy.y, ++ty.y, dy.y+=2)
{ {
typename TMPIMG::Iterator ix = iy; typename TMPIMG::Iterator ix = iy;
typename TMPIMG::Iterator tx = ty; typename TMPIMG::Iterator tx = ty;
DestIterator dx = dy; DestIterator dx = dy;
for(int x=0; x<w-1; ++x, ++ix.x, ++tx.x, dx.x+=2) for(int x=0; x<w-1; ++x, ++ix.x, ++tx.x, dx.x+=2)
{ {
skipping to change at line 1146 skipping to change at line 1146
{ {
beautifyCrackEdgeImage(src.first, src.second, src.third, beautifyCrackEdgeImage(src.first, src.second, src.third,
edge_marker, background_marker); edge_marker, background_marker);
} }
/** Helper class that stores edgel attributes. /** Helper class that stores edgel attributes.
*/ */
class Edgel class Edgel
{ {
public: public:
/** The type of an Edgel's members.
*/
typedef float value_type;
/** The edgel's sub-pixel x coordinate. /** The edgel's sub-pixel x coordinate.
*/ */
float x; value_type x;
/** The edgel's sub-pixel y coordinate. /** The edgel's sub-pixel y coordinate.
*/ */
float y; value_type y;
/** The edgel's strength (magnitude of the gradient vector). /** The edgel's strength (magnitude of the gradient vector).
*/ */
float strength; value_type strength;
/** /**
The edgel's orientation. This is the angle The edgel's orientation. This is the clockwise angle in radians
between the x-axis and the edge, so that the bright side of the between the x-axis and the edge, so that the bright side of the
edge is on the right. The angle is measured edge is on the left when one looks along the orientation vector.
counter-clockwise in radians like this: The angle is measured clockwise because the y-axis increases
downwards (left-handed coordinate system):
\code \code
edgel axis edgel axis
\ (bright side) \
(dark \ (dark \ (bright side)
side) \ /__ side) \
\\ \ orientation angle \
\ |
+------------> x-axis +------------> x-axis
| |\ |
| | \ /_/ orientation angle
| | \\
| \
| |
y-axis V y-axis V
\endcode \endcode
So, for example a vertical edge with its dark side on the left So, for example a vertical edge with its dark side on the left
has orientation PI/2, and a horizontal edge with dark side on top has orientation PI/2, and a horizontal edge with dark side on top
has orientation 0. Obviously, the edge's orientation changes has orientation PI. Obviously, the edge's orientation changes
by PI if the contrast is reversed. by PI if the contrast is reversed.
Note that this convention changed as of VIGRA version 1.7.0.
*/ */
float orientation; value_type orientation;
Edgel() Edgel()
: x(0.0f), y(0.0f), strength(0.0f), orientation(0.0f) : x(0.0), y(0.0), strength(0.0), orientation(0.0)
{} {}
Edgel(float ix, float iy, float is, float io) Edgel(value_type ix, value_type iy, value_type is, value_type io)
: x(ix), y(iy), strength(is), orientation(io) : x(ix), y(iy), strength(is), orientation(io)
{} {}
}; };
template <class Image1, class Image2, class BackInsertable> template <class SrcIterator, class SrcAccessor,
void internalCannyFindEdgels(Image1 const & gx, class MagnitudeImage, class BackInsertable>
Image1 const & gy, void internalCannyFindEdgels(SrcIterator ul, SrcAccessor grad,
Image2 const & magnitude, MagnitudeImage const & magnitude,
BackInsertable & edgels) BackInsertable & edgels)
{ {
typedef typename Image1::value_type PixelType; typedef typename SrcAccessor::value_type PixelType;
typedef typename PixelType::value_type ValueType;
double t = 0.5 / VIGRA_CSTD::sin(M_PI/8.0); double t = 0.5 / VIGRA_CSTD::sin(M_PI/8.0);
for(int y=1; y<gx.height()-1; ++y) ul += Diff2D(1,1);
for(int y=1; y<magnitude.height()-1; ++y, ++ul.y)
{ {
for(int x=1; x<gx.width()-1; ++x) SrcIterator ix = ul;
for(int x=1; x<magnitude.width()-1; ++x, ++ix.x)
{ {
PixelType gradx = gx(x,y);
PixelType grady = gy(x,y);
double mag = magnitude(x, y); double mag = magnitude(x, y);
if(mag == 0.0) if(mag == 0.0)
continue; continue;
ValueType gradx = grad.getComponent(ix, 0);
ValueType grady = grad.getComponent(ix, 1);
int dx = (int)VIGRA_CSTD::floor(gradx*t/mag + 0.5); int dx = (int)VIGRA_CSTD::floor(gradx*t/mag + 0.5);
int dy = (int)VIGRA_CSTD::floor(grady*t/mag + 0.5); int dy = (int)VIGRA_CSTD::floor(grady*t/mag + 0.5);
int x1 = x - dx, int x1 = x - dx,
x2 = x + dx, x2 = x + dx,
y1 = y - dy, y1 = y - dy,
y2 = y + dy; y2 = y + dy;
PixelType m1 = magnitude(x1, y1); double m1 = magnitude(x1, y1);
PixelType m3 = magnitude(x2, y2); double m3 = magnitude(x2, y2);
if(m1 < mag && m3 <= mag) if(m1 < mag && m3 <= mag)
{ {
Edgel edgel; Edgel edgel;
// local maximum => quadratic interpolation of sub-pixel lo cation // local maximum => quadratic interpolation of sub-pixel lo cation
PixelType del = (m1 - m3) / 2.0 / (m1 + m3 - 2.0*mag); double del = 0.5 * (m1 - m3) / (m1 + m3 - 2.0*mag);
edgel.x = x + dx*del; edgel.x = Edgel::value_type(x + dx*del);
edgel.y = y + dy*del; edgel.y = Edgel::value_type(y + dy*del);
edgel.strength = mag; edgel.strength = Edgel::value_type(mag);
double orientation = VIGRA_CSTD::atan2(-grady, gradx) - M_P double orientation = VIGRA_CSTD::atan2(grady, gradx) + 0.5*
I * 1.5; M_PI;
if(orientation < 0.0) if(orientation < 0.0)
orientation += 2.0*M_PI; orientation += 2.0*M_PI;
edgel.orientation = orientation; edgel.orientation = Edgel::value_type(orientation);
edgels.push_back(edgel); edgels.push_back(edgel);
} }
} }
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* cannyEdgelList */ /* cannyEdgelList */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Simple implementation of Canny's edge detector. /** \brief Simple implementation of Canny's edge detector.
This operator first calculates the gradient vector for each The function can be called in two modes: If you pass a 'scale', it is a
pixel of the image using first derivatives of a Gaussian at the ssumed that the
given scale. Then a very simple non-maxima supression is performed: original image is scalar, and the Gaussian gradient is internally compu
ted at the
given 'scale'. If the function is called without scale parameter, it is
assumed that
the given image already contains the gradient (i.e. its value_type must
be
a vector of length 2).
On the basis of the gradient image, a simple non-maxima supression is p
erformed:
for each 3x3 neighborhood, it is determined whether the center pixel ha s for each 3x3 neighborhood, it is determined whether the center pixel ha s
larger gradient magnitude than its two neighbors in gradient direction larger gradient magnitude than its two neighbors in gradient direction
(where the direction is rounded into octands). If this is the case, (where the direction is rounded into octands). If this is the case,
a new \ref Edgel is appended to the given vector of <TT>edgels</TT>. Th e subpixel a new \ref Edgel is appended to the given vector of <TT>edgels</TT>. Th e subpixel
edgel position is determined by fitting a parabola edgel position is determined by fitting a parabola to the three gradien
to the three gradient magnitude values t
mentioned above. The sub-pixel location of the parabola's tip magnitude values mentioned above. The sub-pixel location of the parabol
a's tip
and the gradient magnitude and direction (from the pixel center) and the gradient magnitude and direction (from the pixel center)
are written in the newly created edgel. are written in the newly created edgel.
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
// compute edgels from a gradient image
template <class SrcIterator, class SrcAccessor, class BackInsertabl e> template <class SrcIterator, class SrcAccessor, class BackInsertabl e>
void cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src void
, cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src,
BackInsertable & edgels, double scale); BackInsertable & edgels);
// compute edgels from a scaler image (determine gradient internall
y at 'scale')
template <class SrcIterator, class SrcAccessor, class BackInsertabl
e>
void
cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src,
BackInsertable & edgels, double scale);
} }
\endcode \endcode
use argument objects in conjunction with \ref ArgumentObjectFactories : use argument objects in conjunction with \ref ArgumentObjectFactories :
\code \code
namespace vigra { namespace vigra {
// compute edgels from a gradient image
template <class SrcIterator, class SrcAccessor, class BackInsertabl
e>
void
cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src,
BackInsertable & edgels);
// compute edgels from a scaler image (determine gradient internall
y at 'scale')
template <class SrcIterator, class SrcAccessor, class BackInsertabl e> template <class SrcIterator, class SrcAccessor, class BackInsertabl e>
void void
cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src, cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src,
BackInsertable & edgels, double scale); BackInsertable & edgels, double scale);
} }
\endcode \endcode
<b> Usage:</b> <b> Usage:</b>
<b>\#include</b> \<<a href="edgedetection_8hxx-source.html">vigra/edged etection.hxx</a>\><br> <b>\#include</b> \<<a href="edgedetection_8hxx-source.html">vigra/edged etection.hxx</a>\><br>
skipping to change at line 1327 skipping to change at line 1357
<b> Preconditions:</b> <b> Preconditions:</b>
\code \code
scale > 0 scale > 0
\endcode \endcode
*/ */
doxygen_overloaded_function(template <...> void cannyEdgelList) doxygen_overloaded_function(template <...> void cannyEdgelList)
template <class SrcIterator, class SrcAccessor, class BackInsertable> template <class SrcIterator, class SrcAccessor, class BackInsertable>
void cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src, void
BackInsertable & edgels, double scale) cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src,
BackInsertable & edgels, double scale)
{ {
int w = lr.x - ul.x; typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP
int h = lr.y - ul.y; romote TmpType;
BasicImage<TinyVector<TmpType, 2> > grad(lr-ul);
// calculate image gradients gaussianGradient(srcIterRange(ul, lr, src), destImage(grad), scale);
typedef typename
NumericTraits<typename SrcAccessor::value_type>::RealPromote
TmpType;
BasicImage<TmpType> tmp(w,h), dx(w,h), dy(w,h);
Kernel1D<double> smooth, grad;
smooth.initGaussian(scale); cannyEdgelList(srcImageRange(grad), edgels);
grad.initGaussianDerivative(scale, 1); }
separableConvolveX(srcIterRange(ul, lr, src), destImage(tmp), kernel1d( template <class SrcIterator, class SrcAccessor, class BackInsertable>
grad)); inline void
separableConvolveY(srcImageRange(tmp), destImage(dx), kernel1d(smooth)) cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src,
; BackInsertable & edgels, double scale)
{
cannyEdgelList(src.first, src.second, src.third, edgels, scale);
}
separableConvolveY(srcIterRange(ul, lr, src), destImage(tmp), kernel1d( template <class SrcIterator, class SrcAccessor, class BackInsertable>
grad)); void
separableConvolveX(srcImageRange(tmp), destImage(dy), kernel1d(smooth)) cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src,
; BackInsertable & edgels)
{
using namespace functor;
combineTwoImages(srcImageRange(dx), srcImage(dy), destImage(tmp), typedef typename SrcAccessor::value_type SrcType;
MagnitudeFunctor<TmpType>()); typedef typename NumericTraits<typename SrcType::value_type>::RealPromo
te TmpType;
BasicImage<TmpType> magnitude(lr-ul);
transformImage(srcIterRange(ul, lr, src), destImage(magnitude), norm(Ar
g1()));
// find edgels // find edgels
internalCannyFindEdgels(dx, dy, tmp, edgels); internalCannyFindEdgels(ul, src, magnitude, edgels);
} }
template <class SrcIterator, class SrcAccessor, class BackInsertable> template <class SrcIterator, class SrcAccessor, class BackInsertable>
inline void inline void
cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src, cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src,
BackInsertable & edgels, double scale) BackInsertable & edgels)
{ {
cannyEdgelList(src.first, src.second, src.third, edgels, scale); cannyEdgelList(src.first, src.second, src.third, edgels);
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* cannyEdgeImage */ /* cannyEdgeImage */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Detect and mark edges in an edge image using Canny's algorithm. /** \brief Detect and mark edges in an edge image using Canny's algorithm.
skipping to change at line 1458 skipping to change at line 1492
class GradValue, class DestValue> class GradValue, class DestValue>
void cannyEdgeImage( void cannyEdgeImage(
SrcIterator sul, SrcIterator slr, SrcAccessor sa, SrcIterator sul, SrcIterator slr, SrcAccessor sa,
DestIterator dul, DestAccessor da, DestIterator dul, DestAccessor da,
double scale, GradValue gradient_threshold, DestValue edge_marke r) double scale, GradValue gradient_threshold, DestValue edge_marke r)
{ {
std::vector<Edgel> edgels; std::vector<Edgel> edgels;
cannyEdgelList(sul, slr, sa, edgels, scale); cannyEdgelList(sul, slr, sa, edgels, scale);
int w = slr.x - sul.x;
int h = slr.y - sul.y;
for(unsigned int i=0; i<edgels.size(); ++i) for(unsigned int i=0; i<edgels.size(); ++i)
{ {
if(gradient_threshold < edgels[i].strength) if(gradient_threshold < edgels[i].strength)
{ {
Diff2D pix((int)(edgels[i].x + 0.5), (int)(edgels[i].y + 0.5)); Diff2D pix((int)(edgels[i].x + 0.5), (int)(edgels[i].y + 0.5));
if(pix.x < 0 || pix.x >= w || pix.y < 0 || pix.y >= h)
continue;
da.set(edge_marker, dul, pix); da.set(edge_marker, dul, pix);
} }
} }
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class GradValue, class DestValue> class GradValue, class DestValue>
inline void cannyEdgeImage( inline void cannyEdgeImage(
triple<SrcIterator, SrcIterator, SrcAccessor> src, triple<SrcIterator, SrcIterator, SrcAccessor> src,
skipping to change at line 1966 skipping to change at line 2006
pair<DestIterator, DestAccessor> dest, pair<DestIterator, DestAccessor> dest,
double scale, GradValue gradient_threshold, DestValue edge_marke r) double scale, GradValue gradient_threshold, DestValue edge_marke r)
{ {
cannyEdgeImageWithThinning(src.first, src.second, src.third, cannyEdgeImageWithThinning(src.first, src.second, src.third,
dest.first, dest.second, dest.first, dest.second,
scale, gradient_threshold, edge_marker, true ); scale, gradient_threshold, edge_marker, true );
} }
/********************************************************/ /********************************************************/
template <class Image1, class Image2, class BackInsertable> template <class SrcIterator, class SrcAccessor,
void internalCannyFindEdgels3x3(Image1 const & grad, class MaskImage, class BackInsertable>
Image2 const & mask, void internalCannyFindEdgels3x3(SrcIterator ul, SrcAccessor grad,
MaskImage const & mask,
BackInsertable & edgels) BackInsertable & edgels)
{ {
typedef typename Image1::value_type PixelType; typedef typename SrcAccessor::value_type PixelType;
typedef typename PixelType::value_type ValueType; typedef typename PixelType::value_type ValueType;
for(int y=1; y<grad.height()-1; ++y) ul += Diff2D(1,1);
for(int y=1; y<mask.height()-1; ++y, ++ul.y)
{ {
for(int x=1; x<grad.width()-1; ++x) SrcIterator ix = ul;
for(int x=1; x<mask.width()-1; ++x, ++ix.x)
{ {
if(!mask(x,y)) if(!mask(x,y))
continue; continue;
ValueType gradx = grad(x,y)[0]; ValueType gradx = grad.getComponent(ix, 0);
ValueType grady = grad(x,y)[1]; ValueType grady = grad.getComponent(ix, 1);
double mag = hypot(gradx, grady); double mag = hypot(gradx, grady);
if(mag == 0.0) if(mag == 0.0)
continue; continue;
double c = gradx / mag, double c = gradx / mag,
s = grady / mag; s = grady / mag;
Matrix<double> ml(3,3), mr(3,1), l(3,1), r(3,1); Matrix<double> ml(3,3), mr(3,1), l(3,1), r(3,1);
l(0,0) = 1.0; l(0,0) = 1.0;
for(int yy = -1; yy <= 1; ++yy) for(int yy = -1; yy <= 1; ++yy)
{ {
for(int xx = -1; xx <= 1; ++xx) for(int xx = -1; xx <= 1; ++xx)
{ {
double u = c*xx + s*yy; double u = c*xx + s*yy;
double v = norm(grad(x+xx, y+yy)); double v = norm(grad(ix, Diff2D(xx, yy)));
l(1,0) = u; l(1,0) = u;
l(2,0) = u*u; l(2,0) = u*u;
ml += outer(l); ml += outer(l);
mr += v*l; mr += v*l;
} }
} }
linearSolve(ml, mr, r); linearSolve(ml, mr, r);
Edgel edgel; Edgel edgel;
// local maximum => quadratic interpolation of sub-pixel locati on // local maximum => quadratic interpolation of sub-pixel locati on
double del = -r(1,0) / 2.0 / r(2,0); double del = -r(1,0) / 2.0 / r(2,0);
if(std::fabs(del) > 1.5) // don't move by more than about a pi xel diameter if(std::fabs(del) > 1.5) // don't move by more than about a pi xel diameter
del = 0.0; del = 0.0;
edgel.x = x + c*del; edgel.x = Edgel::value_type(x + c*del);
edgel.y = y + s*del; edgel.y = Edgel::value_type(y + s*del);
edgel.strength = mag; edgel.strength = Edgel::value_type(mag);
double orientation = VIGRA_CSTD::atan2(-grady, gradx) - M_PI * double orientation = VIGRA_CSTD::atan2(grady, gradx) + 0.5*M_PI
1.5; ;
if(orientation < 0.0) if(orientation < 0.0)
orientation += 2.0*M_PI; orientation += 2.0*M_PI;
edgel.orientation = orientation; edgel.orientation = Edgel::value_type(orientation);
edgels.push_back(edgel); edgels.push_back(edgel);
} }
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* cannyEdgelList3x3 */ /* cannyEdgelList3x3 */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Improved implementation of Canny's edge detector. /** \brief Improved implementation of Canny's edge detector.
This operator first computes pixels which are crossed by the edge using This operator first computes pixels which are crossed by the edge using
cannyEdgeImageWithThinning(). The gradient magnitude in the 3x3 neighbo rhood of these cannyEdgeImageWithThinning(). The gradient magnitudes in the 3x3 neighb orhood of these
pixels are then projected onto the normal of the edge (as determined pixels are then projected onto the normal of the edge (as determined
by the gradient direction). The edgel's subpixel location is found by f itting a by the gradient direction). The edgel's subpixel location is found by f itting a
parabola through the 9 gradient values and determining the parabola's t ip. parabola through the 9 gradient values and determining the parabola's t ip.
A new \ref Edgel is appended to the given vector of <TT>edgels</TT>. Si nce the parabola A new \ref Edgel is appended to the given vector of <TT>edgels</TT>. Si nce the parabola
is fitted to 9 points rather than 3 points as in cannyEdgelList(), the accuracy is higher. is fitted to 9 points rather than 3 points as in cannyEdgelList(), the accuracy is higher.
The function can be called in two modes: If you pass a 'scale', it is a
ssumed that the
original image is scalar, and the Gaussian gradient is internally compu
ted at the
given 'scale'. If the function is called without scale parameter, it is
assumed that
the given image already contains the gradient (i.e. its value_type must
be
a vector of length 2).
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
// compute edgels from a gradient image
template <class SrcIterator, class SrcAccessor, class BackInsertabl
e>
void cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor
src,
BackInsertable & edgels);
// compute edgels from a scaler image (determine gradient internall
y at 'scale')
template <class SrcIterator, class SrcAccessor, class BackInsertabl e> template <class SrcIterator, class SrcAccessor, class BackInsertabl e>
void cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor src, void cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor src,
BackInsertable & edgels, double scale); BackInsertable & edgels, double scale);
} }
\endcode \endcode
use argument objects in conjunction with \ref ArgumentObjectFactories : use argument objects in conjunction with \ref ArgumentObjectFactories :
\code \code
namespace vigra { namespace vigra {
// compute edgels from a gradient image
template <class SrcIterator, class SrcAccessor, class BackInsertabl
e>
void
cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src
,
BackInsertable & edgels);
// compute edgels from a scaler image (determine gradient internall
y at 'scale')
template <class SrcIterator, class SrcAccessor, class BackInsertabl e> template <class SrcIterator, class SrcAccessor, class BackInsertabl e>
void void
cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src , cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src ,
BackInsertable & edgels, double scale); BackInsertable & edgels, double scale);
} }
\endcode \endcode
<b> Usage:</b> <b> Usage:</b>
<b>\#include</b> \<<a href="edgedetection_8hxx-source.html">vigra/edged etection.hxx</a>\><br> <b>\#include</b> \<<a href="edgedetection_8hxx-source.html">vigra/edged etection.hxx</a>\><br>
skipping to change at line 2101 skipping to change at line 2163
<b> Preconditions:</b> <b> Preconditions:</b>
\code \code
scale > 0 scale > 0
\endcode \endcode
*/ */
doxygen_overloaded_function(template <...> void cannyEdgelList3x3) doxygen_overloaded_function(template <...> void cannyEdgelList3x3)
template <class SrcIterator, class SrcAccessor, class BackInsertable> template <class SrcIterator, class SrcAccessor, class BackInsertable>
void cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor src, void
BackInsertable & edgels, double scale) cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor src,
BackInsertable & edgels, double scale)
{ {
int w = lr.x - ul.x;
int h = lr.y - ul.y;
typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP romote TmpType; typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP romote TmpType;
BasicImage<TinyVector<TmpType, 2> > grad(lr-ul); BasicImage<TinyVector<TmpType, 2> > grad(lr-ul);
gaussianGradient(srcIterRange(ul, lr, src), destImage(grad), scale); gaussianGradient(srcIterRange(ul, lr, src), destImage(grad), scale);
cannyEdgelList3x3(srcImageRange(grad), edgels);
}
template <class SrcIterator, class SrcAccessor, class BackInsertable>
inline void
cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src,
BackInsertable & edgels, double scale)
{
cannyEdgelList3x3(src.first, src.second, src.third, edgels, scale);
}
template <class SrcIterator, class SrcAccessor, class BackInsertable>
void
cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor src,
BackInsertable & edgels)
{
UInt8Image edges(lr-ul); UInt8Image edges(lr-ul);
cannyEdgeImageFromGradWithThinning(srcImageRange(grad), destImage(edges ), cannyEdgeImageFromGradWithThinning(srcIterRange(ul, lr, src), destImage (edges),
0.0, 1, false); 0.0, 1, false);
// find edgels // find edgels
internalCannyFindEdgels3x3(grad, edges, edgels); internalCannyFindEdgels3x3(ul, src, edges, edgels);
} }
template <class SrcIterator, class SrcAccessor, class BackInsertable> template <class SrcIterator, class SrcAccessor, class BackInsertable>
inline void inline void
cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src, cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src,
BackInsertable & edgels, double scale) BackInsertable & edgels)
{ {
cannyEdgelList3x3(src.first, src.second, src.third, edgels, scale); cannyEdgelList3x3(src.first, src.second, src.third, edgels);
} }
//@} //@}
/** \page CrackEdgeImage Crack Edge Image /** \page CrackEdgeImage Crack Edge Image
Crack edges are marked <i>between</i> the pixels of an image. Crack edges are marked <i>between</i> the pixels of an image.
A Crack Edge Image is an image that represents these edges. In order A Crack Edge Image is an image that represents these edges. In order
to accomodate the cracks, the Crack Edge Image must be twice as large to accomodate the cracks, the Crack Edge Image must be twice as large
as the original image (precisely (2*w - 1) by (2*h - 1)). A Crack Edge Imag e as the original image (precisely (2*w - 1) by (2*h - 1)). A Crack Edge Imag e
 End of changes. 64 change blocks. 
105 lines changed or deleted 202 lines changed or added


 eigensystem.hxx   eigensystem.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2004 by Ullrich Koethe */ /* Copyright 2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 62 skipping to change at line 60
namespace detail namespace detail
{ {
// code adapted from JAMA // code adapted from JAMA
// a and b will be overwritten // a and b will be overwritten
template <class T, class C1, class C2> template <class T, class C1, class C2>
void void
housholderTridiagonalization(MultiArrayView<2, T, C1> &a, MultiArrayView<2, T, C2> &b) housholderTridiagonalization(MultiArrayView<2, T, C1> &a, MultiArrayView<2, T, C2> &b)
{ {
const unsigned int n = rowCount(a); const MultiArrayIndex n = rowCount(a);
vigra_precondition(n == columnCount(a), vigra_precondition(n == columnCount(a),
"housholderTridiagonalization(): matrix must be square."); "housholderTridiagonalization(): matrix must be square.");
vigra_precondition(n == rowCount(b) && 2 <= columnCount(b), vigra_precondition(n == rowCount(b) && 2 <= columnCount(b),
"housholderTridiagonalization(): matrix size mismatch."); "housholderTridiagonalization(): matrix size mismatch.");
MultiArrayView<1, T, C2> d = b.bindOuter(0); MultiArrayView<1, T, C2> d = b.bindOuter(0);
MultiArrayView<1, T, C2> e = b.bindOuter(1); MultiArrayView<1, T, C2> e = b.bindOuter(1);
for(unsigned int j = 0; j < n; ++j) for(MultiArrayIndex j = 0; j < n; ++j)
{ {
d(j) = a(n-1, j); d(j) = a(n-1, j);
} }
// Householder reduction to tridiagonalMatrix form. // Householder reduction to tridiagonalMatrix form.
for(int i = n-1; i > 0; --i) for(int i = n-1; i > 0; --i)
{ {
// Scale to avoid under/overflow. // Scale to avoid under/overflow.
skipping to change at line 206 skipping to change at line 204
a(n-1, n-1) = 1.0; a(n-1, n-1) = 1.0;
e(0) = 0.0; e(0) = 0.0;
} }
// code adapted from JAMA // code adapted from JAMA
// de and z will be overwritten // de and z will be overwritten
template <class T, class C1, class C2> template <class T, class C1, class C2>
bool bool
tridiagonalMatrixEigensystem(MultiArrayView<2, T, C1> &de, MultiArrayView<2 , T, C2> &z) tridiagonalMatrixEigensystem(MultiArrayView<2, T, C1> &de, MultiArrayView<2 , T, C2> &z)
{ {
const unsigned int n = rowCount(z); MultiArrayIndex n = rowCount(z);
vigra_precondition(n == columnCount(z), vigra_precondition(n == columnCount(z),
"tridiagonalMatrixEigensystem(): matrix must be square."); "tridiagonalMatrixEigensystem(): matrix must be square.");
vigra_precondition(n == rowCount(de) && 2 <= columnCount(de), vigra_precondition(n == rowCount(de) && 2 <= columnCount(de),
"tridiagonalMatrixEigensystem(): matrix size mismatch."); "tridiagonalMatrixEigensystem(): matrix size mismatch.");
MultiArrayView<1, T, C2> d = de.bindOuter(0); MultiArrayView<1, T, C2> d = de.bindOuter(0);
MultiArrayView<1, T, C2> e = de.bindOuter(1); MultiArrayView<1, T, C2> e = de.bindOuter(1);
for(unsigned int i = 1; i < n; i++) { for(MultiArrayIndex i = 1; i < n; i++) {
e(i-1) = e(i); e(i-1) = e(i);
} }
e(n-1) = 0.0; e(n-1) = 0.0;
T f = 0.0; T f = 0.0;
T tst1 = 0.0; T tst1 = 0.0;
T eps = VIGRA_CSTD::pow(2.0,-52.0); T eps = VIGRA_CSTD::pow(2.0,-52.0);
for(unsigned int l = 0; l < n; ++l) for(MultiArrayIndex l = 0; l < n; ++l)
{ {
// Find small subdiagonalMatrix element // Find small subdiagonalMatrix element
tst1 = std::max(tst1, abs(d(l)) + abs(e(l))); tst1 = std::max(tst1, abs(d(l)) + abs(e(l)));
unsigned int m = l; unsigned int m = l;
// Original while-loop from Java code // Original while-loop from Java code
while(m < n) while(m < n)
{ {
if(abs(e(m)) <= eps*tst1) if(abs(e(m)) <= eps*tst1)
skipping to change at line 316 skipping to change at line 314
} while(abs(e(l)) > eps*tst1); } while(abs(e(l)) > eps*tst1);
} }
d(l) = d(l) + f; d(l) = d(l) + f;
e(l) = 0.0; e(l) = 0.0;
} }
// Sort eigenvalues and corresponding vectors. // Sort eigenvalues and corresponding vectors.
for(unsigned int i = 0; i < n-1; ++i) for(unsigned int i = 0; i < n-1; ++i)
{ {
int k = i; unsigned int k = i;
T p = abs(d(i)); T p = d(i);
for(unsigned int j = i+1; j < n; ++j) for(unsigned int j = i+1; j < n; ++j)
{ {
T p1 = abs(d(j)); T p1 = d(j);
if(p < p1) if(p < p1)
{ {
k = j; k = j;
p = p1; p = p1;
} }
} }
if(k != i) if(k != i)
{ {
std::swap(d(k), d(i)); std::swap(d(k), d(i));
for(unsigned int j = 0; j < n; ++j) for(unsigned int j = 0; j < n; ++j)
skipping to change at line 1011 skipping to change at line 1009
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin ear_algebra.hxx</a>\><br> <b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin ear_algebra.hxx</a>\><br>
Namespaces: vigra and vigra::linalg Namespaces: vigra and vigra::linalg
*/ */
template <class T, class C1, class C2, class C3> template <class T, class C1, class C2, class C3>
bool bool
symmetricEigensystem(MultiArrayView<2, T, C1> const & a, symmetricEigensystem(MultiArrayView<2, T, C1> const & a,
MultiArrayView<2, T, C2> & ew, MultiArrayView<2, T, C3> & ev) MultiArrayView<2, T, C2> & ew, MultiArrayView<2, T, C3> & ev)
{ {
vigra_precondition(isSymmetric(a), vigra_precondition(isSymmetric(a),
"symmetricEigensystem(): symmetric input matrix required."); "symmetricEigensystem(): symmetric input matrix required.");
unsigned int acols = columnCount(a); const MultiArrayIndex acols = columnCount(a);
vigra_precondition(1 == columnCount(ew) && acols == rowCount(ew) && vigra_precondition(1 == columnCount(ew) && acols == rowCount(ew) &&
acols == columnCount(ev) && acols == rowCount(ev), acols == columnCount(ev) && acols == rowCount(ev),
"symmetricEigensystem(): matrix shape mismatch."); "symmetricEigensystem(): matrix shape mismatch.");
ev.copy(a); // does nothing if &ev == &a ev.copy(a); // does nothing if &ev == &a
Matrix<T> de(acols, 2); Matrix<T> de(acols, 2);
detail::housholderTridiagonalization(ev, de); detail::housholderTridiagonalization(ev, de);
if(!detail::tridiagonalMatrixEigensystem(de, ev)) if(!detail::tridiagonalMatrixEigensystem(de, ev))
return false; return false;
skipping to change at line 1046 skipping to change at line 1044
<b>\#include</b> \<<a href="eigensystem_8hxx-source.html">vigra/eigensy stem.hxx</a>\> or<br> <b>\#include</b> \<<a href="eigensystem_8hxx-source.html">vigra/eigensy stem.hxx</a>\> or<br>
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin ear_algebra.hxx</a>\><br> <b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin ear_algebra.hxx</a>\><br>
Namespaces: vigra and vigra::linalg Namespaces: vigra and vigra::linalg
*/ */
template <class T, class C1, class C2, class C3> template <class T, class C1, class C2, class C3>
bool bool
nonsymmetricEigensystem(MultiArrayView<2, T, C1> const & a, nonsymmetricEigensystem(MultiArrayView<2, T, C1> const & a,
MultiArrayView<2, std::complex<T>, C2> & ew, MultiArrayView<2, T, C3> & ev) MultiArrayView<2, std::complex<T>, C2> & ew, MultiArrayView<2, T, C3> & ev)
{ {
unsigned int acols = columnCount(a); const MultiArrayIndex acols = columnCount(a);
vigra_precondition(acols == rowCount(a), vigra_precondition(acols == rowCount(a),
"nonsymmetricEigensystem(): square input matrix required."); "nonsymmetricEigensystem(): square input matrix required.");
vigra_precondition(1 == columnCount(ew) && acols == rowCount(ew) && vigra_precondition(1 == columnCount(ew) && acols == rowCount(ew) &&
acols == columnCount(ev) && acols == rowCount(ev), acols == columnCount(ev) && acols == rowCount(ev),
"nonsymmetricEigensystem(): matrix shape mismatch."); "nonsymmetricEigensystem(): matrix shape mismatch.");
Matrix<T> H(a); Matrix<T> H(a);
Matrix<T> de(acols, 2); Matrix<T> de(acols, 2);
detail::nonsymmetricHessenbergReduction(H, ev); detail::nonsymmetricHessenbergReduction(H, ev);
if(!detail::hessenbergQrDecomposition(H, ev, de)) if(!detail::hessenbergQrDecomposition(H, ev, de))
return false; return false;
for(unsigned int i=0; i < acols; ++i) for(MultiArrayIndex i = 0; i < acols; ++i)
{ {
ew(i,0) = std::complex<T>(de(i, 0), de(i, 1)); ew(i,0) = std::complex<T>(de(i, 0), de(i, 1));
} }
return true; return true;
} }
/** Compute the roots of a polynomial using the eigenvalue method. /** Compute the roots of a polynomial using the eigenvalue method.
\a poly is a real polynomial (compatible to \ref vigra::PolynomialV iew), \a poly is a real polynomial (compatible to \ref vigra::PolynomialV iew),
and \a roots a complex valued vector (compatible to <tt>std::vector </tt> and \a roots a complex valued vector (compatible to <tt>std::vector </tt>
skipping to change at line 1126 skipping to change at line 1124
return polynomialRootsEigenvalueMethod(poly, roots, true); return polynomialRootsEigenvalueMethod(poly, roots, true);
} }
/** Compute the real roots of a real polynomial using the eigenvalue me thod. /** Compute the real roots of a real polynomial using the eigenvalue me thod.
\a poly is a real polynomial (compatible to \ref vigra::PolynomialV iew), \a poly is a real polynomial (compatible to \ref vigra::PolynomialV iew),
and \a roots a real valued vector (compatible to <tt>std::vector</t t> and \a roots a real valued vector (compatible to <tt>std::vector</t t>
with a <tt>value_type</tt> compatible to the type <tt>POLYNOMIAL::R eal</tt>) to which with a <tt>value_type</tt> compatible to the type <tt>POLYNOMIAL::R eal</tt>) to which
the roots are appended. The function calls \ref polynomialRootsEige nvalueMethod() and the roots are appended. The function calls \ref polynomialRootsEige nvalueMethod() and
throws away all complex roots. It returns <tt>false</tt> if it fail s to converge. throws away all complex roots. It returns <tt>false</tt> if it fail s to converge.
The parameter <tt>polishRoots</tt> is ignored (it is only here for
syntax compatibility
with polynomialRealRoots()).
<b>\#include</b> \<<a href="eigensystem_8hxx-source.html">vigra/eig ensystem.hxx</a>\> or<br> <b>\#include</b> \<<a href="eigensystem_8hxx-source.html">vigra/eig ensystem.hxx</a>\> or<br>
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra /linear_algebra.hxx</a>\><br> <b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra /linear_algebra.hxx</a>\><br>
Namespaces: vigra and vigra::linalg Namespaces: vigra and vigra::linalg
\see polynomialRealRoots(), vigra::Polynomial \see polynomialRealRoots(), vigra::Polynomial
*/ */
template <class POLYNOMIAL, class VECTOR> template <class POLYNOMIAL, class VECTOR>
bool polynomialRealRootsEigenvalueMethod(POLYNOMIAL const & p, VECTOR & roo ts, bool polishRoots) bool polynomialRealRootsEigenvalueMethod(POLYNOMIAL const & p, VECTOR & roo ts, bool /* polishRoots */)
{ {
typedef typename NumericTraits<typename VECTOR::value_type>::ComplexPro mote Complex; typedef typename NumericTraits<typename VECTOR::value_type>::ComplexPro mote Complex;
ArrayVector<Complex> croots; ArrayVector<Complex> croots;
if(!polynomialRootsEigenvalueMethod(p, croots)) if(!polynomialRootsEigenvalueMethod(p, croots))
return false; return false;
for(unsigned int i = 0; i < croots.size(); ++i) for(unsigned int i = 0; i < croots.size(); ++i)
if(croots[i].imag() == 0.0) if(croots[i].imag() == 0.0)
roots.push_back(croots[i].real()); roots.push_back(croots[i].real());
return true; return true;
} }
 End of changes. 15 change blocks. 
15 lines changed or deleted 16 lines changed or added


 error.hxx   error.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 fftw.hxx   fftw.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 fftw3.hxx   fftw3.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2004 by Ullrich Koethe */ /* Copyright 1998-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 458 skipping to change at line 456
{ {
typedef FFTWComplex Promote; typedef FFTWComplex Promote;
}; };
template <> template <>
struct PromoteTraits<double, FFTWComplex> struct PromoteTraits<double, FFTWComplex>
{ {
typedef FFTWComplex Promote; typedef FFTWComplex Promote;
}; };
template<class T>
struct CanSkipInitialization<std::complex<T> >
{
typedef typename CanSkipInitialization<T>::type type;
static const bool value = type::asBool;
};
template<>
struct CanSkipInitialization<FFTWComplex>
{
typedef CanSkipInitialization<fftw_real>::type type;
static const bool value = type::asBool;
};
/********************************************************/ /********************************************************/
/* */ /* */
/* FFTWComplex Operations */ /* FFTWComplex Operations */
/* */ /* */
/********************************************************/ /********************************************************/
/** \addtogroup FFTWComplexOperators Functions for FFTWComplex /** \addtogroup FFTWComplexOperators Functions for FFTWComplex
<b>\#include</b> \<<a href="fftw3_8hxx-source.html">vigra/fftw3.hxx</a> \> (for FFTW 3) or<br> <b>\#include</b> \<<a href="fftw3_8hxx-source.html">vigra/fftw3.hxx</a> \> (for FFTW 3) or<br>
<b>\#include</b> \<<a href="fftw_8hxx-source.html">vigra/fftw.hxx</a>\> (for deprecated FFTW 2)<br> <b>\#include</b> \<<a href="fftw_8hxx-source.html">vigra/fftw.hxx</a>\> (for deprecated FFTW 2)<br>
skipping to change at line 724 skipping to change at line 736
value_type operator()(ITERATOR const & i) const { value_type operator()(ITERATOR const & i) const {
return (*i).re(); return (*i).re();
} }
/// Read real part at offset from iterator position. /// Read real part at offset from iterator position.
template <class ITERATOR, class DIFFERENCE> template <class ITERATOR, class DIFFERENCE>
value_type operator()(ITERATOR const & i, DIFFERENCE d) const { value_type operator()(ITERATOR const & i, DIFFERENCE d) const {
return i[d].re(); return i[d].re();
} }
/// Write real part at iterator position. /// Write real part at iterator position from a scalar.
template <class ITERATOR> template <class ITERATOR>
void set(value_type const & v, ITERATOR const & i) const { void set(value_type const & v, ITERATOR const & i) const {
(*i).re()= v; (*i).re()= v;
} }
/// Write real part at offset from iterator position. /// Write real part at offset from iterator position from a scalar.
template <class ITERATOR, class DIFFERENCE> template <class ITERATOR, class DIFFERENCE>
void set(value_type const & v, ITERATOR const & i, DIFFERENCE d) const { void set(value_type const & v, ITERATOR const & i, DIFFERENCE d) const {
i[d].re()= v; i[d].re()= v;
} }
/// Write real part at iterator position into a scalar.
template <class ITERATOR>
void set(FFTWComplex const & v, ITERATOR const & i) const {
*i = v.re();
}
/// Write real part at offset from iterator position into a scalar.
template <class ITERATOR, class DIFFERENCE>
void set(FFTWComplex const & v, ITERATOR const & i, DIFFERENCE d) const
{
i[d] = v.re();
}
}; };
/** Encapsulate access to the the imaginary part of a complex number. /** Encapsulate access to the the imaginary part of a complex number.
<b>\#include</b> \<<a href="fftw3_8hxx-source.html">vigra/fftw3.hxx</a> \> (for FFTW 3) or<br> <b>\#include</b> \<<a href="fftw3_8hxx-source.html">vigra/fftw3.hxx</a> \> (for FFTW 3) or<br>
<b>\#include</b> \<<a href="fftw_8hxx-source.html">vigra/fftw.hxx</a>\> (for deprecated FFTW 2)<br> <b>\#include</b> \<<a href="fftw_8hxx-source.html">vigra/fftw.hxx</a>\> (for deprecated FFTW 2)<br>
Namespace: vigra Namespace: vigra
*/ */
class FFTWImaginaryAccessor class FFTWImaginaryAccessor
{ {
skipping to change at line 761 skipping to change at line 785
value_type operator()(ITERATOR const & i) const { value_type operator()(ITERATOR const & i) const {
return (*i).im(); return (*i).im();
} }
/// Read imaginary part at offset from iterator position. /// Read imaginary part at offset from iterator position.
template <class ITERATOR, class DIFFERENCE> template <class ITERATOR, class DIFFERENCE>
value_type operator()(ITERATOR const & i, DIFFERENCE d) const { value_type operator()(ITERATOR const & i, DIFFERENCE d) const {
return i[d].im(); return i[d].im();
} }
/// Write imaginary part at iterator position. /// Write imaginary part at iterator position from a scalar.
template <class ITERATOR> template <class ITERATOR>
void set(value_type const & v, ITERATOR const & i) const { void set(value_type const & v, ITERATOR const & i) const {
(*i).im()= v; (*i).im()= v;
} }
/// Write imaginary part at offset from iterator position. /// Write imaginary part at offset from iterator position from a sc alar.
template <class ITERATOR, class DIFFERENCE> template <class ITERATOR, class DIFFERENCE>
void set(value_type const & v, ITERATOR const & i, DIFFERENCE d) const { void set(value_type const & v, ITERATOR const & i, DIFFERENCE d) const {
i[d].im()= v; i[d].im()= v;
} }
/// Write imaginary part at iterator position into a scalar.
template <class ITERATOR>
void set(FFTWComplex const & v, ITERATOR const & i) const {
*i = v.im();
}
/// Write imaginary part at offset from iterator position into a sc
alar.
template <class ITERATOR, class DIFFERENCE>
void set(FFTWComplex const & v, ITERATOR const & i, DIFFERENCE d) const
{
i[d] = v.im();
}
}; };
/** Write a real number into a complex one. The imaginary part is set /** Write a real number into a complex one. The imaginary part is set
to 0. to 0.
<b>\#include</b> \<<a href="fftw3_8hxx-source.html">vigra/fftw3.hxx</a> \> (for FFTW 3) or<br> <b>\#include</b> \<<a href="fftw3_8hxx-source.html">vigra/fftw3.hxx</a> \> (for FFTW 3) or<br>
<b>\#include</b> \<<a href="fftw_8hxx-source.html">vigra/fftw.hxx</a>\> (for deprecated FFTW 2)<br> <b>\#include</b> \<<a href="fftw_8hxx-source.html">vigra/fftw.hxx</a>\> (for deprecated FFTW 2)<br>
Namespace: vigra Namespace: vigra
*/ */
class FFTWWriteRealAccessor: public FFTWRealAccessor class FFTWWriteRealAccessor: public FFTWRealAccessor
skipping to change at line 1016 skipping to change at line 1052
\endcode \endcode
*/ */
doxygen_overloaded_function(template <...> void moveDCToCenter) doxygen_overloaded_function(template <...> void moveDCToCenter)
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
class DestImageIterator, class DestAccessor> class DestImageIterator, class DestAccessor>
void moveDCToCenter(SrcImageIterator src_upperleft, void moveDCToCenter(SrcImageIterator src_upperleft,
SrcImageIterator src_lowerright, SrcAccessor sa, SrcImageIterator src_lowerright, SrcAccessor sa,
DestImageIterator dest_upperleft, DestAccess or da) DestImageIterator dest_upperleft, DestAccess or da)
{ {
int w= src_lowerright.x - src_upperleft.x; int w = int(src_lowerright.x - src_upperleft.x);
int h= src_lowerright.y - src_upperleft.y; int h = int(src_lowerright.y - src_upperleft.y);
int w1 = w/2; int w1 = w/2;
int h1 = h/2; int h1 = h/2;
int w2 = (w+1)/2; int w2 = (w+1)/2;
int h2 = (h+1)/2; int h2 = (h+1)/2;
// 2. Quadrant zum 4. // 2. Quadrant zum 4.
copyImage(srcIterRange(src_upperleft, copyImage(srcIterRange(src_upperleft,
src_upperleft + Diff2D(w2, h2), sa), src_upperleft + Diff2D(w2, h2), sa),
destIter (dest_upperleft + Diff2D(w1, h1), da)); destIter (dest_upperleft + Diff2D(w1, h1), da));
skipping to change at line 1098 skipping to change at line 1134
\endcode \endcode
*/ */
doxygen_overloaded_function(template <...> void moveDCToUpperLeft) doxygen_overloaded_function(template <...> void moveDCToUpperLeft)
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
class DestImageIterator, class DestAccessor> class DestImageIterator, class DestAccessor>
void moveDCToUpperLeft(SrcImageIterator src_upperleft, void moveDCToUpperLeft(SrcImageIterator src_upperleft,
SrcImageIterator src_lowerright, SrcAccessor sa, SrcImageIterator src_lowerright, SrcAccessor sa,
DestImageIterator dest_upperleft, DestAccess or da) DestImageIterator dest_upperleft, DestAccess or da)
{ {
int w= src_lowerright.x - src_upperleft.x; int w = int(src_lowerright.x - src_upperleft.x);
int h= src_lowerright.y - src_upperleft.y; int h = int(src_lowerright.y - src_upperleft.y);
int w2 = w/2; int w2 = w/2;
int h2 = h/2; int h2 = h/2;
int w1 = (w+1)/2; int w1 = (w+1)/2;
int h1 = (h+1)/2; int h1 = (h+1)/2;
// 2. Quadrant zum 4. // 2. Quadrant zum 4.
copyImage(srcIterRange(src_upperleft, copyImage(srcIterRange(src_upperleft,
src_upperleft + Diff2D(w2, h2), sa), src_upperleft + Diff2D(w2, h2), sa),
destIter (dest_upperleft + Diff2D(w1, h1), da)); destIter (dest_upperleft + Diff2D(w1, h1), da));
skipping to change at line 1136 skipping to change at line 1172
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
class DestImageIterator, class DestAccessor> class DestImageIterator, class DestAccessor>
inline void moveDCToUpperLeft( inline void moveDCToUpperLeft(
triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
pair<DestImageIterator, DestAccessor> dest) pair<DestImageIterator, DestAccessor> dest)
{ {
moveDCToUpperLeft(src.first, src.second, src.third, moveDCToUpperLeft(src.first, src.second, src.third,
dest.first, dest.second); dest.first, dest.second);
} }
template <class DestImageIterator, class DestAccessor>
void fftShift(DestImageIterator upperleft,
DestImageIterator lowerright, DestAccessor da)
{
int w = int(lowerright.x - upperleft.x);
int h = int(lowerright.y - upperleft.y);
int w2 = w/2;
int h2 = h/2;
int w1 = (w+1)/2;
int h1 = (h+1)/2;
// 2. Quadrant zum 4.
swapImageData(destIterRange(upperleft,
upperleft + Diff2D(w2, h2), da),
destIter (upperleft + Diff2D(w1, h1), da));
// 1. Quadrant zum 3.
swapImageData(destIterRange(upperleft + Diff2D(w2, 0),
upperleft + Diff2D(w, h2), da),
destIter (upperleft + Diff2D(0, h1), da));
}
template <class DestImageIterator, class DestAccessor>
inline void fftShift(
triple<DestImageIterator, DestImageIterator, DestAccessor> dest)
{
fftShift(dest.first, dest.second, dest.third);
}
namespace detail { namespace detail {
template <class T> template <class T>
void void
fourierTransformImpl(FFTWComplexImage::const_traverser sul, fourierTransformImpl(FFTWComplexImage::const_traverser sul,
FFTWComplexImage::const_traverser slr, FFTWComplexImag e::ConstAccessor src, FFTWComplexImage::const_traverser slr, FFTWComplexImag e::ConstAccessor src,
FFTWComplexImage::traverser dul, FFTWComplexImage::Acc essor dest, T sign) FFTWComplexImage::traverser dul, FFTWComplexImage::Acc essor dest, T sign)
{ {
int w = slr.x - sul.x; int w = int(slr.x - sul.x);
int h = slr.y - sul.y; int h = int(slr.y - sul.y);
FFTWComplexImage sworkImage, dworkImage; FFTWComplexImage sworkImage, dworkImage;
fftw_complex * srcPtr = (fftw_complex *)(&*sul); fftw_complex * srcPtr = (fftw_complex *)(&*sul);
fftw_complex * destPtr = (fftw_complex *)(&*dul); fftw_complex * destPtr = (fftw_complex *)(&*dul);
// test for right memory layout (fftw expects a 2*width*height floats a rray) // test for right memory layout (fftw expects a 2*width*height floats a rray)
if (&(*(sul + Diff2D(w, 0))) != &(*(sul + Diff2D(0, 1)))) if (h > 1 && &(*(sul + Diff2D(w, 0))) != &(*(sul + Diff2D(0, 1))))
{ {
sworkImage.resize(w, h); sworkImage.resize(w, h);
copyImage(srcIterRange(sul, slr, src), destImage(sworkImage)); copyImage(srcIterRange(sul, slr, src), destImage(sworkImage));
srcPtr = (fftw_complex *)(&(*sworkImage.upperLeft())); srcPtr = (fftw_complex *)(&(*sworkImage.upperLeft()));
} }
if (&(*(dul + Diff2D(w, 0))) != &(*(dul + Diff2D(0, 1)))) if (h > 1 && &(*(dul + Diff2D(w, 0))) != &(*(dul + Diff2D(0, 1))))
{ {
dworkImage.resize(w, h); dworkImage.resize(w, h);
destPtr = (fftw_complex *)(&(*dworkImage.upperLeft())); destPtr = (fftw_complex *)(&(*dworkImage.upperLeft()));
} }
fftw_plan plan = fftw_plan_dft_2d(h, w, srcPtr, destPtr, sign, FFTW_EST IMATE ); fftw_plan plan = fftw_plan_dft_2d(h, w, srcPtr, destPtr, sign, FFTW_EST IMATE );
fftw_execute(plan); fftw_execute(plan);
fftw_destroy_plan(plan); fftw_destroy_plan(plan);
if (&(*(dul + Diff2D(w, 0))) != &(*(dul + Diff2D(0, 1)))) if (h > 1 && &(*(dul + Diff2D(w, 0))) != &(*(dul + Diff2D(0, 1))))
{ {
copyImage(srcImageRange(dworkImage), destIter(dul, dest)); copyImage(srcImageRange(dworkImage), destIter(dul, dest));
} }
} }
} // namespace detail } // namespace detail
/********************************************************/ /********************************************************/
/* */ /* */
/* fourierTransform */ /* fourierTransform */
skipping to change at line 1287 skipping to change at line 1352
See \ref fourierTransform() for details. See \ref fourierTransform() for details.
*/ */
inline void inline void
fourierTransformInverse(FFTWComplexImage::const_traverser sul, fourierTransformInverse(FFTWComplexImage::const_traverser sul,
FFTWComplexImage::const_traverser slr, FFTWComplexI mage::ConstAccessor src, FFTWComplexImage::const_traverser slr, FFTWComplexI mage::ConstAccessor src,
FFTWComplexImage::traverser dul, FFTWComplexImage:: Accessor dest) FFTWComplexImage::traverser dul, FFTWComplexImage:: Accessor dest)
{ {
detail::fourierTransformImpl(sul, slr, src, dul, dest, FFTW_BACKWARD); detail::fourierTransformImpl(sul, slr, src, dul, dest, FFTW_BACKWARD);
} }
template <class DestImageIterator, class DestAccessor>
void fourierTransformInverse(FFTWComplexImage::const_traverser sul,
FFTWComplexImage::const_traverser slr, FFTWCom
plexImage::ConstAccessor src,
DestImageIterator dul, DestAccessor dest)
{
int w = slr.x - sul.x;
int h = slr.y - sul.y;
FFTWComplexImage workImage(w, h);
fourierTransformInverse(sul, slr, src, workImage.upperLeft(), workImage
.accessor());
copyImage(srcImageRange(workImage), destIter(dul, dest));
}
template <class DestImageIterator, class DestAccessor>
inline void inline void
fourierTransformInverse(triple<FFTWComplexImage::const_traverser, fourierTransformInverse(triple<FFTWComplexImage::const_traverser,
FFTWComplexImage::const_traverser, FFTWCompl exImage::ConstAccessor> src, FFTWComplexImage::const_traverser, FFTWCompl exImage::ConstAccessor> src,
pair<FFTWComplexImage::traverser, FFTWComplexImage: :Accessor> dest) pair<DestImageIterator, DestAccessor> dest)
{ {
fourierTransformInverse(src.first, src.second, src.third, dest.first, d est.second); fourierTransformInverse(src.first, src.second, src.third, dest.first, d est.second);
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* applyFourierFilter */ /* applyFourierFilter */
/* */ /* */
/********************************************************/ /********************************************************/
skipping to change at line 1384 skipping to change at line 1463
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
class FilterImageIterator, class FilterAccessor, class FilterImageIterator, class FilterAccessor,
class DestImageIterator, class DestAccessor> class DestImageIterator, class DestAccessor>
void applyFourierFilter(SrcImageIterator srcUpperLeft, void applyFourierFilter(SrcImageIterator srcUpperLeft,
SrcImageIterator srcLowerRight, SrcAccessor sa, SrcImageIterator srcLowerRight, SrcAccessor sa,
FilterImageIterator filterUpperLeft, FilterAccessor fa, FilterImageIterator filterUpperLeft, FilterAccessor fa,
DestImageIterator destUpperLeft, DestAccessor da) DestImageIterator destUpperLeft, DestAccessor da)
{ {
// copy real input images into a complex one... // copy real input images into a complex one...
int w= srcLowerRight.x - srcUpperLeft.x; int w = int(srcLowerRight.x - srcUpperLeft.x);
int h= srcLowerRight.y - srcUpperLeft.y; int h = int(srcLowerRight.y - srcUpperLeft.y);
FFTWComplexImage workImage(w, h); FFTWComplexImage workImage(w, h);
copyImage(srcIterRange(srcUpperLeft, srcLowerRight, sa), copyImage(srcIterRange(srcUpperLeft, srcLowerRight, sa),
destImage(workImage, FFTWWriteRealAccessor())); destImage(workImage, FFTWWriteRealAccessor()));
// ...and call the impl // ...and call the impl
FFTWComplexImage const & cworkImage = workImage; FFTWComplexImage const & cworkImage = workImage;
applyFourierFilterImpl(cworkImage.upperLeft(), cworkImage.lowerRight(), cworkImage.accessor(), applyFourierFilterImpl(cworkImage.upperLeft(), cworkImage.lowerRight(), cworkImage.accessor(),
filterUpperLeft, fa, filterUpperLeft, fa,
destUpperLeft, da); destUpperLeft, da);
skipping to change at line 1447 skipping to change at line 1526
applyFourierFilter(src.first, src.second, src.third, applyFourierFilter(src.first, src.second, src.third,
filter.first, filter.second, filter.first, filter.second,
dest.first, dest.second); dest.first, dest.second);
} }
template <class FilterImageIterator, class FilterAccessor, template <class FilterImageIterator, class FilterAccessor,
class DestImageIterator, class DestAccessor> class DestImageIterator, class DestAccessor>
void applyFourierFilterImpl( void applyFourierFilterImpl(
FFTWComplexImage::const_traverser srcUpperLeft, FFTWComplexImage::const_traverser srcUpperLeft,
FFTWComplexImage::const_traverser srcLowerRight, FFTWComplexImage::const_traverser srcLowerRight,
FFTWComplexImage::ConstAccessor sa, FFTWComplexImage::ConstAccessor,
FilterImageIterator filterUpperLeft, FilterAccessor fa, FilterImageIterator filterUpperLeft, FilterAccessor fa,
DestImageIterator destUpperLeft, DestAccessor da) DestImageIterator destUpperLeft, DestAccessor da)
{ {
int w = srcLowerRight.x - srcUpperLeft.x; int w = int(srcLowerRight.x - srcUpperLeft.x);
int h = srcLowerRight.y - srcUpperLeft.y; int h = int(srcLowerRight.y - srcUpperLeft.y);
FFTWComplexImage complexResultImg(srcLowerRight - srcUpperLeft); FFTWComplexImage complexResultImg(srcLowerRight - srcUpperLeft);
// FFT from srcImage to complexResultImg // FFT from srcImage to complexResultImg
fftw_plan forwardPlan= fftw_plan forwardPlan=
fftw_plan_dft_2d(h, w, (fftw_complex *)&(*srcUpperLeft), fftw_plan_dft_2d(h, w, (fftw_complex *)&(*srcUpperLeft),
(fftw_complex *)complexResultImg.begin(), (fftw_complex *)complexResultImg.begin(),
FFTW_FORWARD, FFTW_ESTIMATE ); FFTW_FORWARD, FFTW_ESTIMATE );
fftw_execute(forwardPlan); fftw_execute(forwardPlan);
fftw_destroy_plan(forwardPlan); fftw_destroy_plan(forwardPlan);
skipping to change at line 1609 skipping to change at line 1688
filters, results); filters, results);
} }
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
class FilterType, class DestImage> class FilterType, class DestImage>
void applyFourierFilterFamily(SrcImageIterator srcUpperLeft, void applyFourierFilterFamily(SrcImageIterator srcUpperLeft,
SrcImageIterator srcLowerRight, SrcAccessor s a, SrcImageIterator srcLowerRight, SrcAccessor s a,
const ImageArray<FilterType> &filters, const ImageArray<FilterType> &filters,
ImageArray<DestImage> &results) ImageArray<DestImage> &results)
{ {
int w= srcLowerRight.x - srcUpperLeft.x; int w = int(srcLowerRight.x - srcUpperLeft.x);
int h= srcLowerRight.y - srcUpperLeft.y; int h = int(srcLowerRight.y - srcUpperLeft.y);
FFTWComplexImage workImage(w, h); FFTWComplexImage workImage(w, h);
copyImage(srcIterRange(srcUpperLeft, srcLowerRight, sa), copyImage(srcIterRange(srcUpperLeft, srcLowerRight, sa),
destImage(workImage, FFTWWriteRealAccessor())); destImage(workImage, FFTWWriteRealAccessor()));
FFTWComplexImage const & cworkImage = workImage; FFTWComplexImage const & cworkImage = workImage;
applyFourierFilterFamilyImpl(cworkImage.upperLeft(), cworkImage.lowerRi ght(), cworkImage.accessor(), applyFourierFilterFamilyImpl(cworkImage.upperLeft(), cworkImage.lowerRi ght(), cworkImage.accessor(),
filters, results); filters, results);
} }
skipping to change at line 1669 skipping to change at line 1748
// make sure the filter images have the right dimensions // make sure the filter images have the right dimensions
vigra_precondition((srcLowerRight - srcUpperLeft) == filters.imageSize( ), vigra_precondition((srcLowerRight - srcUpperLeft) == filters.imageSize( ),
"applyFourierFilterFamily called with src image size != filters.imageSize()!"); "applyFourierFilterFamily called with src image size != filters.imageSize()!");
// make sure the result image array has the right dimensions // make sure the result image array has the right dimensions
results.resize(filters.size()); results.resize(filters.size());
results.resizeImages(filters.imageSize()); results.resizeImages(filters.imageSize());
// FFT from srcImage to freqImage // FFT from srcImage to freqImage
int w= srcLowerRight.x - srcUpperLeft.x; int w = int(srcLowerRight.x - srcUpperLeft.x);
int h= srcLowerRight.y - srcUpperLeft.y; int h = int(srcLowerRight.y - srcUpperLeft.y);
FFTWComplexImage freqImage(w, h); FFTWComplexImage freqImage(w, h);
FFTWComplexImage result(w, h); FFTWComplexImage result(w, h);
fftw_plan forwardPlan= fftw_plan forwardPlan=
fftw_plan_dft_2d(h, w, (fftw_complex *)&(*srcUpperLeft), fftw_plan_dft_2d(h, w, (fftw_complex *)&(*srcUpperLeft),
(fftw_complex *)freqImage.begin(), (fftw_complex *)freqImage.begin(),
FFTW_FORWARD, FFTW_ESTIMATE ); FFTW_FORWARD, FFTW_ESTIMATE );
fftw_execute(forwardPlan); fftw_execute(forwardPlan);
fftw_destroy_plan(forwardPlan); fftw_destroy_plan(forwardPlan);
 End of changes. 24 change blocks. 
26 lines changed or deleted 110 lines changed or added


 fixedpoint.hxx   fixedpoint.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2004-2005 by Ullrich Koethe */ /* Copyright 2004-2005 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 805 skipping to change at line 803
template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigne d FracBits2> template <unsigned IntBits1, unsigned FracBits1, unsigned IntBits2, unsigne d FracBits2>
struct PromoteTraits<FixedPoint<IntBits1, FracBits1>, struct PromoteTraits<FixedPoint<IntBits1, FracBits1>,
FixedPoint<IntBits2, FracBits2> > FixedPoint<IntBits2, FracBits2> >
{ {
typedef typename typedef typename
FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBit s2, FracBits2> >::PlusType FixedPointTraits<FixedPoint<IntBits1, FracBits1>, FixedPoint<IntBit s2, FracBits2> >::PlusType
Promote; Promote;
}; };
/**************************************************************************
*********/
enum FPOverflowHandling { FPOverflowIgnore, FPOverflowSaturate, FPOverflowE
rror };
template <int IntBits, FPOverflowHandling OverflowHandling = FPOverflowIgno
re>
class FixedPoint16;
/********************************************************/
/* */
/* FixedPoint16-Traits */
/* */
/********************************************************/
/** \page FixedPoint16Traits Numeric and Promote Traits of FixedPoint16
The numeric and promote traits for FixedPoint16 follow
the general specifications for \ref NumericPromotionTraits and
\ref AlgebraicRing. They are implemented in terms of the traits of the
basic types by
partial template specialization:
\code
template <int IntBits, FPOverflowHandling OverflowHandling>
struct NumericTraits<FixedPoint16<IntBits, OverflowHandling> >
{
typedef FixedPoint16<IntBits, OverflowHandling> Type;
typedef Type Promote;
// RealPromote undefined -- multiplication with double is not s
upported.
// ComplexPromote undefined -- multiplication with double is no
t supported.
typedef Type ValueType;
typedef VigraFalseType isIntegral;
typedef VigraTrueType isScalar;
typedef VigraTrueType isSigned;
typedef VigraTrueType isOrdered;
typedef VigraFalseType isComplex;
... // etc.
};
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBit
s2>
struct PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>,
FixedPoint16<IntBits2, OverflowHandling> >
{
typedef FixedPoint16<MetaMax<IntBits1, IntBits2>::value, OverflowHa
ndling> Promote;
... // etc.
};
template <int IntBits, FPOverflowHandling OverflowHandling>
struct NormTraits<FixedPoint16<IntBits, OverflowHandling> >
{
typedef FixedPoint16<IntBits, OverflowHandling> Type;
typedef typename PromoteTraits<Type, Type>::Promote SquaredNormType
;
typedef Type NormType;
};
template <int IntBits, FPOverflowHandling OverflowHandling>
struct SquareRootTraits<FixedPoint16<IntBits, OverflowHandling> >
{
typedef FixedPoint16<IntBits, OverflowHandling> Type;
typedef FixedPoint16<(IntBits + 1) / 2, OverflowHandling> SquareRo
otResult;
typedef Type SquareRo
otArgument;
};
\endcode
<b>\#include</b> \<<a href="fixedpoint_8hxx-source.html">vigra/fixedpoi
nt.hxx</a>\><br>
Namespace: vigra
*/
template <int IntBits, FPOverflowHandling OverflowHandling>
struct NumericTraits<FixedPoint16<IntBits, OverflowHandling> >
{
typedef FixedPoint16<IntBits, OverflowHandling> Type;
typedef Type Promote;
// RealPromote undefined -- multiplication with double is not suppo
rted.
// ComplexPromote undefined -- multiplication with double is not su
pported.
typedef Type ValueType;
typedef VigraFalseType isIntegral;
typedef VigraTrueType isScalar;
typedef VigraTrueType isSigned;
typedef VigraTrueType isOrdered;
typedef VigraFalseType isComplex;
static Type zero() { return Type(0, FPNoShift); }
static Type one() { return Type(Type::ONE, FPNoShift); }
static Type nonZero() { return one(); }
static Type epsilon() { return Type(1, FPNoShift); }
static Type smallestPositive() { return Type(1, FPNoShift); }
static Type max() { return Type( Type::MAX, FPNoShift); }
static Type min() { return Type( Type::MIN, FPNoShift); }
static Promote toPromote(Type v) { return v; }
static Type fromPromote(Promote v) { return v; };
};
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
struct PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>,
FixedPoint16<IntBits2, OverflowHandling> >
{
typedef FixedPoint16<MetaMax<IntBits1, IntBits2>::value, OverflowHandli
ng> Promote;
static Promote toPromote(FixedPoint16<IntBits1, OverflowHandling> v) {
return Promote(v); }
static Promote toPromote(FixedPoint16<IntBits2, OverflowHandling> v) {
return Promote(v); }
};
template <int IntBits, FPOverflowHandling OverflowHandling>
struct PromoteTraits<FixedPoint16<IntBits, OverflowHandling>,
FixedPoint16<IntBits, OverflowHandling> >
{
typedef FixedPoint16<IntBits, OverflowHandling> Promote;
static Promote toPromote(FixedPoint16<IntBits, OverflowHandling> v) { r
eturn v; }
};
template <int IntBits, FPOverflowHandling OverflowHandling>
struct NormTraits<FixedPoint16<IntBits, OverflowHandling> >
{
typedef FixedPoint16<IntBits, OverflowHandling> Type;
typedef typename PromoteTraits<Type, Type>::Promote SquaredNormType;
typedef Type NormType;
};
template <int IntBits, FPOverflowHandling OverflowHandling>
struct SquareRootTraits<FixedPoint16<IntBits, OverflowHandling> >
{
typedef FixedPoint16<IntBits, OverflowHandling> Type;
typedef FixedPoint16<(IntBits + 1) / 2, OverflowHandling> SquareRootRe
sult;
typedef Type SquareRootAr
gument;
};
#ifndef DOXYGEN
template <bool Compatible>
struct FixedPoint_error__Right_shift_operator_has_unsupported_semantics
: staticAssert::AssertBool<Compatible>
{};
#endif /* DOXYGEN */
template <bool Predicate>
struct FixedPoint16_assignment_error__Target_object_has_too_few_integer_bit
s
: staticAssert::AssertBool<Predicate>
{};
namespace detail {
template<int BeforeIntBits, int AfterIntBits,
bool Round = false,
bool RightShift = (AfterIntBits >= BeforeIntBits)>
struct FP16Align;
template<int BeforeIntBits>
struct FP16Align<BeforeIntBits, BeforeIntBits, true, true>
{
static inline Int32 exec(Int32 v)
{
return v;
}
};
template<int BeforeIntBits>
struct FP16Align<BeforeIntBits, BeforeIntBits, false, true>
{
static inline Int32 exec(Int32 v)
{
return v;
}
};
template<int BeforeIntBits, int AfterIntBits>
struct FP16Align<BeforeIntBits, AfterIntBits, false, true>
{
static inline Int32 exec(Int32 v)
{
VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_uns
upported_semantics<((-1 >> 8) == -1)>));
return v >> (AfterIntBits - BeforeIntBits);
}
};
template<int BeforeIntBits, int AfterIntBits>
struct FP16Align<BeforeIntBits, AfterIntBits, true, true>
{
enum { ONE_HALF = 1 << (AfterIntBits - BeforeIntBits - 1) };
static inline Int32 exec(Int32 v)
{
VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_uns
upported_semantics<((-1 >> 8) == -1)>));
return (v + ONE_HALF) >> (AfterIntBits - BeforeIntBits);
}
};
template<int BeforeIntBits, int AfterIntBits, bool Round>
struct FP16Align<BeforeIntBits, AfterIntBits, Round, false>
{
static inline Int32 exec(Int32 v)
{
return v << (BeforeIntBits - AfterIntBits);
}
};
template <FPOverflowHandling OverflowHandling = FPOverflowIgnore>
struct FP16OverflowHandling
{
static inline Int32 exec(Int32 v)
{
return v;
}
static inline Int32 exec(UInt32 v)
{
return v;
}
};
template <>
struct FP16OverflowHandling<FPOverflowSaturate>
{
static inline Int32 exec(Int32 v)
{
if(v >= 1 << 15)
return (1 << 15) - 1;
if(v < -(1 << 15))
return -(1 << 15);
return v;
}
static inline Int32 exec(UInt32 v)
{
if(v >= 1 << 15)
return (1 << 15) - 1;
return v;
}
};
template <>
struct FP16OverflowHandling<FPOverflowError>
{
static inline Int32 exec(Int32 v)
{
vigra_precondition(v < (1 << 15) && v >= -(1 << 15),
"FixedPoint16: Operation overflows.");
return v;
}
static inline Int32 exec(UInt32 v)
{
vigra_precondition(v < (1 << 15),
"FixedPoint16: Operation overflows.");
return v;
}
};
template <int IntBits1, int IntBits2, int IntBitsOut,
FPOverflowHandling OverflowHandling >
struct FP16AddImpl
{
enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
static inline Int32 exec(Int32 t1, Int32 t2)
{
return FP16OverflowHandling<OverflowHandling>::exec(
FP16Align<MinIntBits, IntBitsOut, /*Round*/ true>::exec(
FP16Align<IntBits1, MinIntBits, /*Round*/ false>::exe
c(t1) +
FP16Align<IntBits2, MinIntBits, /*Round*/ false>::exe
c(t2)));
}
};
template <int IntBits1, int IntBits2, int IntBitsOut,
FPOverflowHandling OverflowHandling >
struct FP16SubImpl
{
enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
static inline Int32 exec(Int32 t1, Int32 t2)
{
return FP16OverflowHandling<OverflowHandling>::exec(
FP16Align<MinIntBits, IntBitsOut, /*Round*/ true>::exec(
FP16Align<IntBits1, MinIntBits, /*Round*/ false>::exe
c(t1) -
FP16Align<IntBits2, MinIntBits, /*Round*/ false>::exe
c(t2)));
}
};
template <int IntBits1, int IntBits2, int IntBitsOut,
FPOverflowHandling OverflowHandling >
struct FP16MulImpl
{
static inline Int32 exec(Int32 t1, Int32 t2)
{
return FP16OverflowHandling<OverflowHandling>::exec(
FP16Align<IntBits1+IntBits2, IntBitsOut+15, /*Round*/ tr
ue>::exec(t1*t2));
}
};
template <int IntBits1, int IntBits2, int IntBitsOut,
FPOverflowHandling OverflowHandling >
struct FP16DivImpl
{
static inline Int32 exec(Int32 t1, Int32 t2)
{
if(t2 == 0)
return (t1 >= 0)
? (1 << 15) - 1
: -(1 << 15);
return FP16OverflowHandling<OverflowHandling>::exec(
FP16Align<IntBits1-IntBits2, IntBitsOut+1, /*Round*/ tru
e>::exec((t1<<16)/t2));
}
};
} // namespace detail
/********************************************************/
/* */
/* FixedPoint16 */
/* */
/********************************************************/
template <class TARGET, int IntBits, FPOverflowHandling OverflowHandling>
TARGET fixed_point_cast(FixedPoint16<IntBits, OverflowHandling> v);
/** Template for 16-bit signed fixed point arithmetic.
Fixed point arithmetic is used when computations with fractional accura
cy
must be made at the highest speed possible (e.g. in the inner loop
of a volume rendering routine). The speed-up relative to floating
point arithmetic can be dramatic, especially when one can avoid
conversions between integer and floating point numbers (these are
very expensive because integer and floating point arithmetic
resides in different pipelines).
The template wraps an <tt>Int16</tt> and uses <tt>IntBits</tt> to
represent the integral part of a number, and <tt>15 - IntBits</tt>
for the fractional part. The 16th bit is reserved because FixedPoint16
is a signed type. Results of expressions with mixed types will preserve
larger number of <tt>IntBits</tt> of the results, in order to minimize
the possibility for overflow. Nonetheless, overflow can occur, and the
template parameter <tt>OverflowHandling</tt> determines how this will b
e
handled:
<DL>
<DT>FPOverflowIgnore<DD> (default) Ignore overflow, i.e. use the usual
modulo behavior of the
built-in integer types.
<DT>FPOverflowSaturate<DD> Use the largest or smallest representable nu
mber (depending on sign)
in case of overflow.
<DT>FPOverflowError<DD> Throw <tt>PreconditionViolation</tt> upon overf
low. This is useful for
debugging.
</DL>
The implementation relies on Int32-arithmetic and requires that the rig
ht-shift operator
preserves signedness. Although not enforced by the C++ standard, this i
s implemented
by most of today's processors. This property is checked by a
VIGRA_STATIC_ASSERT(FixedPoint_error__Right_shift_operator_has_unsuppor
ted_semantics).
<tt>FixedPoint16</tt> implements the required interface of an
\ref AlgebraicRing and the required numeric and
promotion traits. In addition, it supports functions <tt>add</tt>,
<tt>sub</tt>, <tt>mul</tt>, and <tt>div</tt>, where a particular layout
of the result can be enforced.
Built-in numeric types can be converted into <tt>FixedPoint16</tt> by t
he
appropriate constructors, and from <tt>FixedPoint16</tt> by means of
<tt>fixed_point_cast&lt;TargetType&gt;(fixedPoint)</tt>.
<b>See also:</b>
<ul>
<li> \ref FixedPoint16Operations
<li> \ref FixedPoint16Traits
</ul>
<b>\#include</b> \<<a href="fixedpoint_8hxx-source.html">vigra/fixedpoi
nt.hxx</a>\><br>
Namespace: vigra
*/
template <int IntBits, FPOverflowHandling OverflowHandling>
class FixedPoint16
{
public:
static const Int32 TOTAL_BITS = 15; // bit 16 is sign
static const Int32 INT_BITS = IntBits;
static const Int32 FRACTIONAL_BITS = TOTAL_BITS - INT_BITS;
static const Int32 MAX = (Int32)((1u << TOTAL_BITS) - 1);
static const Int32 MIN = -(Int32)(1u << TOTAL_BITS);
static const Int32 ONE = 1 << FRACTIONAL_BITS;
static const Int32 ONE_HALF = ONE >> 1;
static const Int32 FRACTIONAL_MASK = (1u << FRACTIONAL_BITS) - 1;
static const Int32 INT_MASK = 0xffffffffu ^ FRACTIONAL_MASK;
Int16 value;
FixedPoint16()
: value(0)
{
VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_uns
upported_semantics<((-1 >> 8) == -1)>));
}
/** Construct from an int (fractional part will become zero).
Possible overflow is handled according to the taget type's <tt>
OverflowHandling</tt>.
*/
explicit FixedPoint16(Int32 v)
: value(detail::FP16OverflowHandling<OverflowHandling>::exec(v << FRACT
IONAL_BITS))
{
VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_uns
upported_semantics<((-1 >> 8) == -1)>));
}
/** Construct from an int by a bitwise copy. This is normally only
used internally.
*/
FixedPoint16(Int32 v, FixedPointNoShift)
: value(detail::FP16OverflowHandling<OverflowHandling>::exec(v))
{
VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_uns
upported_semantics<((-1 >> 8) == -1)>));
}
/** Construct from a double and round the fractional part to
<tt>FRACTIONAL_BITS</tt> accuracy. Possible overflow is handled
according
to the taget type's <tt>OverflowHandling</tt>.
*/
explicit FixedPoint16(double rhs)
: value(detail::FP16OverflowHandling<OverflowHandling>::exec(roundi(rhs
* ONE)))
{
VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_uns
upported_semantics<((-1 >> 8) == -1)>));
}
/** Copy constructor.
*/
FixedPoint16(const FixedPoint16 &other)
: value(other.value)
{
VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_uns
upported_semantics<((-1 >> 8) == -1)>));
}
/** Construct from a FixedPoint16 with different layout. It rounds
as appropriate and
handles possible overflow according to the taget type's <tt>Ove
rflowHandling</tt>.
*/
template <int IntBits2, FPOverflowHandling OverflowHandling2>
FixedPoint16(const FixedPoint16<IntBits2, OverflowHandling2> &other)
: value(detail::FP16OverflowHandling<OverflowHandling>::exec(
detail::FP16Align<IntBits2, IntBits, /*Round*/true>::exec(other
.value)))
{
VIGRA_STATIC_ASSERT((FixedPoint_error__Right_shift_operator_has_uns
upported_semantics<((-1 >> 8) == -1)>));
}
/** Assignment from int. The fractional part will become zero.
Possible overflow is handled according to the taget type's <tt>
OverflowHandling</tt>.
*/
FixedPoint16 &operator=(Int32 rhs)
{
value = detail::FP16OverflowHandling<OverflowHandling>::exec(rhs <<
FRACTIONAL_BITS);
return *this;
}
/** Assignment form double. The fractional part is rounded, and pos
sible overflow is
handled according to the taget type's <tt>OverflowHandling</tt>
.
*/
FixedPoint16 &operator=(double rhs)
{
value = detail::FP16OverflowHandling<OverflowHandling>::exec(roundi
(rhs * ONE));
return *this;
}
/** Copy assignment.
*/
FixedPoint16 & operator=(const FixedPoint16 &other)
{
value = other.value;
return *this;
}
/** Assignment from a FixedPoint16 with different layout. It rounds
as appropriate, and possible overflow is
handled according to the taget type's <tt>OverflowHandling</tt>
.
*/
template <int IntBits2>
FixedPoint16 & operator=(const FixedPoint16<IntBits2, OverflowHandling>
&other)
{
value = detail::FP16OverflowHandling<OverflowHandling>::exec(
detail::FP16Align<IntBits2, IntBits, /*Round*/true>::exec(o
ther.value));
return *this;
}
/** Conversion to float
*/
operator float() const
{
return fixed_point_cast<float>(*this);
}
/** Conversion to double
*/
operator double() const
{
return fixed_point_cast<double>(*this);
}
/** Unary plus.
*/
FixedPoint16 operator+() const
{
return *this;
}
/** Negation.
*/
FixedPoint16 operator-() const
{
return FixedPoint16(-value, FPNoShift);
}
/** Pre-increment.
*/
FixedPoint16 & operator++()
{
value = detail::FP16OverflowHandling<OverflowHandling>::exec(value+
ONE);
return *this;
}
/** Post-increment.
*/
FixedPoint16 operator++(int)
{
FixedPoint16 old(*this);
++(*this);
return old;
}
/** Pre-decrement.
*/
FixedPoint16 & operator--()
{
value = detail::FP16OverflowHandling<OverflowHandling>::exec(value-
ONE);
return *this;
}
/** Post-decrement.
*/
FixedPoint16 operator--(int)
{
FixedPoint16 old(*this);
--(*this);
return old;
}
/** Add-assignment from a FixedPoint16 with different layout. It ro
unds as appropriate, and possible overflow is
handled according to the taget type's <tt>OverflowHandling</tt>
.
*/
template <int IntBits2>
FixedPoint16 & operator+=(const FixedPoint16<IntBits2, OverflowHandling
> &other)
{
value = detail::FP16AddImpl<IntBits, IntBits2, IntBits, OverflowHan
dling>::exec(value, other.value);
return *this;
}
/** Subtract-assignment from a FixedPoint16 with different layout.
It rounds as appropriate, and possible overflow is
handled according to the taget type's <tt>OverflowHandling</tt>
.
*/
template <int IntBits2>
FixedPoint16 & operator-=(const FixedPoint16<IntBits2, OverflowHandling
> &other)
{
value = detail::FP16SubImpl<IntBits, IntBits2, IntBits, OverflowHan
dling>::exec(value, other.value);
return *this;
}
/** Multiply-assignment from a FixedPoint16 with different layout.
It rounds as appropriate, and possible overflow is
handled according to the taget type's <tt>OverflowHandling</tt>
.
*/
template <int IntBits2>
FixedPoint16 & operator*=(const FixedPoint16<IntBits2, OverflowHandling
> &other)
{
value = detail::FP16MulImpl<IntBits, IntBits2, IntBits, OverflowHan
dling>::exec(value, other.value);
return *this;
}
/** Divide-assignment from a FixedPoint16 with different layout. It
rounds as appropriate, and possible overflow is
handled according to the taget type's <tt>OverflowHandling</tt>
.
*/
template <int IntBits2>
FixedPoint16 & operator/=(const FixedPoint16<IntBits2, OverflowHandling
> &other)
{
value = detail::FP16DivImpl<IntBits, IntBits2, IntBits, OverflowHan
dling>::exec(value, other.value);
return *this;
}
};
namespace detail {
template <class T>
struct FixedPoint16Cast;
#define VIGRA_FIXED_POINT_CAST(type) \
template <> \
struct FixedPoint16Cast<type> \
{ \
template <int IntBits, FPOverflowHandling OverflowHandling> \
static type cast(FixedPoint16<IntBits, OverflowHandling> v) \
{ \
return round(v); \
} \
};
VIGRA_FIXED_POINT_CAST(Int8)
VIGRA_FIXED_POINT_CAST(UInt8)
VIGRA_FIXED_POINT_CAST(Int16)
VIGRA_FIXED_POINT_CAST(UInt16)
VIGRA_FIXED_POINT_CAST(Int32)
VIGRA_FIXED_POINT_CAST(UInt32)
VIGRA_FIXED_POINT_CAST(Int64)
VIGRA_FIXED_POINT_CAST(UInt64)
#undef VIGRA_FIXED_POINT_CAST
template <>
struct FixedPoint16Cast<float>
{
template <int IntBits, FPOverflowHandling OverflowHandling>
static float cast(FixedPoint16<IntBits, OverflowHandling> v)
{
return (float)v.value / FixedPoint16<IntBits, OverflowHandling>::ON
E;
}
};
template <>
struct FixedPoint16Cast<double>
{
template <int IntBits, FPOverflowHandling OverflowHandling>
static double cast(FixedPoint16<IntBits, OverflowHandling> v)
{
return (double)v.value / FixedPoint16<IntBits, OverflowHandling>::O
NE;
}
};
} // namespace detail
/********************************************************/
/* */
/* FixedPoint16Operations */
/* */
/********************************************************/
/** \addtogroup FixedPoint16Operations Functions for FixedPoint16
\brief <b>\#include</b> \<<a href="fixedpoint_8hxx-source.html">vig
ra/fixedpoint.hxx</a>\><br>
These functions fulfill the requirements of an \ref AlgebraicRing.
Namespace: vigra
<p>
*/
//@{
/** Convert a FixedPoint16 to a built-in type.
If the target is integral, the value is rounded.<br>
Usage:
\code
FixedPoint16<16,15> fp(...);
double d = fixed_point_cast<double>(fp);
\endcode
*/
template <class TARGET, int IntBits, FPOverflowHandling OverflowHandling>
TARGET fixed_point_cast(FixedPoint16<IntBits, OverflowHandling> v)
{
return detail::FixedPoint16Cast<TARGET>::cast(v);
}
/// equal
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
inline
bool operator==(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<In
tBits2, OverflowHandling> r)
{
enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
return (l.value << (IntBits1 - MinIntBits)) == (r.value << (IntBits2 -
MinIntBits));
}
/// not equal
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
inline
bool operator!=(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<In
tBits2, OverflowHandling> r)
{
enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
return (l.value << (IntBits1 - MinIntBits)) != (r.value << (IntBits2 -
MinIntBits));
}
/// less than
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
inline
bool operator<(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<Int
Bits2, OverflowHandling> r)
{
enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
return (l.value << (IntBits1 - MinIntBits)) < (r.value << (IntBits2 - M
inIntBits));
}
/// less or equal
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
inline
bool operator<=(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<In
tBits2, OverflowHandling> r)
{
enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
return (l.value << (IntBits1 - MinIntBits)) <= (r.value << (IntBits2 -
MinIntBits));
}
/// greater
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
inline
bool operator>(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<Int
Bits2, OverflowHandling> r)
{
enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
return (l.value << (IntBits1 - MinIntBits)) > (r.value << (IntBits2 - M
inIntBits));
}
/// greater or equal
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
inline
bool operator>=(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<In
tBits2, OverflowHandling> r)
{
enum { MinIntBits = MetaMin<IntBits1, IntBits2>::value };
return (l.value << (IntBits1 - MinIntBits)) >= (r.value << (IntBits2 -
MinIntBits));
}
/// addition with automatic determination of the appropriate result typ
e.
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
inline
typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint
16<IntBits2, OverflowHandling> >::Promote
operator+(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2
, OverflowHandling> r)
{
typedef typename
PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint1
6<IntBits2, OverflowHandling> >::Promote
Result;
return Result(detail::FP16AddImpl<IntBits1, IntBits2, Result::INT_BITS,
OverflowHandling>::exec(l.value, r.value), FPNoShift);
}
/// addition with enforced result type.
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2,
int IntBits3>
inline
FixedPoint16<IntBits3, OverflowHandling> &
add(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, Over
flowHandling> r,
FixedPoint16<IntBits3, OverflowHandling> & result)
{
result.value = detail::FP16AddImpl<IntBits1, IntBits2, IntBits3, Overfl
owHandling>::exec(l.value, r.value);
return result;
}
/// subtraction with automatic determination of the appropriate result
type.
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
inline
typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint
16<IntBits2, OverflowHandling> >::Promote
operator-(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2
, OverflowHandling> r)
{
typedef typename
PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint1
6<IntBits2, OverflowHandling> >::Promote
Result;
return Result(detail::FP16SubImpl<IntBits1, IntBits2, Result::INT_BITS,
OverflowHandling>::exec(l.value, r.value), FPNoShift);
}
/// subtraction with enforced result type.
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2,
int IntBits3>
inline FixedPoint16<IntBits3, OverflowHandling> &
sub(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, Over
flowHandling> r,
FixedPoint16<IntBits3, OverflowHandling> & result)
{
result.value = detail::FP16SubImpl<IntBits1, IntBits2, IntBits3, Overfl
owHandling>::exec(l.value, r.value);
return result;
}
/// multiplication with automatic determination of the appropriate resu
lt type.
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
inline
typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint
16<IntBits2, OverflowHandling> >::Promote
operator*(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2
, OverflowHandling> r)
{
typedef typename
PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint1
6<IntBits2, OverflowHandling> >::Promote
Result;
return Result(detail::FP16MulImpl<IntBits1, IntBits2, Result::INT_BITS,
OverflowHandling>::exec(l.value, r.value), FPNoShift);
}
/// multiplication with enforced result type.
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2,
int IntBits3>
inline
FixedPoint16<IntBits3, OverflowHandling> &
mul(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, Over
flowHandling> r,
FixedPoint16<IntBits3, OverflowHandling> & result)
{
result.value = detail::FP16MulImpl<IntBits1, IntBits2, IntBits3, Overfl
owHandling>::exec(l.value, r.value);
return result;
}
/// division with automatic determination of the appropriate result typ
e.
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2>
inline
typename PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint
16<IntBits2, OverflowHandling> >::Promote
operator/(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2
, OverflowHandling> r)
{
typedef typename
PromoteTraits<FixedPoint16<IntBits1, OverflowHandling>, FixedPoint1
6<IntBits2, OverflowHandling> >::Promote
Result;
return Result(detail::FP16DivImpl<IntBits1, IntBits2, Result::INT_BITS,
OverflowHandling>::exec(l.value, r.value), FPNoShift);
}
/// division with enforced result type.
template <int IntBits1, FPOverflowHandling OverflowHandling, int IntBits2,
int IntBits3>
inline
FixedPoint16<IntBits3, OverflowHandling> &
div(FixedPoint16<IntBits1, OverflowHandling> l, FixedPoint16<IntBits2, Over
flowHandling> r,
FixedPoint16<IntBits3, OverflowHandling> & result)
{
result.value = detail::FP16DivImpl<IntBits1, IntBits2, IntBits3, Overfl
owHandling>::exec(l.value, r.value);
return result;
}
/// square root.
template <int IntBits, FPOverflowHandling OverflowHandling>
inline typename SquareRootTraits<FixedPoint16<IntBits, OverflowHandling> >:
:SquareRootResult
sqrt(FixedPoint16<IntBits, OverflowHandling> v)
{
typedef typename SquareRootTraits<FixedPoint16<IntBits, OverflowHandlin
g> >::SquareRootResult Result;
enum { Shift = 15 + IntBits - 2*Result::INT_BITS };
return Result(sqrti(v.value << Shift), FPNoShift);
}
#ifndef VIGRA_NO_HYPOT
using ::hypot;
#endif
/// Length of hypothenuse.
template <int IntBits, FPOverflowHandling OverflowHandling>
inline FixedPoint16<IntBits, OverflowHandling>
hypot(FixedPoint16<IntBits, OverflowHandling> v1, FixedPoint16<IntBits, Ove
rflowHandling> v2)
{
UInt32 l = abs(v1.value), r = abs(v2.value);
// sq(l) + sq(r) <= 2**31, so overflow handling after sqrti is sufficie
nt
return FixedPoint16<IntBits, OverflowHandling>(
detail::FP16OverflowHandling<OverflowHandling>::exec(sqr
ti(sq(l) + sq(r))),
FPNoShift);
}
using std::atan2;
/// Arctangent. Accuracy better than 1/3 degree (9 significant bits).
template <int IntBits, FPOverflowHandling OverflowHandling>
FixedPoint16<2, OverflowHandling>
atan2(FixedPoint16<IntBits, OverflowHandling> y, FixedPoint16<IntBits, Over
flowHandling> x)
{
enum { ResIntBits = 2 };
typedef FixedPoint16<ResIntBits, OverflowHandling> FP;
static const FP zero(0), pi(M_PI), pi_2(0.5 * M_PI), mpi_2(-0.5 * M_PI)
;
static const Int32 Pi_4 = roundi(0.25 * M_PI * (1 << 15)), // 15 frac
bits
Pi3_4 = roundi(0.75 * M_PI * (1 << 15)),
c1 = roundi(0.19826763260224867 * (1 << 15)),
c2 = roundi(-0.9757748231899761 * (1 << 30));
// coefficients c1 and c2 minimize
//
// NIntegrate[(c1 r^3 + c2 r + Pi/4 - a)^4 /. r -> (Cos[a] - Sin[a])/(C
os[a] + Sin[a]), {a, 0, Pi/2}]
//
// Thanks to Jim Shima, http://www.dspguru.com/comp.dsp/tricks/alg/fxda
tan2.htm
if(x.value == 0)
return (y.value > 0)
? pi_2
: (y.value < 0)
? mpi_2
: zero;
Int32 abs_y = abs(y.value);
Int32 r, angle;
if(x.value > 0)
{
if(y.value == 0)
return zero;
r = ((x.value - abs_y) << 15) / (x.value + abs_y); // 15 frac bits
angle = Pi_4;
}
else
{
if(y.value == 0)
return pi;
r = ((x.value + abs_y) << 15) / (abs_y - x.value); // 15 frac bits
angle = Pi3_4;
}
angle += r*((c2 + c1 * (sq(r) >> 15)) >> 15) >> 15;
return (y.value > 0)
? FP(detail::FP16Align<0, ResIntBits, true>::exec( angle), F
PNoShift)
: FP(detail::FP16Align<0, ResIntBits, true>::exec(-angle), F
PNoShift);
}
/// absolute value.
template <int IntBits, FPOverflowHandling OverflowHandling>
inline FixedPoint16<IntBits, OverflowHandling>
abs(FixedPoint16<IntBits, OverflowHandling> v)
{
return FixedPoint16<IntBits, OverflowHandling>(abs(v.value), FPNoShift)
;
}
/// squared norm (same as v*v).
template <int IntBits, FPOverflowHandling OverflowHandling>
inline
typename NormTraits<FixedPoint16<IntBits, OverflowHandling> >::SquaredNormT
ype
squaredNorm(FixedPoint16<IntBits, OverflowHandling> v)
{
return v*v;
}
/// norm (same as abs).
template <int IntBits, FPOverflowHandling OverflowHandling>
inline
typename NormTraits<FixedPoint16<IntBits, OverflowHandling> >::NormType
norm(FixedPoint16<IntBits, OverflowHandling> const & v)
{
return abs(v);
}
/// fractional part. (difference between v and its floor)
template <int IntBits, FPOverflowHandling OverflowHandling>
inline FixedPoint16<IntBits, OverflowHandling>
frac(FixedPoint16<IntBits, OverflowHandling> v)
{
return FixedPoint16<IntBits, OverflowHandling>(
v.value - (v.value & FixedPoint16<IntBits, OverflowHandling>::IN
T_MASK),
FPNoShift);
}
/// dual fractional part. (1 - frac(v))
template <int IntBits, FPOverflowHandling OverflowHandling>
inline FixedPoint16<IntBits, OverflowHandling>
dual_frac(FixedPoint16<IntBits, OverflowHandling> v)
{
return FixedPoint16<IntBits, OverflowHandling>(
FixedPoint16<IntBits, OverflowHandling>::ONE - v.value + (v.valu
e & FixedPoint16<IntBits, OverflowHandling>::INT_MASK),
FPNoShift);
}
/// rounding down.
template <int IntBits, FPOverflowHandling OverflowHandling>
inline Int32
floor(FixedPoint16<IntBits, OverflowHandling> v)
{
return(v.value >> FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_B
ITS);
}
/// rounding up.
template <int IntBits, FPOverflowHandling OverflowHandling>
inline Int32
ceil(FixedPoint16<IntBits, OverflowHandling> v)
{
return((v.value + FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_M
ASK) >>
FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_B
ITS);
}
/// rounding to the nearest integer.
template <int IntBits, FPOverflowHandling OverflowHandling>
inline Int32
round(FixedPoint16<IntBits, OverflowHandling> v)
{
return((v.value + FixedPoint16<IntBits, OverflowHandling>::ONE_HALF) >>
FixedPoint16<IntBits, OverflowHandling>::FRACTIONAL_B
ITS);
}
/// rounding to the nearest integer.
template <int IntBits, FPOverflowHandling OverflowHandling>
inline Int32
roundi(FixedPoint16<IntBits, OverflowHandling> v)
{
return round(v);
}
//@}
} // namespace vigra } // namespace vigra
namespace std {
template <int IntBits, vigra::FPOverflowHandling OverflowHandling>
ostream & operator<<(ostream & s, vigra::FixedPoint16<IntBits, OverflowHand
ling> v)
{
s << vigra::fixed_point_cast<float>(v);
return s;
}
} // namespace std
#endif // VIGRA_FIXEDPOINT_HXX #endif // VIGRA_FIXEDPOINT_HXX
 End of changes. 5 change blocks. 
3 lines changed or deleted 1120 lines changed or added


 flatmorphology.hxx   flatmorphology.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 338 skipping to change at line 336
// search to the right // search to the right
for(i=rankpos; i<256; i++) for(i=rankpos; i<256; i++)
{ {
if((float)(hist[i]+leftsum) / winsize >= rank) brea k; if((float)(hist[i]+leftsum) / winsize >= rank) brea k;
leftsum+=hist[i]; leftsum+=hist[i];
} }
rankpos = i; rankpos = i;
} }
else else
{ {
/// search to the left // search to the left
for(i=rankpos-1; i>=0; i--) for(i=rankpos-1; i>=0; i--)
{ {
leftsum-=hist[i]; leftsum-=hist[i];
if((float)leftsum / winsize < rank) break; if((float)leftsum / winsize < rank) break;
} }
rankpos = i; rankpos = i;
} }
} }
da.set(rankpos, xd); da.set(rankpos, xd);
skipping to change at line 905 skipping to change at line 903
// search to the right // search to the right
for(i=rankpos; i<256; i++) for(i=rankpos; i<256; i++)
{ {
if((float)(hist[i]+leftsum) / winsize >= rank) break; if((float)(hist[i]+leftsum) / winsize >= rank) break;
leftsum+=hist[i]; leftsum+=hist[i];
} }
rankpos = i; rankpos = i;
} }
else else
{ {
/// search to the left // search to the left
for(i=rankpos-1; i>=0; i--) for(i=rankpos-1; i>=0; i--)
{ {
leftsum-=hist[i]; leftsum-=hist[i];
if((float)leftsum / winsize < rank) break; if((float)leftsum / winsize < rank) break;
} }
rankpos = i; rankpos = i;
} }
} }
da.set(rankpos, xd); da.set(rankpos, xd);
 End of changes. 5 change blocks. 
5 lines changed or deleted 3 lines changed or added


 functorexpression.hxx   functorexpression.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 49 skipping to change at line 47
#define VIGRA_FUNCTOREXPRESSION_HXX #define VIGRA_FUNCTOREXPRESSION_HXX
/** \page FunctorExpressions Functor Expressions /** \page FunctorExpressions Functor Expressions
Simple automatic functor creation by means of expression templates Simple automatic functor creation by means of expression templates
(also known as a "lambda library"). (also known as a "lambda library").
<b>\#include</b> \<<a href="functorexpression_8hxx-source.html">vigra/f unctorexpression.hxx</a>\><br> <b>\#include</b> \<<a href="functorexpression_8hxx-source.html">vigra/f unctorexpression.hxx</a>\><br>
Namespace: vigra::functor Namespace: vigra::functor
<b> Note:</b> This functionality is not available under Microsoft Visua
l C++,
because support for partial template specialization is required.
<b> Motivation</b> <b> Motivation</b>
Many generic algorithms are made more flexible by means of functors Many generic algorithms are made more flexible by means of functors
which define part of the algorithms' behavior according to the which define part of the algorithms' behavior according to the
needs of a specific situation. For example, we can apply an exponential needs of a specific situation. For example, we can apply an exponential
to each pixel by passing a pointer to the <TT>exp</TT> function to each pixel by passing a pointer to the <TT>exp</TT> function
to <TT>transformImage()</TT>: to <TT>transformImage()</TT>:
\code \code
vigra::FImage src(w,h), dest(w,h); vigra::FImage src(w,h), dest(w,h);
skipping to change at line 143 skipping to change at line 138
<b> Automatic Functor Creation</b> <b> Automatic Functor Creation</b>
Automatic functor creation in VIGRA is based on a technique called Automatic functor creation in VIGRA is based on a technique called
<a href="http://extreme.indiana.edu/~tveldhui/papers/Expression-Templat es/exprtmpl.html">Expression Templates</a>. <a href="http://extreme.indiana.edu/~tveldhui/papers/Expression-Templat es/exprtmpl.html">Expression Templates</a>.
This means that C++ operators are This means that C++ operators are
overloaded so that they don't execute the specified operation directly, overloaded so that they don't execute the specified operation directly,
but instead produce a functor which will later calculate the result. but instead produce a functor which will later calculate the result.
This technique has the big advantage that the familiar operator notatio n This technique has the big advantage that the familiar operator notatio n
can be used, while all the flexibility of generic programming is preser ved. can be used, while all the flexibility of generic programming is preser ved.
Unfortunately, it requires partial template specialization, so these ca
pabilities
are not available on compilers that dont support this C++ feature
(in particular, on Microsoft Visual C++).
The above problem "apply <TT>exp(-beta*v)</TT> to every pixel" will be solved The above problem "apply <TT>exp(-beta*v)</TT> to every pixel" will be solved
like this: like this:
\code \code
using namespace vigra::functor; using namespace vigra::functor;
float beta = ...; float beta = ...;
transformImage(srcImageRange(src), destImage(dest), transformImage(srcImageRange(src), destImage(dest),
skipping to change at line 180 skipping to change at line 172
for algorithms that have multiple input images, such as for algorithms that have multiple input images, such as
\ref combineTwoImages() and \ref combineThreeImages(). \ref combineTwoImages() and \ref combineThreeImages().
<DT><b>* (multiplication):</b><DD> creates a functor that returns the p roduct of <DT><b>* (multiplication):</b><DD> creates a functor that returns the p roduct of
its arguments. Likewise, the other C++ operators (i.e. its arguments. Likewise, the other C++ operators (i.e.
<TT>+, -, *, /, %, ==, !=, <, <=, >, >=, &&, ||, &, |, ^, !, ~</TT >) <TT>+, -, *, /, %, ==, !=, <, <=, >, >=, &&, ||, &, |, ^, !, ~</TT >)
are overloaded. are overloaded.
<DT><b><TT>exp():</TT></b><DD> creates a functor that takes the exponen tial of its <DT><b><TT>exp():</TT></b><DD> creates a functor that takes the exponen tial of its
argument. Likewise, the other algebraic functions argument. Likewise, the other algebraic functions
(i.e. <TT>sqrt, exp, log, log10, sin, asin, cos, acos, tan, (i.e. <TT>sq, sqrt, exp, log, log10, sin, asin, cos, acos, tan,
atan, abs, floor, ceil, pow, atan2, fmod, min, max</TT>) atan, abs, floor, ceil, pow, atan2, fmod, min, max</TT>)
are overloaded. are overloaded.
</DL> </DL>
We will explain additional capabilities of the functor creation mechani sm We will explain additional capabilities of the functor creation mechani sm
by means of examples. by means of examples.
The same argument can be used several times in the expression. The same argument can be used several times in the expression.
For example, to calculate the gradient magnitude from the components For example, to calculate the gradient magnitude from the components
skipping to change at line 1030 skipping to change at line 1022
template <class EXPR1, class EXPR2, class EXPR3> template <class EXPR1, class EXPR2, class EXPR3>
struct IfThenElseFunctor struct IfThenElseFunctor
{ {
IfThenElseFunctor(EXPR1 const & e1, EXPR2 const & e2, EXPR3 const & e3) IfThenElseFunctor(EXPR1 const & e1, EXPR2 const & e2, EXPR3 const & e3)
: expr1_(e1), expr2_(e2), expr3_(e3) : expr1_(e1), expr2_(e2), expr3_(e3)
{} {}
typename ResultTraits0<IfThenElseFunctor>::Res typename ResultTraits0<IfThenElseFunctor>::Res
operator()() const operator()() const
{ {
typename if(expr1_())
ResultTraits0<IfThenElseFunctor>::Res {
r2(expr2_()); return typename ResultTraits0<IfThenElseFunctor>::Res(expr2_())
typename ;
ResultTraits0<IfThenElseFunctor>::Res }
r3(expr3_()); else
return expr1_() ? r2 : r3; {
return typename ResultTraits0<IfThenElseFunctor>::Res(expr3_())
;
}
} }
template <class T> template <class T>
typename ResultTraits1<IfThenElseFunctor, T>::Res typename ResultTraits1<IfThenElseFunctor, T>::Res
operator()(T const & v1) const operator()(T const & v1) const
{ {
typename if(expr1_(v1))
ResultTraits1<IfThenElseFunctor, T>::Res {
r2(expr2_(v1)); return typename ResultTraits1<IfThenElseFunctor, T>::Res(expr2_
typename (v1));
ResultTraits1<IfThenElseFunctor, T>::Res }
r3(expr3_(v1)); else
return expr1_(v1) ? r2 : r3; {
return typename ResultTraits1<IfThenElseFunctor, T>::Res(expr3_
(v1));
}
} }
template <class T1, class T2> template <class T1, class T2>
typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res
operator()(T1 const & v1, T2 const & v2) const operator()(T1 const & v1, T2 const & v2) const
{ {
typename if(expr1_(v1, v2))
ResultTraits2<IfThenElseFunctor, T1, T2>::Res {
r2(expr2_(v1, v2)); return typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res(e
typename xpr2_(v1, v2));
ResultTraits2<IfThenElseFunctor, T1, T2>::Res }
r3(expr3_(v1, v2)); else
return expr1_(v1, v2) ? r2 : r3; {
return typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res(e
xpr3_(v1, v2));
}
} }
template <class T1, class T2, class T3> template <class T1, class T2, class T3>
typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res
operator()(T1 const & v1, T2 const & v2, T3 const & v3) const operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
{ {
typename if(expr1_(v1, v2, v3))
ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res {
r2(expr2_(v1, v2, v3)); return typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::R
typename es(expr2_(v1, v2, v3));
ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res }
r3(expr3_(v1, v2, v3)); else
return expr1_(v1, v2, v3) ? r2 : r3; {
return typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::R
es(expr3_(v1, v2, v3));
}
} }
private: private:
EXPR1 expr1_; EXPR1 expr1_;
EXPR2 expr2_; EXPR2 expr2_;
EXPR3 expr3_; EXPR3 expr3_;
IfThenElseFunctor & operator=(IfThenElseFunctor const &); // not implem ented IfThenElseFunctor & operator=(IfThenElseFunctor const &); // not implem ented
}; };
skipping to change at line 1109 skipping to change at line 1105
UnaryFunctor<EXPR2>, UnaryFunctor<EXPR2>,
UnaryFunctor<EXPR3> > >(p); UnaryFunctor<EXPR3> > >(p);
} }
/************************************************************/ /************************************************************/
/* */ /* */
/* functors for unary functions */ /* functors for unary functions */
/* */ /* */
/************************************************************/ /************************************************************/
#define MAKE_FUNCTOR_UNARY_FUNCTION(function, namespc) \ #define MAKE_FUNCTOR_UNARY_FUNCTION(function, namespc, traitsClass, traitsV alue) \
using ::namespc::function; \ using ::namespc::function; \
template <class EXPR> \ template <class EXPR> \
struct Functor_##function; \ struct Functor_##function; \
\ \
template <class EXPR> \ template <class EXPR> \
struct ResultTraits0<Functor_##function<EXPR> > \ struct ResultTraits0<Functor_##function<EXPR> > \
{ \ { \
typedef typename ResultTraits0<EXPR>::Res R1; \ typedef typename ResultTraits0<EXPR>::Res R1; \
typedef typename NumericTraits<R1>::RealPromote Res; \ typedef typename traitsClass<R1>::traitsValue Res; \
}; \ }; \
\ \
template <class EXPR, class T1> \ template <class EXPR, class T1> \
struct ResultTraits1<Functor_##function<EXPR>, T1> \ struct ResultTraits1<Functor_##function<EXPR>, T1> \
{ \ { \
typedef typename ResultTraits1<EXPR, T1>::Res R1; \ typedef typename ResultTraits1<EXPR, T1>::Res R1; \
typedef typename NumericTraits<R1>::RealPromote Res; \ typedef typename traitsClass<R1>::traitsValue Res; \
}; \ }; \
\ \
template <class EXPR, class T1, class T2> \ template <class EXPR, class T1, class T2> \
struct ResultTraits2<Functor_##function<EXPR>, T1, T2> \ struct ResultTraits2<Functor_##function<EXPR>, T1, T2> \
{ \ { \
typedef typename ResultTraits2<EXPR, T1, T2>::Res R1; \ typedef typename ResultTraits2<EXPR, T1, T2>::Res R1; \
typedef typename NumericTraits<R1>::RealPromote Res; \ typedef typename traitsClass<R1>::traitsValue Res; \
}; \ }; \
\ \
template <class EXPR, class T1, class T2, class T3> \ template <class EXPR, class T1, class T2, class T3> \
struct ResultTraits3<Functor_##function<EXPR>, T1, T2, T3> \ struct ResultTraits3<Functor_##function<EXPR>, T1, T2, T3> \
{ \ { \
typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res R1; \ typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res R1; \
typedef typename NumericTraits<R1>::RealPromote Res; \ typedef typename traitsClass<R1>::traitsValue Res; \
}; \ }; \
\ \
template <class EXPR> \ template <class EXPR> \
struct Functor_##function \ struct Functor_##function \
{ \ { \
Functor_##function(EXPR const & e) \ Functor_##function(EXPR const & e) \
: expr_(e) \ : expr_(e) \
{} \ {} \
\ \
typename ResultTraits0<Functor_##function>::Res \ typename ResultTraits0<Functor_##function>::Res \
skipping to change at line 1194 skipping to change at line 1190
template <class EXPR> \ template <class EXPR> \
inline UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > > \ inline UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > > \
function(UnaryFunctor<EXPR> const & e) \ function(UnaryFunctor<EXPR> const & e) \
{ \ { \
Functor_##function<UnaryFunctor<EXPR> > p(e); \ Functor_##function<UnaryFunctor<EXPR> > p(e); \
return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > >(p); \ return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > >(p); \
} }
/************************************************************/ /************************************************************/
MAKE_FUNCTOR_UNARY_FUNCTION(sqrt, std) MAKE_FUNCTOR_UNARY_FUNCTION(sq, vigra, NumericTraits, RealPromote)
MAKE_FUNCTOR_UNARY_FUNCTION(exp, std) MAKE_FUNCTOR_UNARY_FUNCTION(sqrt, std, NumericTraits, RealPromote)
MAKE_FUNCTOR_UNARY_FUNCTION(log, std) MAKE_FUNCTOR_UNARY_FUNCTION(exp, std, NumericTraits, RealPromote)
MAKE_FUNCTOR_UNARY_FUNCTION(log10, std) MAKE_FUNCTOR_UNARY_FUNCTION(log, std, NumericTraits, RealPromote)
MAKE_FUNCTOR_UNARY_FUNCTION(sin, std) MAKE_FUNCTOR_UNARY_FUNCTION(log10, std, NumericTraits, RealPromote)
MAKE_FUNCTOR_UNARY_FUNCTION(asin, std) MAKE_FUNCTOR_UNARY_FUNCTION(sin, std, NumericTraits, RealPromote)
MAKE_FUNCTOR_UNARY_FUNCTION(cos, std) MAKE_FUNCTOR_UNARY_FUNCTION(asin, std, NumericTraits, RealPromote)
MAKE_FUNCTOR_UNARY_FUNCTION(acos, std) MAKE_FUNCTOR_UNARY_FUNCTION(cos, std, NumericTraits, RealPromote)
MAKE_FUNCTOR_UNARY_FUNCTION(tan, std) MAKE_FUNCTOR_UNARY_FUNCTION(acos, std, NumericTraits, RealPromote)
MAKE_FUNCTOR_UNARY_FUNCTION(atan, std) MAKE_FUNCTOR_UNARY_FUNCTION(tan, std, NumericTraits, RealPromote)
MAKE_FUNCTOR_UNARY_FUNCTION(floor, std) MAKE_FUNCTOR_UNARY_FUNCTION(atan, std, NumericTraits, RealPromote)
MAKE_FUNCTOR_UNARY_FUNCTION(ceil, std) MAKE_FUNCTOR_UNARY_FUNCTION(floor, std, NumericTraits, RealPromote)
MAKE_FUNCTOR_UNARY_FUNCTION(abs, vigra) MAKE_FUNCTOR_UNARY_FUNCTION(ceil, std, NumericTraits, RealPromote)
//MAKE_FUNCTOR_UNARY_FUNCTION(norm, vigra) MAKE_FUNCTOR_UNARY_FUNCTION(abs, vigra, NumericTraits, RealPromote)
//MAKE_FUNCTOR_UNARY_FUNCTION(squaredNorm, vigra) MAKE_FUNCTOR_UNARY_FUNCTION(norm, vigra, NormTraits, NormType)
MAKE_FUNCTOR_UNARY_FUNCTION(squaredNorm, vigra, NormTraits, SquaredNormType
)
#undef MAKE_FUNCTOR_UNARY_FUNCTION #undef MAKE_FUNCTOR_UNARY_FUNCTION
/************************************************************/ /************************************************************/
/* */ /* */
/* functors for unary operators */ /* functors for unary operators */
/* */ /* */
/************************************************************/ /************************************************************/
#define MAKE_FUNCTOR_UNARY_OPERATOR(name, op) \ #define MAKE_FUNCTOR_UNARY_OPERATOR(name, op) \
 End of changes. 16 change blocks. 
60 lines changed or deleted 64 lines changed or added


 functortraits.hxx   functortraits.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2005 by Ullrich Koethe */ /* Copyright 1998-2005 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 46 skipping to change at line 44
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_FUNCTORTRAITS_HXX #ifndef VIGRA_FUNCTORTRAITS_HXX
#define VIGRA_FUNCTORTRAITS_HXX #define VIGRA_FUNCTORTRAITS_HXX
#include <functional> #include <functional>
#include "metaprogramming.hxx" #include "metaprogramming.hxx"
namespace vigra { namespace vigra {
struct InitializerTag {};
struct UnaryFunctorTag {};
struct BinaryFunctorTag {};
struct TernaryFunctorTag {};
struct UnaryAnalyserTag {};
struct BinaryAnalyserTag {};
struct TernaryAnalyserTag {};
struct UnaryReduceFunctorTag
: public InitializerTag, public UnaryAnalyserTag
{};
struct BinaryReduceFunctorTag
: public InitializerTag, public BinaryAnalyserTag
{};
typedef UnaryFunctorTag UnaryExpandFunctorTag;
typedef BinaryFunctorTag BinaryExpandFunctorTag;
template <class T> template <class T>
class FunctorTraitsBase class FunctorTraitsBase
{ {
public: public:
typedef T type; typedef T type;
typedef VigraFalseType isInitializer; typedef typename IsDerivedFrom<T, InitializerTag>::result isInitializer ;
typedef VigraFalseType isUnaryFunctor; typedef typename IsDerivedFrom<T, UnaryFunctorTag>::result isUnaryFunct
typedef VigraFalseType isBinaryFunctor; or;
typedef VigraFalseType isTernaryFunctor; typedef typename IsDerivedFrom<T, BinaryFunctorTag>::result isBinaryFun
ctor;
typedef typename IsDerivedFrom<T, TernaryFunctorTag>::result isTernaryF
unctor;
typedef VigraFalseType isUnaryAnalyser; typedef typename IsDerivedFrom<T, UnaryAnalyserTag>::result isUnaryAnal
typedef VigraFalseType isBinaryAnalyser; yser;
typedef VigraFalseType isTernaryAnalyser; typedef typename IsDerivedFrom<T, BinaryAnalyserTag>::result isBinaryAn
alyser;
typedef typename IsDerivedFrom<T, TernaryAnalyserTag>::result isTernary
Analyser;
}; };
/** \addtogroup Functors /** \addtogroup Functors
*/ */
//@{ //@{
/** \brief Export associated information for a functor. /** \brief Export associated information for a functor.
The FunctorTraits class contains the following fields: The FunctorTraits class contains the following fields:
\code \code
skipping to change at line 88 skipping to change at line 105
typedef ... isUnaryFunctor; typedef ... isUnaryFunctor;
typedef ... isBinaryFunctor; typedef ... isBinaryFunctor;
typedef ... isTernaryFunctor; typedef ... isTernaryFunctor;
typedef ... isUnaryAnalyser; typedef ... isUnaryAnalyser;
typedef ... isBinaryAnalyser; typedef ... isBinaryAnalyser;
typedef ... isTernaryAnalyser; typedef ... isTernaryAnalyser;
}; };
\endcode \endcode
Where the dots are either <tt>VigraTrueType</tt> or <tt>VigraFalseType< /tt> where the dots are either <tt>VigraTrueType</tt> or <tt>VigraFalseType< /tt>
depending on whether the functor supports the respective functionality or not. depending on whether the functor supports the respective functionality or not.
Note that these traits are automatically defined correctly when your fu
nctor is derived
from the appropriate functor tag classes:
\code
struct InitializerTag {};
struct UnaryFunctorTag {};
struct BinaryFunctorTag {};
struct TernaryFunctorTag {};
struct UnaryAnalyserTag {};
struct BinaryAnalyserTag {};
struct TernaryAnalyserTag {};
struct UnaryReduceFunctorTag : public InitializerTag, public UnaryAnaly
serTag {};
struct BinaryReduceFunctorTag : public InitializerTag, public BinaryAna
lyserTag {};
\endcode
If a functor <tt>f</tt> is a model of these categories, it supports the following If a functor <tt>f</tt> is a model of these categories, it supports the following
calls (<tt>v</tt> is a variable such that the result type of the functo r calls (<tt>v</tt> is a variable such that the result type of the functo r
calls can be converted into <tt>v</tt>'s type, and <tt>a1, a2, a3</tt> are calls can be converted into <tt>v</tt>'s type, and <tt>a1, a2, a3</tt> are
variables convertible into the functor's argument types): variables convertible into the functor's argument types):
<DL> <DL>
<DT><b>Initializer</b> <DT><b>Initializer</b>
<DD> <tt>v = f()</tt> (used with initImageWithFunctor()) <DD> <tt>v = f()</tt> (used with initImageWithFunctor())
<DT><b>UnaryFunctor</b> <DT><b>UnaryFunctor</b>
<DD> <tt>v = f(a1)</tt> (used with transformImage()) <DD> <tt>v = f(a1)</tt> (used with transformImage())
 End of changes. 9 change blocks. 
11 lines changed or deleted 52 lines changed or added


 gaborfilter.hxx   gaborfilter.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2002-2004 by Ullrich Koethe and Hans Meine */ /* Copyright 2002-2004 by Ullrich Koethe and Hans Meine */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 123 skipping to change at line 121
\endcode \endcode
*/ */
doxygen_overloaded_function(template <...> void createGaborFilter) doxygen_overloaded_function(template <...> void createGaborFilter)
template <class DestImageIterator, class DestAccessor> template <class DestImageIterator, class DestAccessor>
void createGaborFilter(DestImageIterator destUpperLeft, void createGaborFilter(DestImageIterator destUpperLeft,
DestImageIterator destLowerRight, DestAccessor da, DestImageIterator destLowerRight, DestAccessor da,
double orientation, double centerFrequency, double orientation, double centerFrequency,
double angularSigma, double radialSigma) double angularSigma, double radialSigma)
{ {
int w= destLowerRight.x - destUpperLeft.x; int w = int(destLowerRight.x - destUpperLeft.x);
int h= destLowerRight.y - destUpperLeft.y; int h = int(destLowerRight.y - destUpperLeft.y);
double squaredSum = 0.0; double squaredSum = 0.0;
double cosTheta= VIGRA_CSTD::cos(orientation); double cosTheta= VIGRA_CSTD::cos(orientation);
double sinTheta= VIGRA_CSTD::sin(orientation); double sinTheta= VIGRA_CSTD::sin(orientation);
double radialSigma2 = radialSigma*radialSigma; double radialSigma2 = radialSigma*radialSigma;
double angularSigma2 = angularSigma*angularSigma; double angularSigma2 = angularSigma*angularSigma;
double wscale = w % 1 ? double wscale = w % 1 ?
1.0f / (w-1) : 1.0f / (w-1) :
 End of changes. 4 change blocks. 
5 lines changed or deleted 3 lines changed or added


 gaussians.hxx   gaussians.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2004 by Ullrich Koethe */ /* Copyright 1998-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 93 skipping to change at line 91
\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{x^2}{2\sigma^2}} \frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{x^2}{2\sigma^2}}
\f] \f]
Precondition: Precondition:
\code \code
sigma > 0.0 sigma > 0.0
\endcode \endcode
*/ */
explicit Gaussian(T sigma = 1.0, unsigned int derivativeOrder = 0) explicit Gaussian(T sigma = 1.0, unsigned int derivativeOrder = 0)
: sigma_(sigma), : sigma_(sigma),
sigma2_(-0.5 / sigma / sigma), sigma2_(T(-0.5 / sigma / sigma)),
norm_(0.0), norm_(0.0),
order_(derivativeOrder), order_(derivativeOrder),
hermitePolynomial_(derivativeOrder / 2 + 1) hermitePolynomial_(derivativeOrder / 2 + 1)
{ {
vigra_precondition(sigma_ > 0.0, vigra_precondition(sigma_ > 0.0,
"Gaussian::Gaussian(): sigma > 0 required."); "Gaussian::Gaussian(): sigma > 0 required.");
switch(order_) switch(order_)
{ {
case 1: case 1:
case 2: case 2:
norm_ = -1.0 / (VIGRA_CSTD::sqrt(2.0 * M_PI) * sq(sigma) * sigma); norm_ = T(-1.0 / (VIGRA_CSTD::sqrt(2.0 * M_PI) * sq(sigma) * sigma));
break; break;
case 3: case 3:
norm_ = 1.0 / (VIGRA_CSTD::sqrt(2.0 * M_PI) * sq(sigma) * s q(sigma) * sigma); norm_ = T(1.0 / (VIGRA_CSTD::sqrt(2.0 * M_PI) * sq(sigma) * sq(sigma) * sigma));
break; break;
default: default:
norm_ = 1.0 / VIGRA_CSTD::sqrt(2.0 * M_PI) / sigma; norm_ = T(1.0 / VIGRA_CSTD::sqrt(2.0 * M_PI) / sigma);
} }
calculateHermitePolynomial(); calculateHermitePolynomial();
} }
/** Function (functor) call. /** Function (functor) call.
*/ */
result_type operator()(argument_type x) const; result_type operator()(argument_type x) const;
/** Get the standard deviation of the Gaussian. /** Get the standard deviation of the Gaussian.
*/ */
skipping to change at line 156 skipping to change at line 154
template <class T> template <class T>
typename Gaussian<T>::result_type typename Gaussian<T>::result_type
Gaussian<T>::operator()(argument_type x) const Gaussian<T>::operator()(argument_type x) const
{ {
T x2 = x * x; T x2 = x * x;
T g = norm_ * VIGRA_CSTD::exp(x2 * sigma2_); T g = norm_ * VIGRA_CSTD::exp(x2 * sigma2_);
switch(order_) switch(order_)
{ {
case 0: case 0:
return g; return detail::RequiresExplicitCast<result_type>::cast(g);
case 1: case 1:
return x * g; return detail::RequiresExplicitCast<result_type>::cast(x * g);
case 2: case 2:
return (1.0 - sq(x / sigma_)) * g; return detail::RequiresExplicitCast<result_type>::cast((1.0 - s q(x / sigma_)) * g);
case 3: case 3:
return (3.0 - sq(x / sigma_)) * x * g; return detail::RequiresExplicitCast<result_type>::cast((3.0 - s q(x / sigma_)) * x * g);
default: default:
return order_ % 2 == 0 ? return order_ % 2 == 0 ?
g * horner(x2) detail::RequiresExplicitCast<result_type>::cast(g *
: x * g * horner(x2); horner(x2))
: detail::RequiresExplicitCast<result_type>::cast(x *
g * horner(x2));
} }
} }
template <class T> template <class T>
T Gaussian<T>::horner(T x) const T Gaussian<T>::horner(T x) const
{ {
int i = order_ / 2; int i = order_ / 2;
T res = hermitePolynomial_[i]; T res = hermitePolynomial_[i];
for(--i; i >= 0; --i) for(--i; i >= 0; --i)
res = x * res + hermitePolynomial_[i]; res = x * res + hermitePolynomial_[i];
skipping to change at line 189 skipping to change at line 187
template <class T> template <class T>
void Gaussian<T>::calculateHermitePolynomial() void Gaussian<T>::calculateHermitePolynomial()
{ {
if(order_ == 0) if(order_ == 0)
{ {
hermitePolynomial_[0] = 1.0; hermitePolynomial_[0] = 1.0;
} }
else if(order_ == 1) else if(order_ == 1)
{ {
hermitePolynomial_[0] = -1.0 / sigma_ / sigma_; hermitePolynomial_[0] = T(-1.0 / sigma_ / sigma_);
} }
else else
{ {
// calculate Hermite polynomial for requested derivative // calculate Hermite polynomial for requested derivative
// recursively according to // recursively according to
// (0) // (0)
// h (x) = 1 // h (x) = 1
// //
// (1) // (1)
// h (x) = -x / s^2 // h (x) = -x / s^2
// //
// (n+1) (n) (n-1) // (n+1) (n) (n-1)
// h (x) = -1 / s^2 * [ x * h (x) + n * h (x) ] // h (x) = -1 / s^2 * [ x * h (x) + n * h (x) ]
// //
T s2 = -1.0 / sigma_ / sigma_; T s2 = T(-1.0 / sigma_ / sigma_);
ArrayVector<T> hn(3*order_+3, 0.0); ArrayVector<T> hn(3*order_+3, 0.0);
typename ArrayVector<T>::iterator hn0 = hn.begin(), typename ArrayVector<T>::iterator hn0 = hn.begin(),
hn1 = hn0 + order_+1, hn1 = hn0 + order_+1,
hn2 = hn1 + order_+1, hn2 = hn1 + order_+1,
ht; ht;
hn2[0] = 1.0; hn2[0] = 1.0;
hn1[1] = s2; hn1[1] = s2;
for(unsigned int i = 2; i <= order_; ++i) for(unsigned int i = 2; i <= order_; ++i)
{ {
hn0[0] = s2 * (i-1) * hn2[0]; hn0[0] = s2 * (i-1) * hn2[0];
 End of changes. 14 change blocks. 
15 lines changed or deleted 15 lines changed or added


 gradient_energy_tensor.hxx   gradient_energy_tensor.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2004-2005 by Ullrich Koethe */ /* Copyright 2004-2005 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 imagecontainer.hxx   imagecontainer.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 imageinfo.hxx   imageinfo.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2001 by Ullrich Koethe */ /* Copyright 1998-2001 by Ullrich Koethe */
/* Copyright 2001-2002 by Gunnar Kedenburg */ /* Copyright 2001-2002 by Gunnar Kedenburg */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 60 skipping to change at line 58
#ifndef VIGRA_IMAGEINFO_HXX #ifndef VIGRA_IMAGEINFO_HXX
#define VIGRA_IMAGEINFO_HXX #define VIGRA_IMAGEINFO_HXX
#include <memory> #include <memory>
#include <string> #include <string>
#include "config.hxx" #include "config.hxx"
#include "error.hxx" #include "error.hxx"
#include "diff2d.hxx" #include "diff2d.hxx"
#include "codec.hxx" #include "codec.hxx"
#include "array_vector.hxx" #include "array_vector.hxx"
#include "multi_iterator.hxx"
namespace vigra namespace vigra
{ {
/** \addtogroup VigraImpex Image Import/Export Facilities /** \addtogroup VigraImpex Image Import/Export Facilities
supports GIF, TIFF, JPEG, BMP, PNM (PBM, PGM, PPM), PNG, SunRaster, KHO ROS-VIFF formats supports GIF, TIFF, JPEG, BMP, PNM (PBM, PGM, PPM), PNG, SunRaster, KHO ROS-VIFF formats
**/ **/
//@{ //@{
/** \brief List the image formats VIGRA can read and write. /** \brief List the image formats VIGRA can read and write.
skipping to change at line 407 skipping to change at line 406
/** Get the number of extra (non color) bands in the image. /** Get the number of extra (non color) bands in the image.
** Usually these are the alpha channels. ** Usually these are the alpha channels.
**/ **/
VIGRA_EXPORT int numExtraBands() const; VIGRA_EXPORT int numExtraBands() const;
/** Get size of the image. /** Get size of the image.
**/ **/
VIGRA_EXPORT Size2D size() const; VIGRA_EXPORT Size2D size() const;
/** Get size of the image in a form compatible to MultiArray.
**/
VIGRA_EXPORT MultiArrayShape<2>::type shape() const;
/** Returns true if the image is gray scale. /** Returns true if the image is gray scale.
**/ **/
VIGRA_EXPORT bool isGrayscale() const; VIGRA_EXPORT bool isGrayscale() const;
/** Returns true if the image is colored (RGB). /** Returns true if the image is colored (RGB).
**/ **/
VIGRA_EXPORT bool isColor() const; VIGRA_EXPORT bool isColor() const;
/** Query the pixel type of the image. /** Query the pixel type of the image.
skipping to change at line 430 skipping to change at line 433
<DT>"INT16"<DD> 16-bit signed integer (short) <DT>"INT16"<DD> 16-bit signed integer (short)
<DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short) <DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short)
<DT>"INT32"<DD> 32-bit signed integer (long) <DT>"INT32"<DD> 32-bit signed integer (long)
<DT>"UINT32"<DD> 32-bit unsigned integer (unsigned long) <DT>"UINT32"<DD> 32-bit unsigned integer (unsigned long)
<DT>"FLOAT"<DD> 32-bit floating point (float) <DT>"FLOAT"<DD> 32-bit floating point (float)
<DT>"DOUBLE"<DD> 64-bit floating point (double) <DT>"DOUBLE"<DD> 64-bit floating point (double)
</DL> </DL>
**/ **/
VIGRA_EXPORT const char * getPixelType() const; VIGRA_EXPORT const char * getPixelType() const;
/// deprecated: use getPixelType() /** Query the pixel type of the image.
Same as getPixelType(), but the result is returned as a
ImageImportInfo::PixelType enum. This is useful to implement
a switch() on the pixel type.
Possible values are:
<DL>
<DT>UINT8<DD> 8-bit unsigned integer (unsigned char)
<DT>INT16<DD> 16-bit signed integer (short)
<DT>UINT16<DD> 16-bit unsigned integer (unsigned short)
<DT>INT32<DD> 32-bit signed integer (long)
<DT>UINT32<DD> 32-bit unsigned integer (unsigned long)
<DT>FLOAT<DD> 32-bit floating point (float)
<DT>DOUBLE<DD> 64-bit floating point (double)
</DL>
**/
VIGRA_EXPORT PixelType pixelType() const; VIGRA_EXPORT PixelType pixelType() const;
/** Returns true if the image has 1 byte per pixel (gray) or /** Returns true if the image has 1 byte per pixel (gray) or
3 bytes per pixel (RGB). 3 bytes per pixel (RGB).
**/ **/
VIGRA_EXPORT bool isByte() const; VIGRA_EXPORT bool isByte() const;
/** Returns the layer offset of the current image, if there is one /** Returns the layer offset of the current image, if there is one
**/ **/
VIGRA_EXPORT Diff2D getPosition() const; VIGRA_EXPORT Diff2D getPosition() const;
 End of changes. 6 change blocks. 
4 lines changed or deleted 23 lines changed or added


 imageiterator.hxx   imageiterator.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 imageiteratoradapter.hxx   imageiteratoradapter.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 impex.hxx   impex.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2001-2002 by Gunnar Kedenburg */ /* Copyright 2001-2002 by Gunnar Kedenburg */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 61 skipping to change at line 59
\brief image import and export functions \brief image import and export functions
this file provides the declarations and implementations of importImage() this file provides the declarations and implementations of importImage()
and exportImage(). the matching implementation for the given datatype is and exportImage(). the matching implementation for the given datatype is
selected by template metacode. selected by template metacode.
*/ */
#ifndef VIGRA_IMPEX_HXX #ifndef VIGRA_IMPEX_HXX
#define VIGRA_IMPEX_HXX #define VIGRA_IMPEX_HXX
#if defined(_MSC_VER)
#pragma warning (disable: 4267)
#endif
#include "sized_int.hxx" #include "sized_int.hxx"
#include "stdimage.hxx" #include "stdimage.hxx"
#include "tinyvector.hxx" #include "tinyvector.hxx"
#include "imageinfo.hxx" #include "imageinfo.hxx"
#include "numerictraits.hxx" #include "numerictraits.hxx"
#include "codec.hxx" #include "codec.hxx"
#include "accessor.hxx" #include "accessor.hxx"
#include "inspectimage.hxx" #include "inspectimage.hxx"
#include "transformimage.hxx" #include "transformimage.hxx"
#include "copyimage.hxx" #include "copyimage.hxx"
skipping to change at line 117 skipping to change at line 111
{ {
typedef unsigned int size_type; typedef unsigned int size_type;
typedef typename ImageIterator::row_iterator DstRowIterator; typedef typename ImageIterator::row_iterator DstRowIterator;
typedef typename Accessor::value_type AccessorValueType; typedef typename Accessor::value_type AccessorValueType;
typedef typename AccessorValueType::value_type DstValueType; typedef typename AccessorValueType::value_type DstValueType;
const size_type width = dec->getWidth(); const size_type width = dec->getWidth();
const size_type height = dec->getHeight(); const size_type height = dec->getHeight();
const size_type num_bands = dec->getNumBands(); const size_type num_bands = dec->getNumBands();
vigra_precondition(num_bands == a.size(ys), vigra_precondition(num_bands == (size_type)a.size(ys),
"importImage(): number of bands (color channels) in file and des tination image differ."); "importImage(): number of bands (color channels) in file and des tination image differ.");
SrcValueType const * scanline; SrcValueType const * scanline;
// MIHAL no default constructor available for cachedfileimages. // MIHAL no default constructor available for cachedfileimages.
DstRowIterator xs = ys.rowIterator(); DstRowIterator xs = ys.rowIterator();
// iterate // iterate
if (num_bands == 4) { if (num_bands == 4) {
// Speedup for this particular case // Speedup for this particular case
unsigned int offset = dec->getOffset(); unsigned int offset = dec->getOffset();
skipping to change at line 303 skipping to change at line 297
<DT>info<DD> user supplied image import information <DT>info<DD> user supplied image import information
<DT>iter<DD> image iterator referencing the upper left pixel of the destination image <DT>iter<DD> image iterator referencing the upper left pixel of the destination image
<DT>a<DD> image accessor for the destination image <DT>a<DD> image accessor for the destination image
</DL> </DL>
*/ */
doxygen_overloaded_function(template <...> void importScalarImage) doxygen_overloaded_function(template <...> void importScalarImage)
template < class ImageIterator, class Accessor > template < class ImageIterator, class Accessor >
void importScalarImage( const ImageImportInfo & info, ImageIterator ite r, Accessor a ) void importScalarImage( const ImageImportInfo & info, ImageIterator ite r, Accessor a )
{ {
#if HAVE_UNIQUE_PTR
std::unique_ptr<Decoder> dec = decoder(info);
#else
std::auto_ptr<Decoder> dec = decoder(info); std::auto_ptr<Decoder> dec = decoder(info);
#endif
std::string pixeltype = dec->getPixelType(); std::string pixeltype = dec->getPixelType();
if ( pixeltype == "UINT8" ) if ( pixeltype == "UINT8" )
read_band( dec.get(), iter, a, (UInt8)0 ); read_band( dec.get(), iter, a, (UInt8)0 );
else if ( pixeltype == "INT16" ) else if ( pixeltype == "INT16" )
read_band( dec.get(), iter, a, Int16() ); read_band( dec.get(), iter, a, Int16() );
else if ( pixeltype == "UINT16" ) else if ( pixeltype == "UINT16" )
read_band( dec.get(), iter, a, (UInt16)0 ); read_band( dec.get(), iter, a, (UInt16)0 );
else if ( pixeltype == "INT32" ) else if ( pixeltype == "INT32" )
read_band( dec.get(), iter, a, Int32() ); read_band( dec.get(), iter, a, Int32() );
skipping to change at line 476 skipping to change at line 474
enc->setNumBands(num_bands); enc->setNumBands(num_bands);
enc->finalizeSettings(); enc->finalizeSettings();
DstValueType * scanline; DstValueType * scanline;
// iterate // iterate
ImageIterator ys(ul); ImageIterator ys(ul);
// MIHAL no default constructor available for cachedfileimages // MIHAL no default constructor available for cachedfileimages
SrcRowIterator xs = ys.rowIterator(); SrcRowIterator xs = ys.rowIterator();
if (num_bands == 4) { // Speedup for the common cases
// Speedup for this particular case switch (num_bands)
{
case 2:
{
unsigned int offset = enc->getOffset();
DstValueType * scanline0;
DstValueType * scanline1;
for( size_type y = 0; y < height; ++y, ++ys.y ) {
xs = ys.rowIterator();
scanline0 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(0));
scanline1 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(1));
for( size_type x = 0; x < width; ++x, ++xs) {
*scanline0 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 0));
*scanline1 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 1));
scanline0 += offset;
scanline1 += offset;
}
enc->nextScanline();
}
break;
}
case 3:
{
unsigned int offset = enc->getOffset();
DstValueType * scanline0;
DstValueType * scanline1;
DstValueType * scanline2;
for( size_type y = 0; y < height; ++y, ++ys.y ) {
xs = ys.rowIterator();
scanline0 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(0));
scanline1 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(1));
scanline2 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(2));
for( size_type x = 0; x < width; ++x, ++xs) {
*scanline0 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 0));
*scanline1 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 1));
*scanline2 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 2));
scanline0 += offset;
scanline1 += offset;
scanline2 += offset;
}
enc->nextScanline();
}
break;
}
case 4:
{
unsigned int offset = enc->getOffset(); unsigned int offset = enc->getOffset();
DstValueType * scanline0; DstValueType * scanline0;
DstValueType * scanline1; DstValueType * scanline1;
DstValueType * scanline2; DstValueType * scanline2;
DstValueType * scanline3; DstValueType * scanline3;
for( size_type y = 0; y < height; ++y, ++ys.y ) { for( size_type y = 0; y < height; ++y, ++ys.y ) {
xs = ys.rowIterator(); xs = ys.rowIterator();
scanline0 = static_cast< DstValueType * > scanline0 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(0)); (enc->currentScanlineOfBand(0));
scanline1 = static_cast< DstValueType * > scanline1 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(1)); (enc->currentScanlineOfBand(1));
scanline2 = static_cast< DstValueType * > scanline2 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(2)); (enc->currentScanlineOfBand(2));
scanline3 = static_cast< DstValueType * > scanline3 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(3)); (enc->currentScanlineOfBand(3));
for( size_type x = 0; x < width; ++x, ++xs) { for( size_type x = 0; x < width; ++x, ++xs) {
/*
*scanline0 = a.template getComponent<SrcRowIterator, 0>
( xs );
*scanline1 = a.template getComponent<SrcRowIterator, 1>
( xs );
*scanline2 = a.template getComponent<SrcRowIterator, 2>
( xs );
*scanline3 = a.template getComponent<SrcRowIterator, 3>
( xs );
*/
*scanline0 = detail::RequiresExplicitCast<DstValueType> ::cast(a.getComponent( xs, 0)); *scanline0 = detail::RequiresExplicitCast<DstValueType> ::cast(a.getComponent( xs, 0));
*scanline1 = detail::RequiresExplicitCast<DstValueType> ::cast(a.getComponent( xs, 1)); *scanline1 = detail::RequiresExplicitCast<DstValueType> ::cast(a.getComponent( xs, 1));
*scanline2 = detail::RequiresExplicitCast<DstValueType> ::cast(a.getComponent( xs, 2)); *scanline2 = detail::RequiresExplicitCast<DstValueType> ::cast(a.getComponent( xs, 2));
*scanline3 = detail::RequiresExplicitCast<DstValueType> ::cast(a.getComponent( xs, 3)); *scanline3 = detail::RequiresExplicitCast<DstValueType> ::cast(a.getComponent( xs, 3));
scanline0 += offset; scanline0 += offset;
scanline1 += offset; scanline1 += offset;
scanline2 += offset; scanline2 += offset;
scanline3 += offset; scanline3 += offset;
} }
enc->nextScanline(); enc->nextScanline();
} }
} break;
else { }
default:
{
// General case // General case
for( size_type y = 0; y < height; ++y, ++ys.y ) { for( size_type y = 0; y < height; ++y, ++ys.y ) {
for( size_type b = 0; b < num_bands; ++b ) { for( size_type b = 0; b < num_bands; ++b ) {
xs = ys.rowIterator(); xs = ys.rowIterator();
scanline = static_cast< DstValueType * > scanline = static_cast< DstValueType * >
(enc->currentScanlineOfBand(b)); (enc->currentScanlineOfBand(b));
for( size_type x = 0; x < width; ++x, ++xs ) { for( size_type x = 0; x < width; ++x, ++xs ) {
*scanline = detail::RequiresExplicitCast<DstValueType>: *scanline = detail::RequiresExplicitCast<DstValueTy
:cast(a.getComponent( xs, b )); pe>::cast(a.getComponent( xs, b ));
scanline += enc->getOffset(); scanline += enc->getOffset();
}
} }
enc->nextScanline();
} }
enc->nextScanline(); }
}
} }
} // write_bands() } // write_bands()
template< class MArray, class DstValueType > template< class MArray, class DstValueType >
void write_bands( Encoder * enc, MArray const & array, DstValueType) void write_bands( Encoder * enc, MArray const & array, DstValueType)
{ {
typedef unsigned int size_type; typedef unsigned int size_type;
// complete decoder settings // complete decoder settings
const size_type width = array.shape(0); const size_type width = array.shape(0);
skipping to change at line 587 skipping to change at line 633
\param a image accessor for the source image \param a image accessor for the source image
*/ */
template< class ImageIterator, class Accessor, class DstValueType > template< class ImageIterator, class Accessor, class DstValueType >
void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Acc essor a, DstValueType) void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Acc essor a, DstValueType)
{ {
typedef unsigned int size_type; typedef unsigned int size_type;
typedef typename ImageIterator::row_iterator SrcRowIterator; typedef typename ImageIterator::row_iterator SrcRowIterator;
typedef typename Accessor::value_type SrcValueType; typedef typename Accessor::value_type SrcValueType;
// complete decoder settings // complete decoder settings
const size_type width = lr.x - ul.x; const size_type width = size_type(lr.x - ul.x);
const size_type height = lr.y - ul.y; const size_type height = size_type(lr.y - ul.y);
enc->setWidth(width); enc->setWidth(width);
enc->setHeight(height); enc->setHeight(height);
enc->setNumBands(1); enc->setNumBands(1);
enc->finalizeSettings(); enc->finalizeSettings();
DstValueType * scanline; DstValueType * scanline;
// iterate // iterate
ImageIterator ys(ul); ImageIterator ys(ul);
// MIHAL no default constructor available for cachedfileimages. // MIHAL no default constructor available for cachedfileimages.
skipping to change at line 628 skipping to change at line 674
} }
// export scalar images with conversion // export scalar images with conversion
template < class SrcIterator, class SrcAccessor, class T > template < class SrcIterator, class SrcAccessor, class T >
void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sg et, void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sg et,
Encoder * enc, Encoder * enc,
const ImageExportInfo & info, const ImageExportInfo & info,
T zero) T zero)
{ {
double fromMin, fromMax, toMin, toMax; double fromMin, fromMax, toMin, toMax;
if(info.hasForcedRangeMapping()) if(info.getFromMin() < info.getFromMax())
{ {
fromMin = info.getFromMin(); fromMin = info.getFromMin();
fromMax = info.getFromMax(); fromMax = info.getFromMax();
toMin = info.getToMin();
toMax = info.getToMax();
} }
else else
{ {
typedef typename SrcAccessor::value_type SrcValue; typedef typename SrcAccessor::value_type SrcValue;
FindMinMax<SrcValue> minmax; FindMinMax<SrcValue> minmax;
inspectImage( sul, slr, sget, minmax ); inspectImage( sul, slr, sget, minmax );
fromMin = (double)minmax.min; fromMin = (double)minmax.min;
fromMax = (double)minmax.max; fromMax = (double)minmax.max;
if(fromMax <= fromMin)
fromMax = fromMin + 1.0;
}
if(info.getToMin() < info.getToMax())
{
toMin = info.getToMin();
toMax = info.getToMax();
}
else
{
toMin = (double)NumericTraits<T>::min(); toMin = (double)NumericTraits<T>::min();
toMax = (double)NumericTraits<T>::max(); toMax = (double)NumericTraits<T>::max();
} }
double scale = (toMax - toMin) / (fromMax - fromMin); double scale = (toMax - toMin) / (fromMax - fromMin);
double offset = (toMin / scale) - fromMin; double offset = (toMin / scale) - fromMin;
BasicImage<T> image(slr-sul); BasicImage<T> image(slr-sul);
transformImage( sul, slr, sget, image.upperLeft(), image.accessor() , transformImage( sul, slr, sget, image.upperLeft(), image.accessor() ,
linearIntensityTransform(scale, offset)); linearIntensityTransform(scale, offset));
write_band( enc, image.upperLeft(), write_band( enc, image.upperLeft(),
image.lowerRight(), image.accessor(), zero ); image.lowerRight(), image.accessor(), zero );
} }
// export vector images without conversion // export vector images without conversion
skipping to change at line 677 skipping to change at line 733
template < class SrcIterator, class SrcAccessor, class T > template < class SrcIterator, class SrcAccessor, class T >
void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sg et, void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sg et,
Encoder * enc, Encoder * enc,
const ImageExportInfo & info, const ImageExportInfo & info,
T zero) T zero)
{ {
unsigned int bands = sget.size(sul); unsigned int bands = sget.size(sul);
vigra_precondition(isBandNumberSupported(enc->getFileType(), bands) , vigra_precondition(isBandNumberSupported(enc->getFileType(), bands) ,
"exportImage(): file format does not support requested number of bands (color channels)"); "exportImage(): file format does not support requested number of bands (color channels)");
typedef typename SrcAccessor::value_type SrcValue; typedef typename SrcAccessor::ElementAccessor SrcElementAccessor;
typedef typename SrcElementAccessor::value_type SrcComponent;
double fromMin, fromMax, toMin, toMax; double fromMin, fromMax, toMin, toMax;
if(info.hasForcedRangeMapping()) if(info.getFromMin() < info.getFromMax())
{ {
fromMin = info.getFromMin(); fromMin = info.getFromMin();
fromMax = info.getFromMax(); fromMax = info.getFromMax();
toMin = info.getToMin();
toMax = info.getToMax();
} }
else else
{ {
typedef typename SrcValue::value_type SrcComponent;
FindMinMax<SrcComponent> minmax; FindMinMax<SrcComponent> minmax;
for(unsigned int i=0; i<bands; ++i) for(unsigned int i=0; i<bands; ++i)
{ {
VectorComponentValueAccessor<SrcValue> band(i); SrcElementAccessor band(i, sget);
inspectImage( sul, slr, band, minmax ); inspectImage( sul, slr, band, minmax );
} }
fromMin = (double)minmax.min; fromMin = (double)minmax.min;
fromMax = (double)minmax.max; fromMax = (double)minmax.max;
if(fromMax <= fromMin)
fromMax = fromMin + 1.0;
}
if(info.getToMin() < info.getToMax())
{
toMin = info.getToMin();
toMax = info.getToMax();
}
else
{
toMin = (double)NumericTraits<T>::min(); toMin = (double)NumericTraits<T>::min();
toMax = (double)NumericTraits<T>::max(); toMax = (double)NumericTraits<T>::max();
} }
double scale = (toMax - toMin) / (fromMax - fromMin); double scale = (toMax - toMin) / (fromMax - fromMin);
double offset = (toMin / scale) - fromMin; double offset = (toMin / scale) - fromMin;
int w = slr.x - sul.x; int w = slr.x - sul.x;
int h = slr.y - sul.y; int h = slr.y - sul.y;
typedef vigra::MultiArray<3, T> MArray; typedef vigra::MultiArray<3, T> MArray;
MArray array(typename MArray::difference_type(w, h, bands)); MArray array(typename MArray::difference_type(w, h, bands));
for(unsigned int i=0; i<bands; ++i) for(unsigned int i=0; i<bands; ++i)
{ {
skipping to change at line 713 skipping to change at line 778
double offset = (toMin / scale) - fromMin; double offset = (toMin / scale) - fromMin;
int w = slr.x - sul.x; int w = slr.x - sul.x;
int h = slr.y - sul.y; int h = slr.y - sul.y;
typedef vigra::MultiArray<3, T> MArray; typedef vigra::MultiArray<3, T> MArray;
MArray array(typename MArray::difference_type(w, h, bands)); MArray array(typename MArray::difference_type(w, h, bands));
for(unsigned int i=0; i<bands; ++i) for(unsigned int i=0; i<bands; ++i)
{ {
BasicImageView<T> subImage = makeBasicImageView(array.bindOuter (i)); BasicImageView<T> subImage = makeBasicImageView(array.bindOuter (i));
VectorComponentValueAccessor<SrcValue> band(i); SrcElementAccessor band(i, sget);
transformImage( sul, slr, band, subImage.upperLeft(), subImage. accessor(), transformImage( sul, slr, band, subImage.upperLeft(), subImage. accessor(),
linearIntensityTransform( scale, offset ) ); linearIntensityTransform( scale, offset ) );
} }
write_bands( enc, array, zero ); write_bands( enc, array, zero );
} }
} // namespace detail } // namespace detail
/*! /*!
\brief Deprecated. \brief Deprecated.
skipping to change at line 983 skipping to change at line 1048
} }
enc->close(); enc->close();
} }
template < class SrcIterator, class SrcAccessor > template < class SrcIterator, class SrcAccessor >
void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget, void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info, VigraTrueType /*scalar* / ) const ImageExportInfo & info, VigraTrueType /*scalar* / )
{ {
typedef typename SrcAccessor::value_type SrcValueType; typedef typename SrcAccessor::value_type SrcValueType;
std::string pixeltype = info.getPixelType(); std::string pixeltype = info.getPixelType();
#ifdef HAVE_UNIQUE_PTR
std::unique_ptr<Encoder> enc = encoder(info);
#else
std::auto_ptr<Encoder> enc = encoder(info); std::auto_ptr<Encoder> enc = encoder(info);
#endif
bool downcast = negotiatePixelType(enc->getFileType(), bool downcast = negotiatePixelType(enc->getFileType(),
TypeAsString<SrcValueType>::result(), pixeltype) ; TypeAsString<SrcValueType>::result(), pixeltype) ;
enc->setPixelType(pixeltype); enc->setPixelType(pixeltype);
if(downcast || info.hasForcedRangeMapping()) if(downcast || info.hasForcedRangeMapping())
{ {
if(pixeltype == "UINT8") if(pixeltype == "UINT8")
detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt8)0); detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt8)0);
else if(pixeltype == "INT16") else if(pixeltype == "INT16")
detail::exportScalarImage( sul, slr, sget, enc.get(), info, Int16()); detail::exportScalarImage( sul, slr, sget, enc.get(), info, Int16());
else if(pixeltype == "UINT16") else if(pixeltype == "UINT16")
 End of changes. 28 change blocks. 
46 lines changed or deleted 116 lines changed or added


 initimage.hxx   initimage.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 inspectimage.hxx   inspectimage.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 41 skipping to change at line 39
/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_INSPECTIMAGE_HXX #ifndef VIGRA_INSPECTIMAGE_HXX
#define VIGRA_INSPECTIMAGE_HXX #define VIGRA_INSPECTIMAGE_HXX
#pragma warning (disable: 4350)
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include "utilities.hxx" #include "utilities.hxx"
#include "numerictraits.hxx" #include "numerictraits.hxx"
#include "iteratortraits.hxx" #include "iteratortraits.hxx"
#include "functortraits.hxx" #include "functortraits.hxx"
#include "rgbvalue.hxx" #include "rgbvalue.hxx"
namespace vigra { namespace vigra {
skipping to change at line 284 skipping to change at line 280
<b> Usage:</b> <b> Usage:</b>
<b>\#include</b> \<<a href="inspectimage_8hxx-source.html">vigra/in spectimage.hxx</a>\><br> <b>\#include</b> \<<a href="inspectimage_8hxx-source.html">vigra/in spectimage.hxx</a>\><br>
Namespace: vigra Namespace: vigra
\code \code
vigra::BImage img(100, 100); vigra::BImage img(100, 100);
vigra::BImage mask(100, 100); vigra::BImage mask(100, 100);
// init functor // init functor
vigra::FindMinMax<vigra::BImage::PixelType> minmax(); vigra::FindMinMax<vigra::BImage::PixelType> minmax;
vigra::inspectImageIf(srcImageRange(img), vigra::inspectImageIf(srcImageRange(img),
maskImage(mask), minmax); maskImage(mask), minmax);
cout << "Min: " << minmax.min << " Max: " << minmax.max; cout << "Min: " << minmax.min << " Max: " << minmax.max;
\endcode \endcode
<b> Required Interface:</b> <b> Required Interface:</b>
skipping to change at line 806 skipping to change at line 802
template <class VALUETYPE> template <class VALUETYPE>
class FunctorTraits<FindMinMax<VALUETYPE> > class FunctorTraits<FindMinMax<VALUETYPE> >
: public FunctorTraitsBase<FindMinMax<VALUETYPE> > : public FunctorTraitsBase<FindMinMax<VALUETYPE> >
{ {
public: public:
typedef VigraTrueType isUnaryAnalyser; typedef VigraTrueType isUnaryAnalyser;
}; };
/********************************************************/ /********************************************************/
/* */ /* */
/* FindSum */
/* */
/********************************************************/
/** \brief Find the sum of the pixel values in an image or ROI.
This Functor can also be used in conjunction with
\ref ArrayOfRegionStatistics to find the sum of all regions in
a labeled image, and with the reduce mode of transformMultiArray().
<b> Traits defined:</b>
<tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitia
lizer</tt>
are true (<tt>VigraTrueType</tt>)
<b> Usage:</b>
<b>\#include</b> \<<a href="inspectimage_8hxx-source.html">vigra/in
spectimage.hxx</a>\><br>
Namespace: vigra
\code
vigra::BImage img;
vigra::FindSum<vigra::BImage::PixelType> sum; // init functor
vigra::inspectImage(srcImageRange(img), sum);
cout << "Sum: " << sum();
\endcode
<b> Required Interface:</b>
\code
VALUETYPE v1, v2(v1);
v1 += v2;
\endcode
*/
template <class VALUETYPE>
class FindSum
: public UnaryReduceFunctorTag
{
public:
/** the functor's argument type
*/
typedef VALUETYPE argument_type;
/** the functor's result type
*/
typedef typename NumericTraits<VALUETYPE>::Promote result_type;
/** init sum
*/
FindSum()
: sum_(NumericTraits<result_type>::zero())
{}
/** (re-)init sum
*/
void reset()
{
sum_ = NumericTraits<result_type>::zero();
}
/** update sum
*/
void operator()(argument_type const & v)
{
sum_ += v;
}
/** merge two statistics
*/
void operator()(FindSum const & v)
{
sum_ += v.sum_;
}
/** return current sum
*/
result_type sum() const
{
return sum_;
}
/** return current sum
*/
result_type operator()() const
{
return sum_;
}
result_type sum_;
};
/********************************************************/
/* */
/* FindAverage */ /* FindAverage */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Find the average pixel value in an image or ROI. /** \brief Find the average pixel value in an image or ROI.
In addition the size of the ROI is calculated. In addition the size of the ROI is calculated.
This Functor can also be used in conjunction with This Functor can also be used in conjunction with
\ref ArrayOfRegionStatistics to find the average of all regions in \ref ArrayOfRegionStatistics to find the average of all regions in
a labeled image. a labeled image.
 End of changes. 6 change blocks. 
6 lines changed or deleted 104 lines changed or added


 interpolating_accessor.hxx   interpolating_accessor.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 iteratoradapter.hxx   iteratoradapter.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 iteratortags.hxx   iteratortags.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2003 by Ullrich Koethe */ /* Copyright 1998-2003 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 iteratortraits.hxx   iteratortraits.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 labelimage.hxx   labelimage.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 45 skipping to change at line 43
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_LABELIMAGE_HXX #ifndef VIGRA_LABELIMAGE_HXX
#define VIGRA_LABELIMAGE_HXX #define VIGRA_LABELIMAGE_HXX
#include <vector> #include <vector>
#include <functional> #include <functional>
#include "utilities.hxx" #include "utilities.hxx"
#include "stdimage.hxx" #include "stdimage.hxx"
#include "union_find.hxx"
#include "sized_int.hxx"
namespace vigra { namespace vigra {
/** \addtogroup Labeling Connected Components Labeling /** \addtogroup Labeling Connected Components Labeling
The 2-dimensional connected components algorithms may use either 4 or 8 connectivity. The 2-dimensional connected components algorithms may use either 4 or 8 connectivity.
By means of a functor the merge criterium can be defined arbitrarily. By means of a functor the merge criterium can be defined arbitrarily.
*/ */
//@{ //@{
/********************************************************/ /********************************************************/
skipping to change at line 164 skipping to change at line 164
doxygen_overloaded_function(template <...> unsigned int labelImage) doxygen_overloaded_function(template <...> unsigned int labelImage)
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class EqualityFunctor> class EqualityFunctor>
unsigned int labelImage(SrcIterator upperlefts, unsigned int labelImage(SrcIterator upperlefts,
SrcIterator lowerrights, SrcAccessor sa, SrcIterator lowerrights, SrcAccessor sa,
DestIterator upperleftd, DestAccessor da, DestIterator upperleftd, DestAccessor da,
bool eight_neighbors, EqualityFunctor equal) bool eight_neighbors, EqualityFunctor equal)
{ {
typedef typename DestAccessor::value_type LabelType;
int w = lowerrights.x - upperlefts.x; int w = lowerrights.x - upperlefts.x;
int h = lowerrights.y - upperlefts.y; int h = lowerrights.y - upperlefts.y;
int x,y,i; int x,y,i;
static const Diff2D neighbor[] = { static const Diff2D neighbor[] = {
Diff2D(-1,0), // left Diff2D(-1,0), // left
Diff2D(-1,-1), // topleft Diff2D(-1,-1), // topleft
Diff2D(0,-1), // top Diff2D(0,-1), // top
Diff2D(1,-1) // topright Diff2D(1,-1) // topright
}; };
static const int left = 0, /* unused: topleft = 1, */ top = 2, toprigh t = 3; static const int left = 0, /* unused: topleft = 1, */ top = 2, toprigh t = 3;
int step = eight_neighbors ? 1 : 2; int step = eight_neighbors ? 1 : 2;
SrcIterator ys(upperlefts); SrcIterator ys = upperlefts;
SrcIterator xs(ys); DestIterator yd = upperleftd;
// temporary image to store region labels
IImage labelimage(w, h);
IImage::Iterator yt = labelimage.upperLeft();
IImage::Iterator xt(yt);
// Kovalevsky's clever idea to use detail::UnionFindArray<LabelType> label;
// image iterator and scan order iterator simultaneously
IImage::ScanOrderIterator label = labelimage.begin();
// pass 1: scan image from upper left to lower right // pass 1: scan image from upper left to lower right
// to find connected components // to find connected components
// Each component will be represented by a tree of pixels. Each // Each component will be represented by a tree of pixels. Each
// pixel contains the scan order address of its parent in the // pixel contains the scan order address of its parent in the
// tree. In order for pass 2 to work correctly, the parent must // tree. In order for pass 2 to work correctly, the parent must
// always have a smaller scan order address than the child. // always have a smaller scan order address than the child.
// Therefore, we can merge trees only at their roots, because the // Therefore, we can merge trees only at their roots, because the
// root of the combined tree must have the smallest scan order // root of the combined tree must have the smallest scan order
// address among all the tree's pixels/ nodes. The root of each // address among all the tree's pixels/ nodes. The root of each
// tree is distinguished by pointing to itself (it contains its // tree is distinguished by pointing to itself (it contains its
// own scan order address). This condition is enforced whenever a // own scan order address). This condition is enforced whenever a
// new region is found or two regions are merged // new region is found or two regions are merged
for(y = 0; y != h; ++y, ++ys.y, ++yt.y) for(y = 0; y != h; ++y, ++ys.y, ++yd.y)
{ {
xs = ys; SrcIterator xs = ys;
xt = yt; DestIterator xd = yd;
int endNeighbor = (y == 0) ? left : (eight_neighbors ? topright : t op); int endNeighbor = (y == 0) ? left : (eight_neighbors ? topright : t op);
for(x = 0; x != w; ++x, ++xs.x, ++xt.x) for(x = 0; x != w; ++x, ++xs.x, ++xd.x)
{ {
int beginNeighbor = (x == 0) ? top : left; int beginNeighbor = (x == 0) ? top : left;
if(x == w-1 && endNeighbor == topright) endNeighbor = top; if(x == w-1 && endNeighbor == topright) endNeighbor = top;
for(i=beginNeighbor; i<=endNeighbor; i+=step) for(i=beginNeighbor; i<=endNeighbor; i+=step)
{ {
if(equal(sa(xs), sa(xs, neighbor[i]))) if(equal(sa(xs), sa(xs, neighbor[i])))
{ {
int neighborLabel = xt[neighbor[i]]; LabelType neighborLabel = label.find(da(xd,neighbor[i]) );
for(int j=i+2; j<=endNeighbor; j+=step) for(int j=i+2; j<=endNeighbor; j+=step)
{ {
if(equal(sa(xs), sa(xs, neighbor[j]))) if(equal(sa(xs), sa(xs, neighbor[j])))
{ {
int neighborLabel1 = xt[neighbor[j]]; neighborLabel = label.makeUnion(da(xd, neighbor
[j]), neighborLabel);
if(neighborLabel != neighborLabel1)
{
// find roots of the region trees
while(neighborLabel != label[neighborLabel]
)
{
neighborLabel = label[neighborLabel];
}
while(neighborLabel1 != label[neighborLabel
1])
{
neighborLabel1 = label[neighborLabel1];
}
// merge the trees
if(neighborLabel1 < neighborLabel)
{
label[neighborLabel] = neighborLabel1;
neighborLabel = neighborLabel1;
}
else if(neighborLabel < neighborLabel1)
{
label[neighborLabel1] = neighborLabel;
}
}
break; break;
} }
} }
*xt = neighborLabel; da.set(neighborLabel, xd);
break; break;
} }
} }
if(i > endNeighbor) if(i > endNeighbor)
{ {
// new region da.set(label.makeNewLabel(), xd);
// The initial label of a new region equals the
// scan order address of it's first pixel.
// This is essential for correct operation of the algorithm
.
*xt = x + y*w;
} }
} }
} }
// pass 2: assign one label to each region (tree) // pass 2: assign one label to each region (tree)
// so that labels form a consecutive sequence 1, 2, ... // so that labels form a consecutive sequence 1, 2, ...
DestIterator yd(upperleftd); unsigned int count = label.makeContiguous();
unsigned int count = 0; yd = upperleftd;
i = 0;
for(y=0; y != h; ++y, ++yd.y) for(y=0; y != h; ++y, ++yd.y)
{ {
DestIterator xd(yd); typename DestIterator::row_iterator xd = yd.rowIterator();
for(x = 0; x != w; ++x, ++xd.x, ++i) for(x = 0; x != w; ++x, ++xd)
{ {
if(label[i] == i) da.set(label[da(xd)], xd);
{
label[i] = ++count;
}
else
{
label[i] = label[label[i]];
}
da.set(label[i], xd);
} }
} }
return count; return count;
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class EqualityFunctor> class EqualityFunctor>
inline inline
unsigned int labelImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, unsigned int labelImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
skipping to change at line 478 skipping to change at line 435
Diff2D(1,-1) // topright Diff2D(1,-1) // topright
}; };
static const int left = 0, /* unused: topleft = 1,*/ top = 2, topright = 3; static const int left = 0, /* unused: topleft = 1,*/ top = 2, topright = 3;
int step = eight_neighbors ? 1 : 2; int step = eight_neighbors ? 1 : 2;
SrcIterator ys(upperlefts); SrcIterator ys(upperlefts);
SrcIterator xs(ys); SrcIterator xs(ys);
// temporary image to store region labels // temporary image to store region labels
IImage labelimage(w, h); typedef BasicImage<IntBiggest> TmpImage;
IImage::ScanOrderIterator label = labelimage.begin(); TmpImage labelimage(w, h);
IImage::Iterator yt = labelimage.upperLeft(); TmpImage::ScanOrderIterator label = labelimage.begin();
IImage::Iterator xt(yt); TmpImage::Iterator yt = labelimage.upperLeft();
TmpImage::Iterator xt(yt);
// pass 1: scan image from upper left to lower right // pass 1: scan image from upper left to lower right
// find connected components // find connected components
for(y = 0; y != h; ++y, ++ys.y, ++yt.y) for(y = 0; y != h; ++y, ++ys.y, ++yt.y)
{ {
xs = ys; xs = ys;
xt = yt; xt = yt;
int endNeighbor = (y == 0) ? left : (eight_neighbors ? topright : t op); int endNeighbor = (y == 0) ? left : (eight_neighbors ? topright : t op);
skipping to change at line 508 skipping to change at line 466
} }
else else
{ {
int beginNeighbor = (x == 0) ? top : left; int beginNeighbor = (x == 0) ? top : left;
if(x == w-1 && endNeighbor == topright) endNeighbor = top; if(x == w-1 && endNeighbor == topright) endNeighbor = top;
for(i=beginNeighbor; i<=endNeighbor; i+=step) for(i=beginNeighbor; i<=endNeighbor; i+=step)
{ {
if(equal(sa(xs), sa(xs, neighbor[i]))) if(equal(sa(xs), sa(xs, neighbor[i])))
{ {
int neighborLabel = xt[neighbor[i]]; IntBiggest neighborLabel = xt[neighbor[i]];
for(int j=i+2; j<=endNeighbor; j+=step) for(int j=i+2; j<=endNeighbor; j+=step)
{ {
if(equal(sa(xs), sa(xs, neighbor[j]))) if(equal(sa(xs), sa(xs, neighbor[j])))
{ {
int neighborLabel1 = xt[neighbor[j]]; IntBiggest neighborLabel1 = xt[neighbor[j]] ;
if(neighborLabel != neighborLabel1) if(neighborLabel != neighborLabel1)
{ {
// find roots of the region trees // find roots of the region trees
while(neighborLabel != label[neighborLa bel]) while(neighborLabel != label[neighborLa bel])
{ {
neighborLabel = label[neighborLabel ]; neighborLabel = label[neighborLabel ];
} }
while(neighborLabel1 != label[neighborL abel1]) while(neighborLabel1 != label[neighborL abel1])
{ {
 End of changes. 21 change blocks. 
73 lines changed or deleted 29 lines changed or added


 labelvolume.hxx   labelvolume.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2006-2007 by F. Heinrich, B. Seppke, Ullrich Koethe */ /* Copyright 2006-2007 by F. Heinrich, B. Seppke, Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 43 skipping to change at line 41
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_LABELVOLUME_HXX #ifndef VIGRA_LABELVOLUME_HXX
#define VIGRA_LABELVOLUME_HXX #define VIGRA_LABELVOLUME_HXX
#include "voxelneighborhood.hxx" #include "voxelneighborhood.hxx"
#include "multi_array.hxx" #include "multi_array.hxx"
#include "union_find.hxx"
namespace vigra{ namespace vigra{
/** \addtogroup Labeling Connected Components Labeling /** \addtogroup Labeling Connected Components Labeling
The 3-dimensional connected components algorithms may use either 6 or 26 connectivity. The 3-dimensional connected components algorithms may use either 6 or 26 connectivity.
By means of a functor the merge criterium can be defined arbitrarily. By means of a functor the merge criterium can be defined arbitrarily.
*/ */
//@{ //@{
/********************************************************/ /********************************************************/
skipping to change at line 205 skipping to change at line 204
return labelVolume(src.first, src.second, src.third, dest.first, dest.s econd, neighborhood3D, equal); return labelVolume(src.first, src.second, src.third, dest.first, dest.s econd, neighborhood3D, equal);
} }
template <class SrcIterator, class SrcAccessor,class SrcShape, template <class SrcIterator, class SrcAccessor,class SrcShape,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class Neighborhood3D, class EqualityFunctor> class Neighborhood3D, class EqualityFunctor>
unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa, unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa,
DestIterator d_Iter, DestAccessor da, DestIterator d_Iter, DestAccessor da,
Neighborhood3D, EqualityFunctor equal) Neighborhood3D, EqualityFunctor equal)
{ {
typedef typename DestAccessor::value_type LabelType;
//basically needed for iteration and border-checks //basically needed for iteration and border-checks
int w = srcShape[0], h = srcShape[1], d = srcShape[2]; int w = srcShape[0], h = srcShape[1], d = srcShape[2];
int x,y,z, i; int x,y,z;
//declare and define Iterators for all three dims at src
SrcIterator zs = s_Iter;
SrcIterator ys(zs);
SrcIterator xs(ys);
// temporary image to store region labels // temporary image to store region labels
typedef vigra::MultiArray<3,int> LabelVolume; detail::UnionFindArray<LabelType> label;
typedef LabelVolume::traverser LabelTraverser;
LabelVolume labelvolume(srcShape);
//Declare traversers for all three dims at target //Declare traversers for all three dims at target
LabelTraverser zt = labelvolume.traverser_begin(); SrcIterator zs = s_Iter;
LabelTraverser yt(zt); DestIterator zd = d_Iter;
LabelTraverser xt(yt);
// Kovalevsky's clever idea to use
// image iterator and scan order iterator simultaneously
// memory order indicates label
LabelVolume::iterator label = labelvolume.begin();
// initialize the neighborhood traversers // initialize the neighborhood traversers
#if 0
NeighborOffsetTraverser<Neighborhood3D> nc(Neighborhood3D::CausalFirst)
;
NeighborOffsetTraverser<Neighborhood3D> nce(Neighborhood3D::CausalLast)
;
#endif /* #if 0 */
NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhood3D::CausalFirst
);
NeighborOffsetCirculator<Neighborhood3D> nce(Neighborhood3D::CausalLast ); NeighborOffsetCirculator<Neighborhood3D> nce(Neighborhood3D::CausalLast );
++nce; ++nce;
// pass 1: scan image from upper left front to lower right back // pass 1: scan image from upper left front to lower right back
// to find connected components // to find connected components
// Each component will be represented by a tree of pixels. Each // Each component will be represented by a tree of pixels. Each
// pixel contains the scan order address of its parent in the // pixel contains the scan order address of its parent in the
// tree. In order for pass 2 to work correctly, the parent must // tree. In order for pass 2 to work correctly, the parent must
// always have a smaller scan order address than the child. // always have a smaller scan order address than the child.
// Therefore, we can merge trees only at their roots, because the // Therefore, we can merge trees only at their roots, because the
// root of the combined tree must have the smallest scan order // root of the combined tree must have the smallest scan order
// address among all the tree's pixels/ nodes. The root of each // address among all the tree's pixels/ nodes. The root of each
// tree is distinguished by pointing to itself (it contains its // tree is distinguished by pointing to itself (it contains its
// own scan order address). This condition is enforced whenever a // own scan order address). This condition is enforced whenever a
// new region is found or two regions are merged // new region is found or two regions are merged
i=0; for(z = 0; z != d; ++z, ++zs.dim2(), ++zd.dim2())
for(z = 0; z != d; ++z, ++zs.dim2(), ++zt.dim2())
{ {
ys = zs; SrcIterator ys(zs);
yt = zt; DestIterator yd(zd);
for(y = 0; y != h; ++y, ++ys.dim1(), ++yt.dim1()) for(y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1())
{ {
xs = ys; SrcIterator xs(ys);
xt = yt; DestIterator xd(yd);
for(x = 0; x != w; ++x, ++xs.dim0(), ++xt.dim0(), ++i) for(x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0())
{ {
*xt = i; // default: new region LabelType currentLabel = label.nextFreeLabel();
//queck whether there is a special borde threatment to be u sed or not //queck whether there is a special border treatment to be u sed or not
AtVolumeBorder atBorder = isAtVolumeBorderCausal(x,y,z,w,h, z); AtVolumeBorder atBorder = isAtVolumeBorderCausal(x,y,z,w,h, z);
//We are not at the border! //We are not at the border!
if(atBorder == NotAtBorder) if(atBorder == NotAtBorder)
{ {
NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhoo
#if 0 d3D::CausalFirst);
nc = NeighborOffsetTraverser<Neighborhood3D>(Neighborho
od3D::CausalFirst);
#endif /* #if 0 */
nc = NeighborOffsetCirculator<Neighborhood3D>(Neighborh
ood3D::CausalFirst);
do do
{ {
// if colors are equal // if colors are equal
if(equal(*xs, xs[*nc])) if(equal(sa(xs), sa(xs, *nc)))
{ {
int neighborLabel = xt[*nc]; currentLabel = label.makeUnion(label[da(xd,*nc)
], currentLabel);
// find the root label of a label tree
while(neighborLabel != label[neighborLabel])
{
neighborLabel = label[neighborLabel];
}
if(neighborLabel < *xt) // always keep the smal
lest among the possible neighbor labels
{
label[*xt] = neighborLabel;
*xt = neighborLabel;
}
else
{
label[neighborLabel] = *xt;
}
} }
++nc; ++nc;
}while(nc!=nce); }
while(nc!=nce);
} }
//we are at a border - handle this!! else //we are at a border - handle this!!
else
{ {
NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhoo
#if 0 d3D::nearBorderDirectionsCausal(atBorder,0));
nc = NeighborOffsetTraverser<Neighborhood3D>(Neighborho
od3D::nearBorderDirectionsCausal(atBorder,0));
#endif /* #if 0 */
nc = NeighborOffsetCirculator<Neighborhood3D>(Neighborh
ood3D::nearBorderDirectionsCausal(atBorder,0));
int j=0; int j=0;
while(nc.direction() != Neighborhood3D::Error) while(nc.direction() != Neighborhood3D::Error)
{ {
// colors equal??? // colors equal???
if(equal(*xs, xs[*nc])) if(equal(sa(xs), sa(xs, *nc)))
{ {
int neighborLabel = xt[*nc]; currentLabel = label.makeUnion(label[da(xd,*nc)
], currentLabel);
// find the root label of a label tree
while(neighborLabel != label[neighborLabel])
{
neighborLabel = label[neighborLabel];
}
if(neighborLabel < *xt) // always keep the smal
lest among the possible neighbor labels
{
label[*xt] = neighborLabel;
*xt = neighborLabel;
}
else
{
label[neighborLabel] = *xt;
}
} }
nc.turnTo(Neighborhood3D::nearBorderDirectionsCausa l(atBorder,++j)); nc.turnTo(Neighborhood3D::nearBorderDirectionsCausa l(atBorder,++j));
} }
} }
da.set(label.finalizeLabel(currentLabel), xd);
} }
} }
} }
LabelType count = label.makeContiguous();
// pass 2: assign one label to each region (tree) // pass 2: assign one label to each region (tree)
// so that labels form a consecutive sequence 1, 2, ... // so that labels form a consecutive sequence 1, 2, ...
DestIterator zd = d_Iter; zd = d_Iter;
unsigned int count = 0;
i= 0;
for(z=0; z != d; ++z, ++zd.dim2()) for(z=0; z != d; ++z, ++zd.dim2())
{ {
DestIterator yd(zd); DestIterator yd(zd);
for(y=0; y != h; ++y, ++yd.dim1()) for(y=0; y != h; ++y, ++yd.dim1())
{ {
DestIterator xd(yd); DestIterator xd(yd);
for(x = 0; x != w; ++x, ++xd.dim0(), ++i) for(x = 0; x != w; ++x, ++xd.dim0())
{ {
if(label[i] == i) da.set(label[da(xd)], xd);
{
label[i] = count++;
}
else
{
label[i] = label[label[i]]; // compress trees
}
da.set(label[i]+1, xd);
} }
} }
} }
return count; return count;
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* labelVolumeSix */ /* labelVolumeSix */
/* */ /* */
skipping to change at line 552 skipping to change at line 478
template <class SrcIterator, class SrcAccessor,class SrcShape, template <class SrcIterator, class SrcAccessor,class SrcShape,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class Neighborhood3D, class Neighborhood3D,
class ValueType, class EqualityFunctor> class ValueType, class EqualityFunctor>
unsigned int labelVolumeWithBackground(SrcIterator s_Iter, SrcShape srcShap e, SrcAccessor sa, unsigned int labelVolumeWithBackground(SrcIterator s_Iter, SrcShape srcShap e, SrcAccessor sa,
DestIterator d_Iter, DestAccessor da , DestIterator d_Iter, DestAccessor da ,
Neighborhood3D, Neighborhood3D,
ValueType backgroundValue, EqualityF unctor equal) ValueType backgroundValue, EqualityF unctor equal)
{ {
typedef typename DestAccessor::value_type LabelType;
//basically needed for iteration and border-checks //basically needed for iteration and border-checks
int w = srcShape[0], h = srcShape[1], d = srcShape[2]; int w = srcShape[0], h = srcShape[1], d = srcShape[2];
int x,y,z, i; int x,y,z;
//declare and define Iterators for all three dims at src
SrcIterator zs = s_Iter;
SrcIterator ys(zs);
SrcIterator xs(ys);
// temporary image to store region labels // temporary image to store region labels
typedef vigra::MultiArray<3,int> LabelVolume; detail::UnionFindArray<LabelType> label;
typedef LabelVolume::traverser LabelTraverser;
LabelVolume labelvolume(srcShape);
//Declare traversers for all three dims at target //Declare traversers for all three dims at target
LabelTraverser zt = labelvolume.traverser_begin(); SrcIterator zs = s_Iter;
LabelTraverser yt(zt); DestIterator zd = d_Iter;
LabelTraverser xt(yt);
// Kovalevsky's clever idea to use
// image iterator and scan order iterator simultaneously
// memory order indicates label
LabelVolume::iterator label = labelvolume.begin();
// initialize the neighborhood traversers // initialize the neighborhood traversers
#if 0
NeighborOffsetTraverser<Neighborhood3D> nc(Neighborhood3D::CausalFirst)
;
NeighborOffsetTraverser<Neighborhood3D> nce(Neighborhood3D::CausalLast)
;
#endif /* #if 0 */
NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhood3D::CausalFirst
);
NeighborOffsetCirculator<Neighborhood3D> nce(Neighborhood3D::CausalLast ); NeighborOffsetCirculator<Neighborhood3D> nce(Neighborhood3D::CausalLast );
++nce; ++nce;
// pass 1: scan image from upper left front to lower right back // pass 1: scan image from upper left front to lower right back
// to find connected components // to find connected components
// Each component will be represented by a tree of pixels. Each // Each component will be represented by a tree of pixels. Each
// pixel contains the scan order address of its parent in the // pixel contains the scan order address of its parent in the
// tree. In order for pass 2 to work correctly, the parent must // tree. In order for pass 2 to work correctly, the parent must
// always have a smaller scan order address than the child. // always have a smaller scan order address than the child.
// Therefore, we can merge trees only at their roots, because the // Therefore, we can merge trees only at their roots, because the
// root of the combined tree must have the smallest scan order // root of the combined tree must have the smallest scan order
// address among all the tree's pixels/ nodes. The root of each // address among all the tree's pixels/ nodes. The root of each
// tree is distinguished by pointing to itself (it contains its // tree is distinguished by pointing to itself (it contains its
// own scan order address). This condition is enforced whenever a // own scan order address). This condition is enforced whenever a
// new region is found or two regions are merged // new region is found or two regions are merged
i=0; for(z = 0; z != d; ++z, ++zs.dim2(), ++zd.dim2())
int backgroundAddress=-1;
for(z = 0; z != d; ++z, ++zs.dim2(), ++zt.dim2())
{ {
ys = zs; SrcIterator ys(zs);
yt = zt; DestIterator yd(zd);
for(y = 0; y != h; ++y, ++ys.dim1(), ++yt.dim1()) for(y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1())
{ {
xs = ys; SrcIterator xs(ys);
xt = yt; DestIterator xd(yd);
for(x = 0; x != w; ++x, ++xs.dim0(), ++xt.dim0(), ++i) for(x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0())
{ {
if(equal(*xs, backgroundValue)){ if(equal(sa(xs), backgroundValue))
if(backgroundAddress==-1) backgroundAddress = i; {
label[i]=backgroundAddress; da.set(label[0], xd);
continue;
} }
else{
*xt = i; // default: new region
//queck whether there is a special borde threatment to
be used or not
AtVolumeBorder atBorder = isAtVolumeBorderCausal(x,y,z,
w,h,z);
//We are not at the border! LabelType currentLabel = label.nextFreeLabel();
if(atBorder == NotAtBorder)
{
#if 0 //queck whether there is a special border treatment to be u
nc = NeighborOffsetTraverser<Neighborhood3D>(Neighb sed or not
orhood3D::CausalFirst); AtVolumeBorder atBorder = isAtVolumeBorderCausal(x,y,z,w,h,
#endif /* #if 0 */ z);
nc = NeighborOffsetCirculator<Neighborhood3D>(Neigh //We are not at the border!
borhood3D::CausalFirst); if(atBorder == NotAtBorder)
{
NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhoo
d3D::CausalFirst);
do do
{
// if colors are equal
if(equal(sa(xs), sa(xs, *nc)))
{ {
// if colors are equal currentLabel = label.makeUnion(label[da(xd,*nc)
if(equal(*xs, xs[*nc])) ], currentLabel);
{ }
int neighborLabel = xt[*nc]; ++nc;
// find the root label of a label tree
while(neighborLabel != label[neighborLabel]
)
{
neighborLabel = label[neighborLabel];
}
if(neighborLabel < *xt) // always keep the
smallest among the possible neighbor labels
{
label[*xt] = neighborLabel;
*xt = neighborLabel;
}
else
{
label[neighborLabel] = *xt;
}
}
++nc;
}while(nc!=nce);
} }
//we are at a border - handle this!! while(nc!=nce);
else }
else //we are at a border - handle this!!
{
NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhoo
d3D::nearBorderDirectionsCausal(atBorder,0));
int j=0;
while(nc.direction() != Neighborhood3D::Error)
{ {
// colors equal???
#if 0 if(equal(sa(xs), sa(xs, *nc)))
nc = NeighborOffsetTraverser<Neighborhood3D>(Neighb
orhood3D::nearBorderDirectionsCausal(atBorder,0));
#endif /* #if 0 */
nc = NeighborOffsetCirculator<Neighborhood3D>(Neigh
borhood3D::nearBorderDirectionsCausal(atBorder,0));
int j=0;
while(nc.direction() != Neighborhood3D::Error)
{ {
// colors equal??? currentLabel = label.makeUnion(label[da(xd,*nc)
if(equal(*xs, xs[*nc])) ], currentLabel);
{
int neighborLabel = xt[*nc];
// find the root label of a label tree
while(neighborLabel != label[neighborLabel]
)
{
neighborLabel = label[neighborLabel];
}
if(neighborLabel < *xt) // always keep the
smallest among the possible neighbor labels
{
label[*xt] = neighborLabel;
*xt = neighborLabel;
}
else
{
label[neighborLabel] = *xt;
}
}
nc.turnTo(Neighborhood3D::nearBorderDirectionsC
ausal(atBorder,++j));
} }
nc.turnTo(Neighborhood3D::nearBorderDirectionsCausa l(atBorder,++j));
} }
} }
da.set(label.finalizeLabel(currentLabel), xd);
} }
} }
} }
LabelType count = label.makeContiguous();
// pass 2: assign one label to each region (tree) // pass 2: assign one label to each region (tree)
// so that labels form a consecutive sequence 1, 2, ... // so that labels form a consecutive sequence 1, 2, ...
DestIterator zd = d_Iter; zd = d_Iter;
unsigned int count = 0;
i= 0;
for(z=0; z != d; ++z, ++zd.dim2()) for(z=0; z != d; ++z, ++zd.dim2())
{ {
DestIterator yd(zd); DestIterator yd(zd);
for(y=0; y != h; ++y, ++yd.dim1()) for(y=0; y != h; ++y, ++yd.dim1())
{ {
DestIterator xd(yd); DestIterator xd(yd);
for(x = 0; x != w; ++x, ++xd.dim0(), ++i) for(x = 0; x != w; ++x, ++xd.dim0())
{ {
if(label[i] == backgroundAddress){ da.set(label[da(xd)], xd);
label[i]=0;
continue;
}
if(label[i] == i)
{
label[i] = count++;
}
else
{
label[i] = label[label[i]]; // compress trees
}
da.set(label[i]+1, xd);
} }
} }
} }
return count; return count;
} }
//@} //@}
} //end of namespace vigra } //end of namespace vigra
 End of changes. 55 change blocks. 
254 lines changed or deleted 88 lines changed or added


 linear_algebra.hxx   linear_algebra.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2004 by Ullrich Koethe */ /* Copyright 2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 linear_solve.hxx   linear_solve.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2003-2008 by Gunnar Kedenburg and Ullrich Koethe */ /* Copyright 2003-2008 by Gunnar Kedenburg and Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 154 skipping to change at line 152
return false; // no reflection needed return false; // no reflection needed
givensCoefficients(a, b, g(0,0), g(0,1)); givensCoefficients(a, b, g(0,0), g(0,1));
g(1,1) = -g(0,0); g(1,1) = -g(0,0);
g(1,0) = g(0,1); g(1,0) = g(0,1);
return true; return true;
} }
// see Golub, van Loan: Algorithm 5.2.2 (p. 227) and Section 12.5.2 (p. 608 ) // see Golub, van Loan: Algorithm 5.2.2 (p. 227) and Section 12.5.2 (p. 608 )
template <class T, class C1, class C2> template <class T, class C1, class C2>
bool bool
qrGivensStepImpl(MultiArrayIndex i, MultiArrayView<2, T, C1> &r, MultiArray View<2, T, C2> &rhs) qrGivensStepImpl(MultiArrayIndex i, MultiArrayView<2, T, C1> r, MultiArrayV iew<2, T, C2> rhs)
{ {
typedef typename Matrix<T>::difference_type Shape; typedef typename Matrix<T>::difference_type Shape;
const MultiArrayIndex m = rowCount(r); const MultiArrayIndex m = rowCount(r);
const MultiArrayIndex n = columnCount(r); const MultiArrayIndex n = columnCount(r);
const MultiArrayIndex rhsCount = columnCount(rhs); const MultiArrayIndex rhsCount = columnCount(rhs);
vigra_precondition(m == rowCount(rhs), vigra_precondition(m == rowCount(rhs),
"qrGivensStepImpl(): Matrix shape mismatch."); "qrGivensStepImpl(): Matrix shape mismatch.");
Matrix<T> givens(2,2); Matrix<T> givens(2,2);
skipping to change at line 362 skipping to change at line 360
void void
incrementalMaxSingularValueApproximation(MultiArrayView<2, T, C1> const & n ewColumn, incrementalMaxSingularValueApproximation(MultiArrayView<2, T, C1> const & n ewColumn,
MultiArrayView<2, T, C2> & z, SNTy pe & v) MultiArrayView<2, T, C2> & z, SNTy pe & v)
{ {
typedef typename Matrix<T>::difference_type Shape; typedef typename Matrix<T>::difference_type Shape;
MultiArrayIndex n = rowCount(newColumn) - 1; MultiArrayIndex n = rowCount(newColumn) - 1;
SNType vneu = squaredNorm(newColumn); SNType vneu = squaredNorm(newColumn);
T yv = dot(columnVector(newColumn, Shape(0,0),n), columnVector(z, Shape (0,0),n)); T yv = dot(columnVector(newColumn, Shape(0,0),n), columnVector(z, Shape (0,0),n));
// use atan2 as it is robust against overflow/underflow // use atan2 as it is robust against overflow/underflow
double t = 0.5*std::atan2(2.0*yv, sq(v)-vneu), T t = 0.5*std::atan2(T(2.0*yv), T(sq(v)-vneu)),
s = std::sin(t), s = std::sin(t),
c = std::cos(t); c = std::cos(t);
v = std::sqrt(sq(c*v) + sq(s)*vneu + 2.0*s*c*yv); v = std::sqrt(sq(c*v) + sq(s)*vneu + 2.0*s*c*yv);
columnVector(z, Shape(0,0),n) = c*columnVector(z, Shape(0,0),n) + s*col umnVector(newColumn, Shape(0,0),n); columnVector(z, Shape(0,0),n) = c*columnVector(z, Shape(0,0),n) + s*col umnVector(newColumn, Shape(0,0),n);
z(n,0) = s*newColumn(n,0); z(n,0) = s*newColumn(n,0);
} }
// O(n) algorithm due to Bischof: Incremental Condition Estimation, 1990 // O(n) algorithm due to Bischof: Incremental Condition Estimation, 1990
template <class T, class C1, class C2, class SNType> template <class T, class C1, class C2, class SNType>
void void
incrementalMinSingularValueApproximation(MultiArrayView<2, T, C1> const & n ewColumn, incrementalMinSingularValueApproximation(MultiArrayView<2, T, C1> const & n ewColumn,
MultiArrayView<2, T, C2> & z, SNTy pe & v, double tolerance) MultiArrayView<2, T, C2> & z, SNTy pe & v, double tolerance)
skipping to change at line 395 skipping to change at line 393
T gamma = newColumn(n,0); T gamma = newColumn(n,0);
if(gamma == 0.0) if(gamma == 0.0)
{ {
v = 0.0; v = 0.0;
return; return;
} }
T yv = dot(columnVector(newColumn, Shape(0,0),n), columnVector(z, Shape (0,0),n)); T yv = dot(columnVector(newColumn, Shape(0,0),n), columnVector(z, Shape (0,0),n));
// use atan2 as it is robust against overflow/underflow // use atan2 as it is robust against overflow/underflow
double t = 0.5*std::atan2(-2.0*yv, squaredNorm(gamma / v) + squaredNorm T t = 0.5*std::atan2(T(-2.0*yv), T(squaredNorm(gamma / v) + squaredNorm
(yv) - 1.0), (yv) - 1.0)),
s = std::sin(t), s = std::sin(t),
c = std::cos(t); c = std::cos(t);
columnVector(z, Shape(0,0),n) *= c; columnVector(z, Shape(0,0),n) *= c;
z(n,0) = (s - c*yv) / gamma; z(n,0) = (s - c*yv) / gamma;
v *= norm(gamma) / hypot(c*gamma, v*(s - c*yv)); v *= norm(gamma) / hypot(c*gamma, v*(s - c*yv));
} }
// QR algorithm with optional column pivoting // QR algorithm with optional column pivoting
template <class T, class C1, class C2, class C3> template <class T, class C1, class C2, class C3>
unsigned int unsigned int
qrTransformToTriangularImpl(MultiArrayView<2, T, C1> & r, MultiArrayView<2, T, C2> & rhs, MultiArrayView<2, T, C3> & householder, qrTransformToTriangularImpl(MultiArrayView<2, T, C1> & r, MultiArrayView<2, T, C2> & rhs, MultiArrayView<2, T, C3> & householder,
ArrayVector<MultiArrayIndex> & permutation, dou ble epsilon) ArrayVector<MultiArrayIndex> & permutation, dou ble epsilon)
skipping to change at line 618 skipping to change at line 616
linearSolveQRReplace(MultiArrayView<2, T, C1> &A, MultiArrayView<2, T, C2> &b, linearSolveQRReplace(MultiArrayView<2, T, C1> &A, MultiArrayView<2, T, C2> &b,
MultiArrayView<2, T, C3> & res, MultiArrayView<2, T, C3> & res,
double epsilon = 0.0) double epsilon = 0.0)
{ {
typedef typename Matrix<T>::difference_type Shape; typedef typename Matrix<T>::difference_type Shape;
MultiArrayIndex n = columnCount(A); MultiArrayIndex n = columnCount(A);
MultiArrayIndex m = rowCount(A); MultiArrayIndex m = rowCount(A);
MultiArrayIndex rhsCount = columnCount(res); MultiArrayIndex rhsCount = columnCount(res);
MultiArrayIndex rank = std::min(m,n); MultiArrayIndex rank = std::min(m,n);
Shape ul(MultiArrayIndex(0), MultiArrayIndex(0));
vigra_precondition(rhsCount == columnCount(b), vigra_precondition(rhsCount == columnCount(b),
"linearSolveQR(): RHS and solution must have the same number of columns."); "linearSolveQR(): RHS and solution must have the same number of columns.");
vigra_precondition(m == rowCount(b), vigra_precondition(m == rowCount(b),
"linearSolveQR(): Coefficient matrix and RHS must have the same number of rows."); "linearSolveQR(): Coefficient matrix and RHS must have the same number of rows.");
vigra_precondition(n == rowCount(res), vigra_precondition(n == rowCount(res),
"linearSolveQR(): Mismatch between column count of coefficient m atrix and row count of solution."); "linearSolveQR(): Mismatch between column count of coefficient m atrix and row count of solution.");
vigra_precondition(epsilon >= 0.0, vigra_precondition(epsilon >= 0.0,
"linearSolveQR(): 'epsilon' must be non-negative."); "linearSolveQR(): 'epsilon' must be non-negative.");
skipping to change at line 635 skipping to change at line 634
vigra_precondition(epsilon >= 0.0, vigra_precondition(epsilon >= 0.0,
"linearSolveQR(): 'epsilon' must be non-negative."); "linearSolveQR(): 'epsilon' must be non-negative.");
if(m < n) if(m < n)
{ {
// minimum norm solution of underdetermined system // minimum norm solution of underdetermined system
Matrix<T> householderMatrix(n, m); Matrix<T> householderMatrix(n, m);
MultiArrayView<2, T, StridedArrayTag> ht = transpose(householderMat rix); MultiArrayView<2, T, StridedArrayTag> ht = transpose(householderMat rix);
rank = (MultiArrayIndex)detail::qrTransformToLowerTriangular(A, b, ht, epsilon); rank = (MultiArrayIndex)detail::qrTransformToLowerTriangular(A, b, ht, epsilon);
res.subarray(Shape(rank,0), Shape(n, rhsCount)).init(NumericTraits< T>::zero()); res.subarray(Shape(rank,0), Shape(n, rhsCount)).init(NumericTraits< T>::zero());
if(rank < m) if(rank < m)
{ {
// system is also rank-deficient => compute minimum norm least squares solution // system is also rank-deficient => compute minimum norm least squares solution
MultiArrayView<2, T, C1> Asub = A.subarray(Shape(0,0), Shape(m, rank)); MultiArrayView<2, T, C1> Asub = A.subarray(ul, Shape(m,rank));
detail::qrTransformToUpperTriangular(Asub, b, epsilon); detail::qrTransformToUpperTriangular(Asub, b, epsilon);
linearSolveUpperTriangular(A.subarray(Shape(0,0), Shape(rank,ra linearSolveUpperTriangular(A.subarray(ul, Shape(rank,rank)),
nk)), b.subarray(ul, Shape(rank,rhsCount))
b.subarray(Shape(0,0), Shape(rank,rh ,
sCount)), res.subarray(ul, Shape(rank, rhsCoun
res.subarray(Shape(0,0), Shape(rank, t)));
rhsCount)));
} }
else else
{ {
// system has full rank => compute minimum norm solution // system has full rank => compute minimum norm solution
linearSolveLowerTriangular(A.subarray(Shape(0,0), Shape(rank,ra linearSolveLowerTriangular(A.subarray(ul, Shape(rank,rank)),
nk)), b.subarray(ul, Shape(rank, rhsCount)
b.subarray(Shape(0,0), Shape(rank, r ),
hsCount)), res.subarray(ul, Shape(rank, rhsCoun
res.subarray(Shape(0,0), Shape(rank, t)));
rhsCount)));
} }
detail::applyHouseholderColumnReflections(householderMatrix.subarra y(Shape(0,0), Shape(n, rank)), res); detail::applyHouseholderColumnReflections(householderMatrix.subarra y(ul, Shape(n, rank)), res);
} }
else else
{ {
// solution of well-determined or overdetermined system // solution of well-determined or overdetermined system
ArrayVector<MultiArrayIndex> permutation((unsigned int)n); ArrayVector<MultiArrayIndex> permutation((unsigned int)n);
for(MultiArrayIndex k=0; k<n; ++k) for(MultiArrayIndex k=0; k<n; ++k)
permutation[k] = k; permutation[k] = k;
rank = (MultiArrayIndex)detail::qrTransformToUpperTriangular(A, b, permutation, epsilon); rank = (MultiArrayIndex)detail::qrTransformToUpperTriangular(A, b, permutation, epsilon);
Matrix<T> permutedSolution(n, rhsCount); Matrix<T> permutedSolution(n, rhsCount);
if(rank < n) if(rank < n)
{ {
// system is rank-deficient => compute minimum norm solution // system is rank-deficient => compute minimum norm solution
Matrix<T> householderMatrix(n, rank); Matrix<T> householderMatrix(n, rank);
MultiArrayView<2, T, StridedArrayTag> ht = transpose(householde rMatrix); MultiArrayView<2, T, StridedArrayTag> ht = transpose(householde rMatrix);
MultiArrayView<2, T, C1> Asub = A.subarray(Shape(0,0), Shape(ra nk,n)); MultiArrayView<2, T, C1> Asub = A.subarray(ul, Shape(rank,n));
detail::qrTransformToLowerTriangular(Asub, ht, epsilon); detail::qrTransformToLowerTriangular(Asub, ht, epsilon);
linearSolveLowerTriangular(A.subarray(Shape(0,0), Shape(rank,ra linearSolveLowerTriangular(A.subarray(ul, Shape(rank,rank)),
nk)), b.subarray(ul, Shape(rank, rhsCount)
b.subarray(Shape(0,0), Shape(rank, r ),
hsCount)), permutedSolution.subarray(ul, Shape(
permutedSolution.subarray(Shape(0,0) rank, rhsCount)));
, Shape(rank, rhsCount)));
detail::applyHouseholderColumnReflections(householderMatrix, pe rmutedSolution); detail::applyHouseholderColumnReflections(householderMatrix, pe rmutedSolution);
} }
else else
{ {
// system has full rank => compute exact or least squares solut ion // system has full rank => compute exact or least squares solut ion
linearSolveUpperTriangular(A.subarray(Shape(0,0), Shape(rank,ra linearSolveUpperTriangular(A.subarray(ul, Shape(rank,rank)),
nk)), b.subarray(ul, Shape(rank,rhsCount))
b.subarray(Shape(0,0), Shape(rank,rh ,
sCount)),
permutedSolution); permutedSolution);
} }
detail::inverseRowPermutation(permutedSolution, res, permutation); detail::inverseRowPermutation(permutedSolution, res, permutation);
} }
return (unsigned int)rank; return (unsigned int)rank;
} }
template <class T, class C1, class C2, class C3> template <class T, class C1, class C2, class C3>
unsigned int linearSolveQR(MultiArrayView<2, T, C1> const & A, MultiArrayVi ew<2, T, C2> const & b, unsigned int linearSolveQR(MultiArrayView<2, T, C1> const & A, MultiArrayVi ew<2, T, C2> const & b,
MultiArrayView<2, T, C3> & res) MultiArrayView<2, T, C3> & res)
skipping to change at line 726 skipping to change at line 724
*/ */
template <class T, class C1, class C2> template <class T, class C1, class C2>
bool inverse(const MultiArrayView<2, T, C1> &v, MultiArrayView<2, T, C2> &r es) bool inverse(const MultiArrayView<2, T, C1> &v, MultiArrayView<2, T, C2> &r es)
{ {
const MultiArrayIndex n = columnCount(v); const MultiArrayIndex n = columnCount(v);
vigra_precondition(n <= rowCount(v), vigra_precondition(n <= rowCount(v),
"inverse(): input matrix must have at least as many rows as columns. "); "inverse(): input matrix must have at least as many rows as columns. ");
vigra_precondition(n == rowCount(res) && rowCount(v) == columnCount(res ), vigra_precondition(n == rowCount(res) && rowCount(v) == columnCount(res ),
"inverse(): shape of output matrix must be the transpose of the inpu t matrix' shape."); "inverse(): shape of output matrix must be the transpose of the inpu t matrix' shape.");
Matrix<T> q(v.shape()), r(n, n); Matrix<T> r(v.shape()), q(n, n);
if(!qrDecomposition(v, q, r)) if(!qrDecomposition(v, q, r))
return false; // a didn't have full rank return false; // a didn't have full rank
linearSolveUpperTriangular(r, transpose(q), res); linearSolveUpperTriangular(r, transpose(q), res);
return true; return true;
} }
/** Create the inverse or pseudo-inverse of matrix \a v. /** Create the inverse or pseudo-inverse of matrix \a v.
The result is returned as a temporary matrix. If the matrix \a v is square, The result is returned as a temporary matrix. If the matrix \a v is square,
the result will have the same shape and contains the inverse of \a v. the result will have the same shape and contains the inverse of \a v.
skipping to change at line 894 skipping to change at line 892
is not positive definite, the function returns <tt>false</tt>. is not positive definite, the function returns <tt>false</tt>.
<b>\#include</b> \<<a href="linear__solve_8hxx-source.html">vigra/linea r_solve.hxx</a>\> or<br> <b>\#include</b> \<<a href="linear__solve_8hxx-source.html">vigra/linea r_solve.hxx</a>\> or<br>
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin ear_algebra.hxx</a>\><br> <b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin ear_algebra.hxx</a>\><br>
Namespaces: vigra and vigra::linalg Namespaces: vigra and vigra::linalg
*/ */
template <class T, class C1, class C2> template <class T, class C1, class C2>
bool choleskyDecomposition(MultiArrayView<2, T, C1> const & A, bool choleskyDecomposition(MultiArrayView<2, T, C1> const & A,
MultiArrayView<2, T, C2> &L) MultiArrayView<2, T, C2> &L)
{ {
typedef T Real;
MultiArrayIndex n = columnCount(A); MultiArrayIndex n = columnCount(A);
vigra_precondition(rowCount(A) == n, vigra_precondition(rowCount(A) == n,
"choleskyDecomposition(): Input matrix must be squar e."); "choleskyDecomposition(): Input matrix must be squar e.");
vigra_precondition(n == columnCount(L) && n == rowCount(L), vigra_precondition(n == columnCount(L) && n == rowCount(L),
"choleskyDecomposition(): Output matrix must have sa me shape as input matrix."); "choleskyDecomposition(): Output matrix must have sa me shape as input matrix.");
vigra_precondition(isSymmetric(A),
"choleskyDecomposition(): Input matrix must be symme
tric.");
for (MultiArrayIndex j = 0; j < n; ++j) for (MultiArrayIndex j = 0; j < n; ++j)
{ {
Real d(0.0); T d(0.0);
for (MultiArrayIndex k = 0; k < j; ++k) for (MultiArrayIndex k = 0; k < j; ++k)
{ {
Real s(0.0); T s(0.0);
for (MultiArrayIndex i = 0; i < k; ++i) for (MultiArrayIndex i = 0; i < k; ++i)
{ {
s += L(k, i)*L(j, i); s += L(k, i)*L(j, i);
} }
L(j, k) = s = (A(j, k) - s)/L(k, k); L(j, k) = s = (A(j, k) - s)/L(k, k);
d = d + s*s; d = d + s*s;
vigra_precondition(A(k, j) == A(j, k),
"choleskyDecomposition(): Input matrix must be symme
tric.");
} }
d = A(j, j) - d; d = A(j, j) - d;
if(d <= 0.0) if(d <= 0.0)
return false; // A is not positive definite return false; // A is not positive definite
L(j, j) = std::sqrt(d); L(j, j) = std::sqrt(d);
for (MultiArrayIndex k = j+1; k < n; ++k) for (MultiArrayIndex k = j+1; k < n; ++k)
{ {
L(j, k) = 0.0; L(j, k) = 0.0;
} }
} }
skipping to change at line 963 skipping to change at line 958
const MultiArrayIndex m = rowCount(a); const MultiArrayIndex m = rowCount(a);
const MultiArrayIndex n = columnCount(a); const MultiArrayIndex n = columnCount(a);
vigra_precondition(n == columnCount(r) && m == rowCount(r) && vigra_precondition(n == columnCount(r) && m == rowCount(r) &&
m == columnCount(q) && m == rowCount(q), m == columnCount(q) && m == rowCount(q),
"qrDecomposition(): Matrix shape mismatch."); "qrDecomposition(): Matrix shape mismatch.");
q = identityMatrix<T>(m); q = identityMatrix<T>(m);
MultiArrayView<2,T, StridedArrayTag> tq = transpose(q); MultiArrayView<2,T, StridedArrayTag> tq = transpose(q);
r = a; r = a;
ArrayVector<MultiArrayIndex> noPivoting; // intentionally empty ArrayVector<MultiArrayIndex> noPivoting; // intentionally empty
return (detail::qrTransformToUpperTriangular(r, tq, noPivoting, epsilon ) == std::min(m,n)); return ((MultiArrayIndex)detail::qrTransformToUpperTriangular(r, tq, no Pivoting, epsilon) == std::min(m,n));
} }
/** Deprecated, use \ref linearSolveUpperTriangular(). /** Deprecated, use \ref linearSolveUpperTriangular().
*/ */
template <class T, class C1, class C2, class C3> template <class T, class C1, class C2, class C3>
inline inline
bool reverseElimination(const MultiArrayView<2, T, C1> &r, const MultiArray View<2, T, C2> &b, bool reverseElimination(const MultiArrayView<2, T, C1> &r, const MultiArray View<2, T, C2> &b,
MultiArrayView<2, T, C3> x) MultiArrayView<2, T, C3> x)
{ {
return linearSolveUpperTriangular(r, b, x); return linearSolveUpperTriangular(r, b, x);
skipping to change at line 1077 skipping to change at line 1072
return false; // l doesn't have full rank return false; // l doesn't have full rank
T sum = b(i, k); T sum = b(i, k);
for(MultiArrayIndex j=0; j<i; ++j) for(MultiArrayIndex j=0; j<i; ++j)
sum -= l(i, j) * x(j, k); sum -= l(i, j) * x(j, k);
x(i, k) = sum / l(i, i); x(i, k) = sum / l(i, i);
} }
} }
return true; return true;
} }
/** Solve a linear system when the Cholesky decomposition of the left h
and side is given.
The square matrix \a L must be a lower-triangular matrix resulting
from Cholesky
decomposition of some positive definite coefficient matrix.
The column vectors of matrix \a b are the right-hand sides of the e
quation (several equations
with the same matrix \a L can thus be solved in one go). The result
is returned
in \a x, whose columns contain the solutions for the correspoinding
columns of \a b. This implementation can be applied in-place, i.e.
<tt>&b == &x</tt> is allowed.
The following size requirements apply:
\code
rowCount(L) == columnCount(L);
rowCount(L) == rowCount(b);
columnCount(L) == rowCount(x);
columnCount(b) == columnCount(x);
\endcode
<b>\#include</b> \<<a href="linear__solve_8hxx-source.html">vigra/linea
r_solve.hxx</a>\> or<br>
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin
ear_algebra.hxx</a>\><br>
Namespaces: vigra and vigra::linalg
*/
template <class T, class C1, class C2, class C3>
inline
void choleskySolve(MultiArrayView<2, T, C1> & L, MultiArrayView<2, T, C2> c
onst & b, MultiArrayView<2, T, C3> & x)
{
/* Solve L * y = b */
linearSolveLowerTriangular(L, b, x);
/* Solve L^T * x = y */
linearSolveUpperTriangular(transpose(L), x, x);
}
/** Solve a linear system. /** Solve a linear system.
\a A is the coefficient matrix, and the column vectors \a A is the coefficient matrix, and the column vectors
in \a b are the right-hand sides of the equation (so, several equat ions in \a b are the right-hand sides of the equation (so, several equat ions
with the same coefficients can be solved in one go). The result is returned with the same coefficients can be solved in one go). The result is returned
in \a res, whose columns contain the solutions for the correspondin g in \a res, whose columns contain the solutions for the correspondin g
columns of \a b. The number of columns of \a A must equal the numbe r of rows of columns of \a b. The number of columns of \a A must equal the numbe r of rows of
both \a b and \a res, and the number of columns of \a b and \a res must match. both \a b and \a res, and the number of columns of \a b and \a res must match.
\a method must be one of the following: \a method must be one of the following:
skipping to change at line 1152 skipping to change at line 1179
for(unsigned int k=0; k<method.size(); ++k) for(unsigned int k=0; k<method.size(); ++k)
method[k] = (std::string::value_type)tolower(method[k]); method[k] = (std::string::value_type)tolower(method[k]);
if(method == "cholesky") if(method == "cholesky")
{ {
vigra_precondition(columnCount(A) == rowCount(A), vigra_precondition(columnCount(A) == rowCount(A),
"linearSolve(): Cholesky method requires square coefficient mat rix."); "linearSolve(): Cholesky method requires square coefficient mat rix.");
Matrix<T> L(A.shape()); Matrix<T> L(A.shape());
if(!choleskyDecomposition(A, L)) if(!choleskyDecomposition(A, L))
return false; // false if A wasn't symmetric positive definite return false; // false if A wasn't symmetric positive definite
linearSolveLowerTriangular(L, b, res); choleskySolve(L, b, res);
linearSolveUpperTriangular(transpose(L), res, res);
} }
else if(method == "qr") else if(method == "qr")
{ {
return (MultiArrayIndex)linearSolveQR(A, b, res) == n; return (MultiArrayIndex)linearSolveQR(A, b, res) == n;
} }
else if(method == "ne") else if(method == "ne")
{ {
return linearSolve(transpose(A)*A, transpose(A)*b, res, "Cholesky") ; return linearSolve(transpose(A)*A, transpose(A)*b, res, "Cholesky") ;
} }
else if(method == "svd") else if(method == "svd")
skipping to change at line 1197 skipping to change at line 1223
} }
//@} //@}
} // namespace linalg } // namespace linalg
using linalg::inverse; using linalg::inverse;
using linalg::determinant; using linalg::determinant;
using linalg::logDeterminant; using linalg::logDeterminant;
using linalg::linearSolve; using linalg::linearSolve;
using linalg::choleskySolve;
using linalg::choleskyDecomposition; using linalg::choleskyDecomposition;
using linalg::qrDecomposition; using linalg::qrDecomposition;
using linalg::linearSolveUpperTriangular; using linalg::linearSolveUpperTriangular;
using linalg::linearSolveLowerTriangular; using linalg::linearSolveLowerTriangular;
} // namespace vigra } // namespace vigra
#endif // VIGRA_LINEAR_SOLVE_HXX #endif // VIGRA_LINEAR_SOLVE_HXX
 End of changes. 26 change blocks. 
49 lines changed or deleted 80 lines changed or added


 localminmax.hxx   localminmax.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 67 skipping to change at line 65
namespace detail { namespace detail {
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class DestValue, class Neighborhood, class DestValue, class Neighborhood,
class Compare> class Compare>
void void
localMinMax(SrcIterator sul, SrcIterator slr, SrcAccessor sa, localMinMax(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
DestIterator dul, DestAccessor da, DestIterator dul, DestAccessor da,
DestValue marker, Neighborhood neighborhood, DestValue marker, Neighborhood,
Compare compare) Compare compare)
{ {
int w = slr.x - sul.x - 2; int w = slr.x - sul.x - 2;
int h = slr.y - sul.y - 2; int h = slr.y - sul.y - 2;
int i,x,y; int i,x,y;
sul += Diff2D(1,1); sul += Diff2D(1,1);
dul += Diff2D(1,1); dul += Diff2D(1,1);
 End of changes. 4 change blocks. 
4 lines changed or deleted 2 lines changed or added


 mathutil.hxx   mathutil.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2005 by Ullrich Koethe */ /* Copyright 1998-2005 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 41 skipping to change at line 39
/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_MATHUTIL_HXX #ifndef VIGRA_MATHUTIL_HXX
#define VIGRA_MATHUTIL_HXX #define VIGRA_MATHUTIL_HXX
#ifdef _MSC_VER
# pragma warning (disable: 4996) // hypot/_hypot confusion
#endif
#include <cmath> #include <cmath>
#include <cstdlib> #include <cstdlib>
#include "config.hxx" #include "config.hxx"
#include "error.hxx" #include "error.hxx"
#include "tuple.hxx" #include "tuple.hxx"
#include "sized_int.hxx" #include "sized_int.hxx"
#include "numerictraits.hxx" #include "numerictraits.hxx"
/*! \page MathConstants Mathematical Constants /*! \page MathConstants Mathematical Constants
skipping to change at line 126 skipping to change at line 128
Defined for all floating point types. Rounds towards the nearest in teger Defined for all floating point types. Rounds towards the nearest in teger
such that <tt>abs(round(t)) == round(abs(t))</tt> for all <tt>t</tt >. such that <tt>abs(round(t)) == round(abs(t))</tt> for all <tt>t</tt >.
<b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br> <b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br>
Namespace: vigra Namespace: vigra
*/ */
inline float round(float t) inline float round(float t)
{ {
return t >= 0.0 return t >= 0.0
? floor(t + 0.5) ? floor(t + 0.5f)
: ceil(t - 0.5); : ceil(t - 0.5f);
} }
inline double round(double t) inline double round(double t)
{ {
return t >= 0.0 return t >= 0.0
? floor(t + 0.5) ? floor(t + 0.5)
: ceil(t - 0.5); : ceil(t - 0.5);
} }
inline long double round(long double t) inline long double round(long double t)
{ {
return t >= 0.0 return t >= 0.0
? floor(t + 0.5) ? floor(t + 0.5)
: ceil(t - 0.5); : ceil(t - 0.5);
} }
/*! Round and cast to integer.
Rounds to the nearest integer like round(), but casts the result to
<tt>int</tt> (this will be faster and is usually needed anyway).
<b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut
il.hxx</a>\><br>
Namespace: vigra
*/
inline int roundi(double t)
{
return t >= 0.0
? int(t + 0.5)
: int(t - 0.5);
}
/*! Round up to the nearest power of 2. /*! Round up to the nearest power of 2.
Efficient algorithm for finding the smallest power of 2 which is no t smaller than \a x Efficient algorithm for finding the smallest power of 2 which is no t smaller than \a x
(function clp2() from Henry Warren: "Hacker's Delight", Addison-Wes ley, 2003, (function clp2() from Henry Warren: "Hacker's Delight", Addison-Wes ley, 2003,
see http://www.hackersdelight.org/). see http://www.hackersdelight.org/).
If \a x > 2^31, the function will return 0 because integer arithmet ic is defined modulo 2^32. If \a x > 2^31, the function will return 0 because integer arithmet ic is defined modulo 2^32.
<b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br> <b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br>
Namespace: vigra Namespace: vigra
*/ */
skipping to change at line 372 skipping to change at line 389
Useful for fast fixed-point computations. Useful for fast fixed-point computations.
<b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br> <b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br>
Namespace: vigra Namespace: vigra
*/ */
inline UInt32 sqrti(UInt32 v) inline UInt32 sqrti(UInt32 v)
{ {
return detail::IntSquareRoot<UInt32>::exec(v); return detail::IntSquareRoot<UInt32>::exec(v);
} }
#ifndef VIGRA_HAS_HYPOT #ifdef VIGRA_NO_HYPOT
/*! Compute the Euclidean distance (length of the hypothenuse of a righ t-angled triangle). /*! Compute the Euclidean distance (length of the hypothenuse of a righ t-angled triangle).
The hypot() function returns the sqrt(a*a + b*b). The hypot() function returns the sqrt(a*a + b*b).
It is implemented in a way that minimizes round-off error. It is implemented in a way that minimizes round-off error.
<b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br> <b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br>
Namespace: vigra Namespace: vigra
*/ */
inline double hypot(double a, double b) inline double hypot(double a, double b)
{ {
skipping to change at line 400 skipping to change at line 417
} }
#else #else
using ::hypot; using ::hypot;
#endif #endif
/*! The sign function. /*! The sign function.
Returns 1, 0, or -1 depending on the sign of \a t. Returns 1, 0, or -1 depending on the sign of \a t, but with the sam e type as \a t.
<b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br> <b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br>
Namespace: vigra Namespace: vigra
*/ */
template <class T> template <class T>
inline T sign(T t) inline T sign(T t)
{ {
return t > NumericTraits<T>::zero() return t > NumericTraits<T>::zero()
? NumericTraits<T>::one() ? NumericTraits<T>::one()
: t < NumericTraits<T>::zero() : t < NumericTraits<T>::zero()
? -NumericTraits<T>::one() ? -NumericTraits<T>::one()
: NumericTraits<T>::zero(); : NumericTraits<T>::zero();
} }
/*! The integer sign function.
Returns 1, 0, or -1 depending on the sign of \a t, converted to int
.
<b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut
il.hxx</a>\><br>
Namespace: vigra
*/
template <class T>
inline int signi(T t)
{
return t > NumericTraits<T>::zero()
? 1
: t < NumericTraits<T>::zero()
? -1
: 0;
}
/*! The binary sign function. /*! The binary sign function.
Transfers the sign of \a t2 to \a t1. Transfers the sign of \a t2 to \a t1.
<b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br> <b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br>
Namespace: vigra Namespace: vigra
*/ */
template <class T1, class T2> template <class T1, class T2>
inline T1 sign(T1 t1, T2 t2) inline T1 sign(T1 t1, T2 t2)
{ {
skipping to change at line 624 skipping to change at line 658
{ {
if(condition(*first) && vopt < *first) if(condition(*first) && vopt < *first)
{ {
vopt = *first; vopt = *first;
best = first; best = first;
} }
} }
return best; return best;
} }
/*! Compute the eigenvalues of a 2x2 real symmetric matrix.
This uses the analytical eigenvalue formula
\f[
\lambda_{1,2} = \frac{1}{2}\left(a_{00} + a_{11} \pm \sqrt{(a_{0
0} - a_{11})^2 + 4 a_{01}^2}\right)
\f]
<b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut
il.hxx</a>\><br>
Namespace: vigra
*/
template <class T>
void symmetric2x2Eigenvalues(T a00, T a01, T a11, T * r0, T * r1)
{
double d = hypot(a00 - a11, 2.0*a01);
*r0 = static_cast<T>(0.5*(a00 + a11 + d));
*r1 = static_cast<T>(0.5*(a00 + a11 - d));
if(*r0 < *r1)
std::swap(*r0, *r1);
}
/*! Compute the eigenvalues of a 3x3 real symmetric matrix.
This uses a numerically stable version of the analytical eigenvalue
formula according to
<p>
David Eberly: <a href="http://www.geometrictools.com/Documentation/
EigenSymmetric3x3.pdf">
<em>"Eigensystems for 3
<b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut
il.hxx</a>\><br>
Namespace: vigra
*/
template <class T>
void symmetric3x3Eigenvalues(T a00, T a01, T a02, T a11, T a12, T a22,
T * r0, T * r1, T * r2)
{
static double inv3 = 1.0 / 3.0, root3 = std::sqrt(3.0);
double c0 = a00*a11*a22 + 2.0*a01*a02*a12 - a00*a12*a12 - a11*a02*a02 -
a22*a01*a01;
double c1 = a00*a11 - a01*a01 + a00*a22 - a02*a02 + a11*a22 - a12*a12;
double c2 = a00 + a11 + a22;
double c2Div3 = c2*inv3;
double aDiv3 = (c1 - c2*c2Div3)*inv3;
if (aDiv3 > 0.0)
aDiv3 = 0.0;
double mbDiv2 = 0.5*(c0 + c2Div3*(2.0*c2Div3*c2Div3 - c1));
double q = mbDiv2*mbDiv2 + aDiv3*aDiv3*aDiv3;
if (q > 0.0)
q = 0.0;
double magnitude = std::sqrt(-aDiv3);
double angle = std::atan2(std::sqrt(-q),mbDiv2)*inv3;
double cs = std::cos(angle);
double sn = std::sin(angle);
*r0 = static_cast<T>(c2Div3 + 2.0*magnitude*cs);
*r1 = static_cast<T>(c2Div3 - magnitude*(cs + root3*sn));
*r2 = static_cast<T>(c2Div3 - magnitude*(cs - root3*sn));
if(*r0 < *r1)
std::swap(*r0, *r1);
if(*r0 < *r2)
std::swap(*r0, *r2);
if(*r1 < *r2)
std::swap(*r1, *r2);
}
namespace detail { namespace detail {
template <class T> template <class T>
T ellipticRD(T x, T y, T z) T ellipticRD(T x, T y, T z)
{ {
double f = 1.0, s = 0.0, X, Y, Z, m; double f = 1.0, s = 0.0, X, Y, Z, m;
for(;;) for(;;)
{ {
m = (x + y + 3.0*z) / 5.0; m = (x + y + 3.0*z) / 5.0;
X = 1.0 - x/m; X = 1.0 - x/m;
skipping to change at line 726 skipping to change at line 822
Namespace: vigra Namespace: vigra
*/ */
inline double ellipticIntegralE(double x, double k) inline double ellipticIntegralE(double x, double k)
{ {
double c2 = sq(VIGRA_CSTD::cos(x)); double c2 = sq(VIGRA_CSTD::cos(x));
double s = VIGRA_CSTD::sin(x); double s = VIGRA_CSTD::sin(x);
k = sq(k*s); k = sq(k*s);
return s*(detail::ellipticRF(c2, 1.0-k, 1.0) - k/3.0*detail::ellipticRD (c2, 1.0-k, 1.0)); return s*(detail::ellipticRF(c2, 1.0-k, 1.0) - k/3.0*detail::ellipticRD (c2, 1.0-k, 1.0));
} }
#ifndef VIGRA_HAS_ERF #if _MSC_VER
namespace detail { namespace detail {
template <class T> template <class T>
double erfImpl(T x) double erfImpl(T x)
{ {
double t = 1.0/(1.0+0.5*VIGRA_CSTD::fabs(x)); double t = 1.0/(1.0+0.5*VIGRA_CSTD::fabs(x));
double ans = t*VIGRA_CSTD::exp(-x*x-1.26551223+t*(1.00002368+t*(0.37409 196+ double ans = t*VIGRA_CSTD::exp(-x*x-1.26551223+t*(1.00002368+t*(0.37409 196+
t*(0.09678418+t*(-0.18628806+t*(0.27886 807+ t*(0.09678418+t*(-0.18628806+t*(0.27886 807+
t*(-1.13520398+t*(1.48851587+t*(-0.8221 5223+ t*(-1.13520398+t*(1.48851587+t*(-0.8221 5223+
skipping to change at line 768 skipping to change at line 864
<b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br> <b>\#include</b> \<<a href="mathutil_8hxx-source.html">vigra/mathut il.hxx</a>\><br>
Namespace: vigra Namespace: vigra
*/ */
inline double erf(double x) inline double erf(double x)
{ {
return detail::erfImpl(x); return detail::erfImpl(x);
} }
#else #else
using VIGRA_CSTD::erf; using ::erf;
#endif #endif
namespace detail { namespace detail {
template <class T> template <class T>
double noncentralChi2CDFApprox(unsigned int degreesOfFreedom, T noncentrali ty, T arg) double noncentralChi2CDFApprox(unsigned int degreesOfFreedom, T noncentrali ty, T arg)
{ {
double a = degreesOfFreedom + noncentrality; double a = degreesOfFreedom + noncentrality;
double b = (a + noncentrality) / sq(a); double b = (a + noncentrality) / sq(a);
 End of changes. 12 change blocks. 
9 lines changed or deleted 114 lines changed or added


 matrix.hxx   matrix.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2003-2008 by Gunnar Kedenburg and Ullrich Koethe */ /* Copyright 2003-2008 by Gunnar Kedenburg and Ullrich Koethe */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 688 skipping to change at line 687
Namespaces: vigra and vigra::linalg Namespaces: vigra and vigra::linalg
**/ **/
template <class T, class C> template <class T, class C>
inline MultiArrayView <2, T, C> inline MultiArrayView <2, T, C>
columnVector(MultiArrayView<2, T, C> const & m, MultiArrayShape<2>::type fi rst, int end) columnVector(MultiArrayView<2, T, C> const & m, MultiArrayShape<2>::type fi rst, int end)
{ {
typedef typename MultiArrayView <2, T, C>::difference_type Shape; typedef typename MultiArrayView <2, T, C>::difference_type Shape;
return m.subarray(first, Shape(end, first[1]+1)); return m.subarray(first, Shape(end, first[1]+1));
} }
/** Create a sub vector view of the vector \a m starting at element \a
first and
ranging to row \a end (non-inclusive).
Note: This function may only be called when either <tt>rowCount(m)
== 1</tt> or
<tt>columnCount(m) == 1</tt>, i.e. when \a m really represents a ve
ctor.
Otherwise, a PreconditionViolation exception is raised.
<b>\#include</b> \<<a href="matrix_8hxx-source.html">vigra/matrix.hxx</
a>\> or<br>
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin
ear_algebra.hxx</a>\><br>
Namespaces: vigra and vigra::linalg
**/
template <class T, class C>
inline MultiArrayView <2, T, C>
subVector(MultiArrayView<2, T, C> const & m, int first, int end)
{
typedef typename MultiArrayView <2, T, C>::difference_type Shape;
if(columnCount(m) == 1)
return m.subarray(Shape(first, 0), Shape(end, 1));
vigra_precondition(rowCount(m) == 1,
"linalg::subVector(): Input must be a vector (1xN or
Nx1).");
return m.subarray(Shape(0, first), Shape(1, end));
}
/** Check whether matrix \a m is symmetric. /** Check whether matrix \a m is symmetric.
<b>\#include</b> \<<a href="matrix_8hxx-source.html">vigra/matrix.hxx</ a>\> or<br> <b>\#include</b> \<<a href="matrix_8hxx-source.html">vigra/matrix.hxx</ a>\> or<br>
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin ear_algebra.hxx</a>\><br> <b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin ear_algebra.hxx</a>\><br>
Namespaces: vigra and vigra::linalg Namespaces: vigra and vigra::linalg
*/ */
template <class T, class C> template <class T, class C>
bool bool
isSymmetric(MultiArrayView<2, T, C> const & m) isSymmetric(MultiArrayView<2, T, C> const & m)
{ {
skipping to change at line 709 skipping to change at line 731
if(size != columnCount(m)) if(size != columnCount(m))
return false; return false;
for(MultiArrayIndex i = 0; i < size; ++i) for(MultiArrayIndex i = 0; i < size; ++i)
for(MultiArrayIndex j = i+1; j < size; ++j) for(MultiArrayIndex j = i+1; j < size; ++j)
if(m(j, i) != m(i, j)) if(m(j, i) != m(i, j))
return false; return false;
return true; return true;
} }
/** Compute the trace of a square matrix.
<b>\#include</b> \<<a href="matrix_8hxx-source.html">vigra/matrix.hxx</
a>\> or<br>
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin
ear_algebra.hxx</a>\><br>
Namespaces: vigra and vigra::linalg
*/
template <class T, class C>
typename NumericTraits<T>::Promote
trace(MultiArrayView<2, T, C> const & m)
{
typedef typename NumericTraits<T>::Promote SumType;
const MultiArrayIndex size = rowCount(m);
vigra_precondition(size == columnCount(m), "linalg::trace(): Matrix mus
t be square.");
SumType sum = NumericTraits<SumType>::zero();
for(MultiArrayIndex i = 0; i < size; ++i)
sum += m(i, i);
return sum;
}
#ifdef DOXYGEN // documentation only -- function is already defined in vigr a/multi_array.hxx #ifdef DOXYGEN // documentation only -- function is already defined in vigr a/multi_array.hxx
/** calculate the squared Frobenius norm of a matrix. /** calculate the squared Frobenius norm of a matrix.
Equal to the sum of squares of the matrix elements. Equal to the sum of squares of the matrix elements.
<b>\#include</b> \<<a href="matrix_8hxx-source.html">vigra/matrix.hxx</ a>\> <b>\#include</b> \<<a href="matrix_8hxx-source.html">vigra/matrix.hxx</ a>\>
Namespace: vigra Namespace: vigra
*/ */
template <class T, class ALLOC> template <class T, class ALLOC>
typename Matrix<T, ALLLOC>::SquaredNormType typename Matrix<T, ALLLOC>::SquaredNormType
skipping to change at line 2121 skipping to change at line 2164
} // namespace linalg } // namespace linalg
using linalg::RowMajor; using linalg::RowMajor;
using linalg::ColumnMajor; using linalg::ColumnMajor;
using linalg::Matrix; using linalg::Matrix;
using linalg::identityMatrix; using linalg::identityMatrix;
using linalg::diagonalMatrix; using linalg::diagonalMatrix;
using linalg::transpose; using linalg::transpose;
using linalg::pointWise; using linalg::pointWise;
using linalg::trace;
using linalg::dot; using linalg::dot;
using linalg::cross; using linalg::cross;
using linalg::outer; using linalg::outer;
using linalg::rowCount; using linalg::rowCount;
using linalg::columnCount; using linalg::columnCount;
using linalg::rowVector; using linalg::rowVector;
using linalg::columnVector; using linalg::columnVector;
using linalg::subVector;
using linalg::isSymmetric; using linalg::isSymmetric;
using linalg::joinHorizontally; using linalg::joinHorizontally;
using linalg::joinVertically; using linalg::joinVertically;
using linalg::argMin; using linalg::argMin;
using linalg::argMinIf; using linalg::argMinIf;
using linalg::argMax; using linalg::argMax;
using linalg::argMaxIf; using linalg::argMaxIf;
/********************************************************/ /********************************************************/
/* */ /* */
skipping to change at line 2162 skipping to change at line 2207
template <class T, class ALLOC> template <class T, class ALLOC>
struct NormTraits<linalg::TemporaryMatrix<T, ALLOC> > struct NormTraits<linalg::TemporaryMatrix<T, ALLOC> >
: public NormTraits<Matrix<T, ALLOC> > : public NormTraits<Matrix<T, ALLOC> >
{ {
typedef NormTraits<Matrix<T, ALLOC> > BaseType; typedef NormTraits<Matrix<T, ALLOC> > BaseType;
typedef linalg::TemporaryMatrix<T, ALLOC> Type; typedef linalg::TemporaryMatrix<T, ALLOC> Type;
typedef typename BaseType::SquaredNormType SquaredNormType; typedef typename BaseType::SquaredNormType SquaredNormType;
typedef typename BaseType::NormType NormType; typedef typename BaseType::NormType NormType;
}; };
} // namespace vigra
namespace std {
/** \addtogroup LinearAlgebraFunctions /** \addtogroup LinearAlgebraFunctions
*/ */
//@{ //@{
/** print a matrix \a m to the stream \a s. /** print a matrix \a m to the stream \a s.
<b>\#include</b> \<<a href="matrix_8hxx-source.html">vigra/matrix.hxx</ a>\> or<br> <b>\#include</b> \<<a href="matrix_8hxx-source.html">vigra/matrix.hxx</ a>\> or<br>
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin ear_algebra.hxx</a>\><br> <b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin ear_algebra.hxx</a>\><br>
Namespace: std Namespace: std
*/ */
template <class T, class C> template <class T, class C>
std::ostream & ostream &
operator<<(std::ostream & s, const vigra::MultiArrayView<2, T, C> &m) operator<<(ostream & s, const vigra::MultiArrayView<2, T, C> &m)
{ {
const MultiArrayIndex rows = vigra::linalg::rowCount(m); const vigra::MultiArrayIndex rows = vigra::linalg::rowCount(m);
const MultiArrayIndex cols = vigra::linalg::columnCount(m); const vigra::MultiArrayIndex cols = vigra::linalg::columnCount(m);
std::ios::fmtflags flags = ios::fmtflags flags = s.setf(ios::right | ios::fixed, ios::adjustfield
s.setf(std::ios::right | std::ios::fixed, std::ios::adjustfield | s | ios::floatfield);
td::ios::floatfield); for(vigra::MultiArrayIndex j = 0; j < rows; ++j)
for(MultiArrayIndex j = 0; j < rows; ++j)
{ {
for(MultiArrayIndex i = 0; i < cols; ++i) for(vigra::MultiArrayIndex i = 0; i < cols; ++i)
{ {
s << std::setw(7) << std::setprecision(4) << m(j, i) << " "; s << m(j, i) << " ";
} }
s << std::endl; s << endl;
} }
s.setf(flags); s.setf(flags);
return s; return s;
} }
//@} //@}
} // namespace std
namespace vigra {
namespace linalg { namespace linalg {
namespace detail { namespace detail {
template <class T1, class C1, class T2, class C2, class T3, class C3> template <class T1, class C1, class T2, class C2, class T3, class C3>
void void
columnStatisticsImpl(MultiArrayView<2, T1, C1> const & A, columnStatisticsImpl(MultiArrayView<2, T1, C1> const & A,
MultiArrayView<2, T2, C2> & mean, MultiArrayView<2, T3, C3 > & sumOfSquaredDifferences) MultiArrayView<2, T2, C2> & mean, MultiArrayView<2, T3, C3 > & sumOfSquaredDifferences)
{ {
MultiArrayIndex m = rowCount(A); MultiArrayIndex m = rowCount(A);
 End of changes. 13 change blocks. 
13 lines changed or deleted 74 lines changed or added


 memory.hxx   memory.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2002-2003 by Ullrich Koethe, Hans Meine */ /* Copyright 2002-2003 by Ullrich Koethe, Hans Meine */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 43 skipping to change at line 41
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_MEMORY_HXX #ifndef VIGRA_MEMORY_HXX
#define VIGRA_MEMORY_HXX #define VIGRA_MEMORY_HXX
#include "metaprogramming.hxx" #include "metaprogramming.hxx"
namespace vigra { namespace detail { namespace vigra {
enum SkipInitializationTag { SkipInitialization};
template<class T>
struct CanSkipInitialization
{
typedef typename TypeTraits<T>::isBuiltinType type;
static const bool value = type::asBool;
};
namespace detail {
template <class T> template <class T>
inline void destroy_n(T * /* p */, int /* n */, VigraTrueType /* isPOD */) inline void destroy_n(T * /* p */, std::ptrdiff_t /* n */, VigraTrueType /* isPOD */)
{ {
} }
template <class T> template <class T>
inline void destroy_n(T * p, int n, VigraFalseType /* isPOD */) inline void destroy_n(T * p, std::ptrdiff_t n, VigraFalseType /* isPOD */)
{ {
T * end = p + n; T * end = p + n;
for(; p != end; ++p) for(; p != end; ++p)
p->~T(); p->~T();
} }
template <class T> template <class T>
inline void destroy_n(T * p, int n) inline void destroy_n(T * p, std::ptrdiff_t n)
{ {
destroy_n(p, n, typename TypeTraits<T>::isPOD()); destroy_n(p, n, typename TypeTraits<T>::isPOD());
} }
/********************************************************************/ /********************************************************************/
// g++ 2.95 has std::destroy() in the STL // g++ 2.95 has std::destroy() in the STL
#if !defined(__GNUC__) || __GNUC__ >= 3 #if !defined(__GNUC__) || __GNUC__ >= 3
template <class T> template <class T>
 End of changes. 7 change blocks. 
7 lines changed or deleted 16 lines changed or added


 metaprogramming.hxx   metaprogramming.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 42 skipping to change at line 40
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_METAPROGRAMMING_HXX #ifndef VIGRA_METAPROGRAMMING_HXX
#define VIGRA_METAPROGRAMMING_HXX #define VIGRA_METAPROGRAMMING_HXX
#include "config.hxx" #include "config.hxx"
#include <limits.h> #include <climits>
#include <limits>
namespace vigra { namespace vigra {
template <int N> template <int N>
class MetaInt class MetaInt
{ {
public: public:
enum { value = N }; static const int value = N;
};
template <int N1, int N2>
class MetaMax
{
public:
static const int value = N1 < N2 ? N2 : N1;
};
template <int N1, int N2>
class MetaMin
{
public:
static const int value = N1 < N2 ? N1 : N2;
}; };
struct VigraTrueType struct VigraTrueType
{ {
enum { asBool = true }; static const bool asBool = true, value = true;
}; };
struct VigraFalseType struct VigraFalseType
{ {
enum { asBool = false }; static const bool asBool = false, value = false;
}; };
/** \addtogroup MultiArrayTags Multi-dimensional Array Tags /** \addtogroup MultiArrayTags Multi-dimensional Array Tags
Meta-programming tags to mark array's as strided or unstrided. Meta-programming tags to mark array's as strided or unstrided.
*/ */
//@{ //@{
/********************************************************/ /********************************************************/
/* */ /* */
skipping to change at line 193 skipping to change at line 206
#undef VIGRA_TYPE_TRAITS #undef VIGRA_TYPE_TRAITS
//@} //@}
template <class A> template <class A>
struct Not; struct Not;
template <> template <>
struct Not<VigraTrueType> struct Not<VigraTrueType>
{ {
typedef VigraFalseType result; typedef VigraFalseType result; // deprecated
static const bool boolResult = false; static const bool boolResult = false; // deprecated
typedef VigraFalseType type;
static const bool value = false;
}; };
template <> template <>
struct Not<VigraFalseType> struct Not<VigraFalseType>
{ {
typedef VigraTrueType result; typedef VigraTrueType result; // deprecated
static const bool boolResult = true; static const bool boolResult = true; // deprecated
typedef VigraTrueType type;
static const bool value = true;
}; };
template <class L, class R> template <class L, class R>
struct And; struct And;
template <> template <>
struct And<VigraFalseType, VigraFalseType> struct And<VigraFalseType, VigraFalseType>
{ {
typedef VigraFalseType result; typedef VigraFalseType result; // deprecated
static const bool boolResult = false; static const bool boolResult = false; // deprecated
typedef VigraFalseType type;
static const bool value = false;
}; };
template <> template <>
struct And<VigraFalseType, VigraTrueType> struct And<VigraFalseType, VigraTrueType>
{ {
typedef VigraFalseType result; typedef VigraFalseType result; // deprecated
static const bool boolResult = false; static const bool boolResult = false; // deprecated
typedef VigraFalseType type;
static const bool value = false;
}; };
template <> template <>
struct And<VigraTrueType, VigraFalseType> struct And<VigraTrueType, VigraFalseType>
{ {
typedef VigraFalseType result; typedef VigraFalseType result; // deprecated
static const bool boolResult = false; static const bool boolResult = false; // deprecated
typedef VigraFalseType type;
static const bool value = false;
}; };
template <> template <>
struct And<VigraTrueType, VigraTrueType> struct And<VigraTrueType, VigraTrueType>
{ {
typedef VigraTrueType result; typedef VigraTrueType result; // deprecated
static const bool boolResult = true; static const bool boolResult = true; // deprecated
typedef VigraTrueType type;
static const bool value = true;
}; };
template <class L, class R> template <class L, class R>
struct Or; struct Or;
template <> template <>
struct Or<VigraFalseType, VigraFalseType> struct Or<VigraFalseType, VigraFalseType>
{ {
typedef VigraFalseType result; typedef VigraFalseType result; // deprecated
static const bool boolResult = false; static const bool boolResult = false; // deprecated
typedef VigraFalseType type;
static const bool value = false;
}; };
template <> template <>
struct Or<VigraTrueType, VigraFalseType> struct Or<VigraTrueType, VigraFalseType>
{ {
typedef VigraTrueType result; typedef VigraTrueType result; // deprecated
static const bool boolResult = true; static const bool boolResult = true; // deprecated
typedef VigraTrueType type;
static const bool value = true;
}; };
template <> template <>
struct Or<VigraFalseType, VigraTrueType> struct Or<VigraFalseType, VigraTrueType>
{ {
typedef VigraTrueType result; typedef VigraTrueType result; // deprecated
static const bool boolResult = true; static const bool boolResult = true; // deprecated
typedef VigraTrueType type;
static const bool value = true;
}; };
template <> template <>
struct Or<VigraTrueType, VigraTrueType> struct Or<VigraTrueType, VigraTrueType>
{ {
typedef VigraTrueType result; typedef VigraTrueType result; // deprecated
static const bool boolResult = true; static const bool boolResult = true; // deprecated
typedef VigraTrueType type;
static const bool value = true;
}; };
#ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
template <class PREDICATE, class TRUECASE, class FALSECASE> template <class PREDICATE, class TRUECASE, class FALSECASE>
struct If; struct If;
template <class TRUECASE, class FALSECASE> template <class TRUECASE, class FALSECASE>
struct If<VigraTrueType, TRUECASE, FALSECASE> struct If<VigraTrueType, TRUECASE, FALSECASE>
{ {
skipping to change at line 301 skipping to change at line 334
template <class TRUECASE, class FALSECASE> template <class TRUECASE, class FALSECASE>
struct IfBool<false, TRUECASE, FALSECASE> struct IfBool<false, TRUECASE, FALSECASE>
{ {
typedef FALSECASE type; typedef FALSECASE type;
}; };
template <class L, class R> template <class L, class R>
struct IsSameType struct IsSameType
{ {
typedef VigraFalseType result; typedef VigraFalseType result; // deprecated
static const bool boolResult = false; static const bool boolResult = false; // deprecated
typedef VigraFalseType type;
static const bool value = false;
}; };
template <class T> template <class T>
struct IsSameType<T, T> struct IsSameType<T, T>
{ {
typedef VigraTrueType result; typedef VigraTrueType result; // deprecated
static const bool boolResult = true; static const bool boolResult = true; // deprecated
typedef VigraTrueType type;
static const bool value = true;
};
template <class L, class R>
struct IsDifferentType
{
typedef VigraTrueType type;
static const bool value = true;
};
template <class T>
struct IsDifferentType<T, T>
{
typedef VigraFalseType type;
static const bool value = false;
};
#endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
template <class From, class To>
struct IsConvertibleTo
{
typedef char falseResult[1];
typedef char trueResult[2];
static From const & check();
static falseResult * testIsConvertible(...);
static trueResult * testIsConvertible(To const &);
enum { resultSize = sizeof(*testIsConvertible(check())) };
static const bool value = (resultSize == 2);
typedef typename
IfBool<value, VigraTrueType, VigraFalseType>::type
type;
}; };
template <class DERIVED, class BASE> template <class DERIVED, class BASE>
struct IsDerivedFrom struct IsDerivedFrom
{ {
typedef char falseResult[1]; typedef char falseResult[1];
typedef char trueResult[2]; typedef char trueResult[2];
static falseResult * testIsDerivedFrom(...); static falseResult * testIsDerivedFrom(...);
static trueResult * testIsDerivedFrom(BASE const *); static trueResult * testIsDerivedFrom(BASE const *);
enum { resultSize = sizeof(*testIsDerivedFrom((DERIVED const *)0)) }; enum { resultSize = sizeof(*testIsDerivedFrom((DERIVED const *)0)) };
static const bool boolResult = (resultSize == 2); static const bool value = (resultSize == 2);
typedef typename typedef typename
IfBool<boolResult, VigraTrueType, VigraFalseType>::type IfBool<value, VigraTrueType, VigraFalseType>::type
result; type;
static const bool boolResult = value; // deprecated
typedef type result; // deprecated
}; };
#endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION template <class T>
struct UnqualifiedType
{
typedef T type;
};
template <class T>
struct UnqualifiedType<T const>
{
typedef T type;
};
template <class T>
struct UnqualifiedType<T &>
: public UnqualifiedType<T>
{};
template <class T>
struct UnqualifiedType<T const &>
: public UnqualifiedType<T>
{};
template <class T>
struct UnqualifiedType<T *>
: public UnqualifiedType<T>
{};
template <class T>
struct UnqualifiedType<T const *>
: public UnqualifiedType<T>
{};
template <class T>
struct has_result_type
{
typedef char falseResult[1];
typedef char trueResult[2];
static falseResult * test(...);
template <class U>
static trueResult * test(U *, typename U::result_type * = 0);
enum { resultSize = sizeof(*test((T*)0)) };
static const bool value = (resultSize == 2);
typedef typename
IfBool<value, VigraTrueType, VigraFalseType>::type
type;
};
template <class T>
struct has_value_type
{
typedef char falseResult[1];
typedef char trueResult[2];
static falseResult * test(...);
template <class U>
static trueResult * test(U *, typename U::value_type * = 0);
enum { resultSize = sizeof(*test((T*)0)) };
static const bool value = (resultSize == 2);
typedef typename
IfBool<value, VigraTrueType, VigraFalseType>::type
type;
};
template <class T>
struct IsIterator
{
typedef char falseResult[1];
typedef char trueResult[2];
static falseResult * test(...);
template <class U>
static trueResult * test(U *, typename U::iterator_category * = 0);
enum { resultSize = sizeof(*test((T*)0)) };
static const bool value = (resultSize == 2);
typedef typename
IfBool<value, VigraTrueType, VigraFalseType>::type
type;
};
template <class T>
struct IsIterator<T*>
{
static const bool value = true;
typedef VigraTrueType type;
};
template <class T>
struct IsIterator<T const *>
{
static const bool value = true;
typedef VigraTrueType type;
};
} // namespace vigra } // namespace vigra
#endif /* VIGRA_METAPROGRAMMING_HXX */ #endif /* VIGRA_METAPROGRAMMING_HXX */
 End of changes. 22 change blocks. 
35 lines changed or deleted 208 lines changed or added


 multi_array.hxx   multi_array.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2003-2008 by Gunnar Kedenburg and Ullrich Koethe */ /* Copyright 2003-2008 by Gunnar Kedenburg and Ullrich Koethe */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 52 skipping to change at line 51
#include "accessor.hxx" #include "accessor.hxx"
#include "tinyvector.hxx" #include "tinyvector.hxx"
#include "rgbvalue.hxx" #include "rgbvalue.hxx"
#include "basicimageview.hxx" #include "basicimageview.hxx"
#include "imageiterator.hxx" #include "imageiterator.hxx"
#include "numerictraits.hxx" #include "numerictraits.hxx"
#include "multi_iterator.hxx" #include "multi_iterator.hxx"
#include "metaprogramming.hxx" #include "metaprogramming.hxx"
#include "mathutil.hxx" #include "mathutil.hxx"
// Bounds checking Macro used if VIGRA_CHECK_BOUNDS is defined.
#ifdef VIGRA_CHECK_BOUNDS
#define VIGRA_ASSERT_INSIDE(diff) \
vigra_precondition(this->isInside(diff), "Index out of bounds")
#else
#define VIGRA_ASSERT_INSIDE(diff)
#endif
namespace vigra namespace vigra
{ {
namespace detail namespace detail
{ {
/********************************************************/ /********************************************************/
/* */ /* */
/* defaultStride */ /* defaultStride */
/* */ /* */
/********************************************************/ /********************************************************/
skipping to change at line 333 skipping to change at line 340
} }
#define VIGRA_COPY_MULTI_ARRAY_DATA(name, op) \ #define VIGRA_COPY_MULTI_ARRAY_DATA(name, op) \
template <class SrcIterator, class Shape, class DestIterator> \ template <class SrcIterator, class Shape, class DestIterator> \
inline void \ inline void \
name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me taInt<0>) \ name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me taInt<0>) \
{ \ { \
SrcIterator send = s + shape[0]; \ SrcIterator send = s + shape[0]; \
for(; s < send; ++s, ++d) \ for(; s < send; ++s, ++d) \
{ \ { \
*d op *s; \ *d op detail::RequiresExplicitCast<typename DestIterator::value_typ e>::cast(*s); \
} \ } \
} \ } \
\ \
template <class SrcIterator, class Shape, class DestIterator, int N> \ template <class SrcIterator, class Shape, class DestIterator, int N> \
void \ void \
name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me taInt<N>) \ name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me taInt<N>) \
{ \ { \
SrcIterator send = s + shape[N]; \ SrcIterator send = s + shape[N]; \
for(; s < send; ++s, ++d) \ for(; s < send; ++s, ++d) \
{ \ { \
skipping to change at line 355 skipping to change at line 362
} \ } \
} \ } \
\ \
template <class DestIterator, class Shape, class T> \ template <class DestIterator, class Shape, class T> \
inline void \ inline void \
name##ScalarMultiArrayData(DestIterator d, Shape const & shape, T const & i nit, MetaInt<0>) \ name##ScalarMultiArrayData(DestIterator d, Shape const & shape, T const & i nit, MetaInt<0>) \
{ \ { \
DestIterator dend = d + shape[0]; \ DestIterator dend = d + shape[0]; \
for(; d < dend; ++d) \ for(; d < dend; ++d) \
{ \ { \
*d op init; \ *d op detail::RequiresExplicitCast<typename DestIterator::value_typ e>::cast(init); \
} \ } \
} \ } \
\ \
template <class DestIterator, class Shape, class T, int N> \ template <class DestIterator, class Shape, class T, int N> \
void \ void \
name##ScalarMultiArrayData(DestIterator d, Shape const & shape, T const & i nit, MetaInt<N>) \ name##ScalarMultiArrayData(DestIterator d, Shape const & shape, T const & i nit, MetaInt<N>) \
{ \ { \
DestIterator dend = d + shape[N]; \ DestIterator dend = d + shape[N]; \
for(; d < dend; ++d) \ for(; d < dend; ++d) \
{ \ { \
skipping to change at line 676 skipping to change at line 683
/** pointer to the image. /** pointer to the image.
*/ */
pointer m_ptr; pointer m_ptr;
template <class U, class CN> template <class U, class CN>
void copyImpl(const MultiArrayView <N, U, CN>& rhs); void copyImpl(const MultiArrayView <N, U, CN>& rhs);
template <class U, class CN> template <class U, class CN>
void swapDataImpl(MultiArrayView <N, U, CN> rhs); void swapDataImpl(MultiArrayView <N, U, CN> rhs);
template <class CN>
bool arraysOverlap(const MultiArrayView <N, T, CN>& rhs) const;
template <class U, class CN> template <class U, class CN>
bool arraysOverlap(const MultiArrayView <N, U, CN>& rhs) const; bool arraysOverlap(const MultiArrayView <N, U, CN>&) const
{
return false;
}
public: public:
/** default constructor: create an empty image of size 0. /** default constructor: create an invalid view,
* i.e. hasData() returns false and size() is zero.
*/ */
MultiArrayView () MultiArrayView ()
: m_shape (diff_zero_t(0)), m_stride (diff_zero_t(0)), m_ptr (0) : m_shape (diff_zero_t(0)), m_stride (diff_zero_t(0)), m_ptr (0)
{} {}
/** construct from shape and pointer /** construct from shape and pointer
*/ */
MultiArrayView (const difference_type &shape, pointer ptr) MultiArrayView (const difference_type &shape, pointer ptr)
: m_shape (shape), : m_shape (shape),
m_stride (detail::defaultStride <MultiArrayView<N,T>::actual_dimensio n> (shape)), m_stride (detail::defaultStride <MultiArrayView<N,T>::actual_dimensio n> (shape)),
m_ptr (ptr) m_ptr (ptr)
{} {}
/** construct from shape, strides (offset of a sample to the next) /** Construct from shape, strides (offset of a sample to the
for every dimension) and pointer next) for every dimension, and pointer. (Note that
strides are not given in bytes, but in offsets of the
respective pointer type.)
*/ */
MultiArrayView (const difference_type &shape, MultiArrayView (const difference_type &shape,
const difference_type &stride, const difference_type &stride,
pointer ptr) pointer ptr)
: m_shape (shape), : m_shape (shape),
m_stride (stride), m_stride (stride),
m_ptr (ptr) m_ptr (ptr)
{} {}
/** Assignment. There are 3 cases: /** Assignment. There are 3 cases:
skipping to change at line 789 skipping to change at line 805
MultiArrayView & operator/=(T const & rhs) MultiArrayView & operator/=(T const & rhs)
{ {
detail::copyDivScalarMultiArrayData(traverser_begin(), shape(), rhs , MetaInt<actual_dimension-1>()); detail::copyDivScalarMultiArrayData(traverser_begin(), shape(), rhs , MetaInt<actual_dimension-1>());
return *this; return *this;
} }
/** array access. /** array access.
*/ */
reference operator[] (const difference_type &d) reference operator[] (const difference_type &d)
{ {
VIGRA_ASSERT_INSIDE(d);
return m_ptr [dot (d, m_stride)]; return m_ptr [dot (d, m_stride)];
} }
/** array access. /** array access.
*/ */
const_reference operator[] (const difference_type &d) const const_reference operator[] (const difference_type &d) const
{ {
VIGRA_ASSERT_INSIDE(d);
return m_ptr [dot (d, m_stride)]; return m_ptr [dot (d, m_stride)];
} }
/** equvalent to bindInner(), when M < N.
*/
template <unsigned int M>
MultiArrayView <N-M, T, StridedArrayTag> operator[] (const TinyVector<M
ultiArrayIndex, M> &d) const
{
return bindInner(d);
}
/** array access in scan-order sense. /** array access in scan-order sense.
Mostly useful to support standard indexing for 1-dimensional mu lti-arrays, Mostly useful to support standard indexing for 1-dimensional mu lti-arrays,
but works for any N. Use scanOrderIndexToCoordinate() and but works for any N. Use scanOrderIndexToCoordinate() and
coordinateToScanOrderIndex() for conversion between indices and coordinates. coordinateToScanOrderIndex() for conversion between indices and coordinates.
*/ */
reference operator[](difference_type_1 d) reference operator[](difference_type_1 d)
{ {
VIGRA_ASSERT_INSIDE(scanOrderIndexToCoordinate(d));
return m_ptr [detail::ScanOrderToOffset<actual_dimension>::exec(d, m_shape, m_stride)]; return m_ptr [detail::ScanOrderToOffset<actual_dimension>::exec(d, m_shape, m_stride)];
} }
/** array access in scan-order sense. /** array access in scan-order sense.
Mostly useful to support standard indexing for 1-dimensional mu lti-arrays, Mostly useful to support standard indexing for 1-dimensional mu lti-arrays,
but works for any N. Use scanOrderIndexToCoordinate() and but works for any N. Use scanOrderIndexToCoordinate() and
coordinateToScanOrderIndex() for conversion between indices and coordinates. coordinateToScanOrderIndex() for conversion between indices and coordinates.
*/ */
const_reference operator[](difference_type_1 d) const const_reference operator[](difference_type_1 d) const
{ {
VIGRA_ASSERT_INSIDE(scanOrderIndexToCoordinate(d));
return m_ptr [detail::ScanOrderToOffset<actual_dimension>::exec(d, m_shape, m_stride)]; return m_ptr [detail::ScanOrderToOffset<actual_dimension>::exec(d, m_shape, m_stride)];
} }
/** convert scan-order index to coordinate. /** convert scan-order index to coordinate.
*/ */
difference_type scanOrderIndexToCoordinate(difference_type_1 d) const difference_type scanOrderIndexToCoordinate(difference_type_1 d) const
{ {
difference_type result; difference_type result;
detail::ScanOrderToCoordinate<actual_dimension>::exec(d, m_shape, r esult); detail::ScanOrderToCoordinate<actual_dimension>::exec(d, m_shape, r esult);
return result; return result;
skipping to change at line 839 skipping to change at line 867
*/ */
difference_type_1 coordinateToScanOrderIndex(const difference_type &d) const difference_type_1 coordinateToScanOrderIndex(const difference_type &d) const
{ {
return detail::CoordinateToScanOrder<actual_dimension>::exec(m_shap e, d); return detail::CoordinateToScanOrder<actual_dimension>::exec(m_shap e, d);
} }
/** 1D array access. Use only if N == 1. /** 1D array access. Use only if N == 1.
*/ */
reference operator() (difference_type_1 x) reference operator() (difference_type_1 x)
{ {
VIGRA_ASSERT_INSIDE(difference_type(x));
return m_ptr [detail::CoordinatesToOffest<C>::exec(m_stride, x)]; return m_ptr [detail::CoordinatesToOffest<C>::exec(m_stride, x)];
} }
/** 2D array access. Use only if N == 2. /** 2D array access. Use only if N == 2.
*/ */
reference operator() (difference_type_1 x, difference_type_1 y) reference operator() (difference_type_1 x, difference_type_1 y)
{ {
VIGRA_ASSERT_INSIDE(difference_type(x, y));
return m_ptr [detail::CoordinatesToOffest<C>::exec(m_stride, x, y)] ; return m_ptr [detail::CoordinatesToOffest<C>::exec(m_stride, x, y)] ;
} }
/** 3D array access. Use only if N == 3. /** 3D array access. Use only if N == 3.
*/ */
reference operator() (difference_type_1 x, difference_type_1 y, differe nce_type_1 z) reference operator() (difference_type_1 x, difference_type_1 y, differe nce_type_1 z)
{ {
VIGRA_ASSERT_INSIDE(difference_type(x, y, z));
return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z]; return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z];
} }
/** 4D array access. Use only if N == 4. /** 4D array access. Use only if N == 4.
*/ */
reference operator() (difference_type_1 x, difference_type_1 y, reference operator() (difference_type_1 x, difference_type_1 y,
difference_type_1 z, difference_type_1 u) difference_type_1 z, difference_type_1 u)
{ {
VIGRA_ASSERT_INSIDE(difference_type(x, y, z, u));
return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_str ide[3]*u]; return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_str ide[3]*u];
} }
/** 5D array access. Use only if N == 5. /** 5D array access. Use only if N == 5.
*/ */
reference operator() (difference_type_1 x, difference_type_1 y, differe nce_type_1 z, reference operator() (difference_type_1 x, difference_type_1 y, differe nce_type_1 z,
difference_type_1 u, difference_type_1 v) difference_type_1 u, difference_type_1 v)
{ {
VIGRA_ASSERT_INSIDE(difference_type(x, y,z, u,v));
return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_str ide[3]*u + m_stride[4]*v]; return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_str ide[3]*u + m_stride[4]*v];
} }
/** 1D const array access. Use only if N == 1. /** 1D const array access. Use only if N == 1.
*/ */
const_reference operator() (difference_type_1 x) const const_reference operator() (difference_type_1 x) const
{ {
VIGRA_ASSERT_INSIDE(difference_type(x));
return m_ptr [detail::CoordinatesToOffest<C>::exec(m_stride, x)]; return m_ptr [detail::CoordinatesToOffest<C>::exec(m_stride, x)];
} }
/** 2D const array access. Use only if N == 2. /** 2D const array access. Use only if N == 2.
*/ */
const_reference operator() (difference_type_1 x, difference_type_1 y) c onst const_reference operator() (difference_type_1 x, difference_type_1 y) c onst
{ {
VIGRA_ASSERT_INSIDE(difference_type(x, y));
return m_ptr [detail::CoordinatesToOffest<C>::exec(m_stride, x, y)] ; return m_ptr [detail::CoordinatesToOffest<C>::exec(m_stride, x, y)] ;
} }
/** 3D const array access. Use only if N == 3. /** 3D const array access. Use only if N == 3.
*/ */
const_reference operator() (difference_type_1 x, difference_type_1 y, d ifference_type_1 z) const const_reference operator() (difference_type_1 x, difference_type_1 y, d ifference_type_1 z) const
{ {
VIGRA_ASSERT_INSIDE(difference_type(x,y,z));
return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z]; return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z];
} }
/** 4D const array access. Use only if N == 4. /** 4D const array access. Use only if N == 4.
*/ */
const_reference operator() (difference_type_1 x, difference_type_1 y, const_reference operator() (difference_type_1 x, difference_type_1 y,
difference_type_1 z, difference_type_1 u) c onst difference_type_1 z, difference_type_1 u) c onst
{ {
VIGRA_ASSERT_INSIDE(difference_type(x,y,z,u));
return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_str ide[3]*u]; return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_str ide[3]*u];
} }
/** 5D const array access. Use only if N == 5. /** 5D const array access. Use only if N == 5.
*/ */
const_reference operator() (difference_type_1 x, difference_type_1 y, d ifference_type_1 z, const_reference operator() (difference_type_1 x, difference_type_1 y, d ifference_type_1 z,
difference_type_1 u, difference_type_1 v) c onst difference_type_1 u, difference_type_1 v) c onst
{ {
VIGRA_ASSERT_INSIDE(difference_type(x,y,z,u,v));
return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_str ide[3]*u + m_stride[4]*v]; return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_str ide[3]*u + m_stride[4]*v];
} }
/** Init with a constant. /** Init with a constant.
*/ */
template <class U> template <class U>
MultiArrayView & init(const U & init) MultiArrayView & init(const U & init)
{ {
detail::copyScalarMultiArrayData(traverser_begin(), shape(), init, MetaInt<actual_dimension-1>()); detail::copyScalarMultiArrayData(traverser_begin(), shape(), init, MetaInt<actual_dimension-1>());
return *this; return *this;
skipping to change at line 1060 skipping to change at line 1098
typedef MultiArray<3, double>::difference_type Shape; typedef MultiArray<3, double>::difference_type Shape;
MultiArray<3, double> array3(Shape(40, 30, 20)); MultiArray<3, double> array3(Shape(40, 30, 20));
// get a 2D array by fixing index 2 to 15 // get a 2D array by fixing index 2 to 15
MultiArrayView <2, double, StridedArrayTag> array2 = array3.bin dAt(2, 15); MultiArrayView <2, double, StridedArrayTag> array2 = array3.bin dAt(2, 15);
\endcode \endcode
*/ */
MultiArrayView <N-1, T, StridedArrayTag> MultiArrayView <N-1, T, StridedArrayTag>
bindAt (difference_type_1 m, difference_type_1 d) const; bindAt (difference_type_1 m, difference_type_1 d) const;
/** Add a singleton dimension (dimension of legth 1).
Singleton dimensions don't change the size of the data, but int
roduce
a new index that can only take the value 0. This is mainly usef
ul for
the 'reduce mode' of transformMultiArray() and combineTwoMultiA
rrays(),
because these functions require the source and destination arra
ys to
have the same number of dimensions.
The range of \a i must be <tt>0 <= i <= N</tt>. The new dimensi
on will become
the i'th index, and the old indices from i upwards will shift o
ne
place to the right.
<b>Usage:</b>
Suppose we want have a 2D array and want to create a 1D array t
hat contains
the row average of the first array.
\code
typedef MultiArrayShape<2>::type Shape2;
MultiArray<2, double> original(Shape2(40, 30));
typedef MultiArrayShape<1>::type Shape1;
MultiArray<1, double> rowAverages(Shape1(30));
// temporarily add a singleton dimension to the destination arr
ay
transformMultiArray(srcMultiArrayRange(original),
destMultiArrayRange(rowAverages.insertSingl
etonDimension(0)),
FindAverage<double>());
\endcode
*/
MultiArrayView <N+1, T, C>
insertSingletonDimension (difference_type_1 i) const;
/** create a rectangular subarray that spans between the /** create a rectangular subarray that spans between the
points p and q, where p is in the subarray, q not. points p and q, where p is in the subarray, q not.
<b>Usage:</b> <b>Usage:</b>
\code \code
// create a 3D array of size 40x30x20 // create a 3D array of size 40x30x20
typedef MultiArray<3, double>::difference_type Shape; typedef MultiArray<3, double>::difference_type Shape;
MultiArray<3, double> array3(Shape(40, 30, 20)); MultiArray<3, double> array3(Shape(40, 30, 20));
// get a subarray set is smaller by one element at all sides // get a subarray set is smaller by one element at all sides
skipping to change at line 1092 skipping to change at line 1162
for example, multiplying the stride of dimension one by three for example, multiplying the stride of dimension one by three
turns an appropriately layed out (interleaved) rgb image into turns an appropriately layed out (interleaved) rgb image into
a single band image. a single band image.
*/ */
MultiArrayView <N, T, StridedArrayTag> MultiArrayView <N, T, StridedArrayTag>
stridearray (const difference_type &s) const stridearray (const difference_type &s) const
{ {
difference_type shape = m_shape; difference_type shape = m_shape;
for (unsigned int i = 0; i < actual_dimension; ++i) for (unsigned int i = 0; i < actual_dimension; ++i)
shape [i] /= s [i]; shape [i] /= s [i];
return MultiArrayView <N, T, StridedArrayTag> return MultiArrayView <N, T, StridedArrayTag>(shape, m_stride * s,
(shape, m_stride * s, m_ptr); m_ptr);
} }
/** permute the dimensions of the array. /** Transpose an array. If N==2, this implements the usual matrix t
The function exchanges the meaning of the dimensions without co ransposition.
pying the data. For N > 2, it reverses the order of the indices.
In case of a 2-dimensional array, this is simply array transpos
ition. In higher dimensions,
there are more possibilities.
<b>Usage:</b><br> <b>Usage:</b><br>
\code \code
typedef MultiArray<2, double>::difference_type Shape; typedef MultiArray<2, double>::difference_type Shape;
MultiArray<2, double> array(10, 20); MultiArray<2, double> array(10, 20);
MultiArray<2, double, StridedArrayTag> transposed = array.permu teDimensions(Shape(1,0)); MultiArray<2, double, StridedArrayTag> transposed = array.trans pose();
for(int i=0; i<array.shape(0), ++i) for(int i=0; i<array.shape(0), ++i)
for(int j=0; j<array.shape(1); ++j) for(int j=0; j<array.shape(1); ++j)
assert(array(i, j) == transposed(j, i)); assert(array(i, j) == transposed(j, i));
\endcode \endcode
*/ */
MultiArrayView <N, T, StridedArrayTag> MultiArrayView <N, T, StridedArrayTag>
permuteDimensions (const difference_type &s) const transpose () const
{ {
difference_type shape, stride, check((typename difference_type::val difference_type shape(m_shape.begin(), difference_type::ReverseCopy
ue_type)0); ),
for (unsigned int i = 0; i < actual_dimension; ++i) stride(m_stride.begin(), difference_type::ReverseCo
{ py);
shape[i] = m_shape[s[i]];
stride[i] = m_stride[s[i]];
++check[s[i]];
}
vigra_precondition(check == difference_type(1),
"MultiArrayView::permuteDimensions(): every dimension must occur
exactly once.");
return MultiArrayView <N, T, StridedArrayTag>(shape, stride, m_ptr) ; return MultiArrayView <N, T, StridedArrayTag>(shape, stride, m_ptr) ;
} }
/** transpose a 2-dimensional array. Use only if N==2. /** permute the dimensions of the array.
The function exchanges the meaning of the dimensions without co
pying the data.
In case of a 2-dimensional array, this is simply array transpos
ition. In higher dimensions,
there are more possibilities.
<b>Usage:</b><br> <b>Usage:</b><br>
\code \code
typedef MultiArray<2, double>::difference_type Shape; typedef MultiArray<2, double>::difference_type Shape;
MultiArray<2, double> array(10, 20); MultiArray<2, double> array(10, 20);
MultiArray<2, double, StridedArrayTag> transposed = array.trans pose(); MultiArray<2, double, StridedArrayTag> transposed = array.permu teDimensions(Shape(1,0));
for(int i=0; i<array.shape(0), ++i) for(int i=0; i<array.shape(0), ++i)
for(int j=0; j<array.shape(1); ++j) for(int j=0; j<array.shape(1); ++j)
assert(array(i, j) == transposed(j, i)); assert(array(i, j) == transposed(j, i));
\endcode \endcode
*/ */
MultiArrayView <2, T, StridedArrayTag> MultiArrayView <N, T, StridedArrayTag>
transpose () const permuteDimensions (const difference_type &s) const;
/** Permute the dimensions of the array so that the strides are in
ascending order.
Determines the appropriate permutation and then calls permuteDi
mensions().
*/
MultiArrayView <N, T, StridedArrayTag>
permuteStridesAscending() const;
/** Permute the dimensions of the array so that the strides are in
descending order.
Determines the appropriate permutation and then calls permuteDi
mensions().
*/
MultiArrayView <N, T, StridedArrayTag>
permuteStridesDescending() const;
/** Compute the ordering of the strides in this array.
The result is describes the current permutation of the axes rel
ative
to the standard ascending stride order.
*/
difference_type strideOrdering() const
{ {
difference_type shape(m_shape[1], m_shape[0]), return strideOrdering(m_stride);
stride(m_stride[1], m_stride[0]);
return MultiArrayView <2, T, StridedArrayTag>(shape, stride, m_ptr)
;
} }
/** Compute the ordering of the given strides.
The result is describes the current permutation of the axes rel
ative
to the standard ascending stride order.
*/
static difference_type strideOrdering(difference_type strides);
/** number of the elements in the array. /** number of the elements in the array.
*/ */
difference_type_1 elementCount () const difference_type_1 elementCount () const
{ {
difference_type_1 ret = m_shape[0]; difference_type_1 ret = m_shape[0];
for(int i = 1; i < actual_dimension; ++i) for(int i = 1; i < actual_dimension; ++i)
ret *= m_shape[i]; ret *= m_shape[i];
return ret; return ret;
} }
skipping to change at line 1266 skipping to change at line 1351
*/ */
typename NormTraits<MultiArrayView>::NormType norm(int type = 2, bool u seSquaredNorm = true) const; typename NormTraits<MultiArrayView>::NormType norm(int type = 2, bool u seSquaredNorm = true) const;
/** return the pointer to the image data /** return the pointer to the image data
*/ */
pointer data () const pointer data () const
{ {
return m_ptr; return m_ptr;
} }
/**
* returns true iff this view refers to valid data,
* i.e. data() is not a NULL pointer. (this is false after
* default construction.)
*/
bool hasData () const
{
return m_ptr != 0;
}
/** returns the N-dimensional MultiIterator pointing /** returns the N-dimensional MultiIterator pointing
to the first element in every dimension. to the first element in every dimension.
*/ */
traverser traverser_begin () traverser traverser_begin ()
{ {
traverser ret (m_ptr, m_stride.begin (), m_shape.begin ()); traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
return ret; return ret;
} }
/** returns the N-dimensional MultiIterator pointing /** returns the N-dimensional MultiIterator pointing
skipping to change at line 1332 skipping to change at line 1427
m_shape = rhs.m_shape; m_shape = rhs.m_shape;
m_stride = rhs.m_stride; m_stride = rhs.m_stride;
m_ptr = rhs.m_ptr; m_ptr = rhs.m_ptr;
} }
else else
this->copyImpl(rhs); this->copyImpl(rhs);
return *this; return *this;
} }
template <unsigned int N, class T, class C> template <unsigned int N, class T, class C>
template <class U, class CN> template <class CN>
bool bool
MultiArrayView <N, T, C>::arraysOverlap(const MultiArrayView <N, U, CN>& rh s) const MultiArrayView <N, T, C>::arraysOverlap(const MultiArrayView <N, T, CN>& rh s) const
{ {
vigra_precondition (shape () == rhs.shape (), vigra_precondition (shape () == rhs.shape (),
"MultiArrayView::arraysOverlap(): shape mismatch."); "MultiArrayView::arraysOverlap(): shape mismatch.");
const_pointer first_element = this->m_ptr, const_pointer first_element = this->m_ptr,
last_element = first_element + dot(this->m_shape - differ ence_type(1), this->m_stride); last_element = first_element + dot(this->m_shape - differ ence_type(1), this->m_stride);
typename MultiArrayView <N, U, CN>::const_pointer typename MultiArrayView <N, T, CN>::const_pointer
rhs_first_element = rhs.data(), rhs_first_element = rhs.data(),
rhs_last_element = rhs_first_element + dot(rhs.shape() - differe nce_type(1), rhs.stride()); rhs_last_element = rhs_first_element + dot(rhs.shape() - differe nce_type(1), rhs.stride());
return !(last_element < rhs_first_element || rhs_last_element < first_e lement); return !(last_element < rhs_first_element || rhs_last_element < first_e lement);
} }
template <unsigned int N, class T, class C> template <unsigned int N, class T, class C>
template <class U, class CN> template <class U, class CN>
void void
MultiArrayView <N, T, C>::copyImpl(const MultiArrayView <N, U, CN>& rhs) MultiArrayView <N, T, C>::copyImpl(const MultiArrayView <N, U, CN>& rhs)
{ {
skipping to change at line 1421 skipping to change at line 1516
{ {
// overlap: we got different views to the same data -- copy to inte rmediate memory in order to avoid // overlap: we got different views to the same data -- copy to inte rmediate memory in order to avoid
// overwriting elements that are still needed. // overwriting elements that are still needed.
MultiArray<N, T> tmp(*this); MultiArray<N, T> tmp(*this);
copy(rhs); copy(rhs);
rhs.copy(tmp); rhs.copy(tmp);
} }
} }
template <unsigned int N, class T, class C> template <unsigned int N, class T, class C>
MultiArrayView <N, T, StridedArrayTag>
MultiArrayView <N, T, C>::permuteDimensions (const difference_type &s) cons
t
{
difference_type shape, stride, check((typename difference_type::value_t
ype)0);
for (unsigned int i = 0; i < actual_dimension; ++i)
{
shape[i] = m_shape[s[i]];
stride[i] = m_stride[s[i]];
++check[s[i]];
}
vigra_precondition(check == difference_type(1),
"MultiArrayView::permuteDimensions(): every dimension must occur exa
ctly once.");
return MultiArrayView <N, T, StridedArrayTag>(shape, stride, m_ptr);
}
template <unsigned int N, class T, class C>
typename MultiArrayView <N, T, C>::difference_type
MultiArrayView <N, T, C>::strideOrdering(difference_type stride)
{
difference_type permutation;
for(unsigned int k=0; k<N; ++k)
permutation[k] = k;
for(unsigned int k=0; k<N-1; ++k)
{
unsigned int smallest = k;
for(unsigned int j=k+1; j<N; ++j)
{
if(stride[j] < stride[smallest])
smallest = j;
}
if(smallest != k)
{
std::swap(stride[k], stride[smallest]);
std::swap(permutation[k], permutation[smallest]);
}
}
difference_type ordering;
for(unsigned int k=0; k<N; ++k)
ordering[permutation[k]] = k;
return ordering;
}
template <unsigned int N, class T, class C>
MultiArrayView <N, T, StridedArrayTag>
MultiArrayView <N, T, C>::permuteStridesAscending() const
{
difference_type ordering(strideOrdering(m_stride)), permutation;
for(MultiArrayIndex k=0; k<N; ++k)
permutation[ordering[k]] = k;
return permuteDimensions(permutation);
}
template <unsigned int N, class T, class C>
MultiArrayView <N, T, StridedArrayTag>
MultiArrayView <N, T, C>::permuteStridesDescending() const
{
difference_type ordering(strideOrdering(m_stride)), permutation;
for(MultiArrayIndex k=0; k<N; ++k)
permutation[ordering[N-1-k]] = k;
return permuteDimensions(permutation);
}
template <unsigned int N, class T, class C>
template <unsigned int M> template <unsigned int M>
MultiArrayView <N-M, T, C> MultiArrayView <N-M, T, C>
MultiArrayView <N, T, C>::bindOuter (const TinyVector <MultiArrayIndex, M> &d) const MultiArrayView <N, T, C>::bindOuter (const TinyVector <MultiArrayIndex, M> &d) const
{ {
TinyVector <MultiArrayIndex, M> stride; TinyVector <MultiArrayIndex, M> stride;
stride.init (m_stride.begin () + N-M, m_stride.end ()); stride.init (m_stride.begin () + N-M, m_stride.end ());
pointer ptr = m_ptr + dot (d, stride); pointer ptr = m_ptr + dot (d, stride);
static const int NNew = (N-M == 0) ? 1 : N-M; static const int NNew = (N-M == 0) ? 1 : N-M;
TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride; TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride;
if (N-M == 0) if (N-M == 0)
skipping to change at line 1562 skipping to change at line 1720
shape.begin () + n); shape.begin () + n);
std::copy (m_stride.begin (), m_stride.begin () + n, stride.begin ( )); std::copy (m_stride.begin (), m_stride.begin () + n, stride.begin ( ));
std::copy (m_stride.begin () + n+1, m_stride.end (), std::copy (m_stride.begin () + n+1, m_stride.end (),
stride.begin () + n); stride.begin () + n);
} }
return MultiArrayView <N-1, T, StridedArrayTag> return MultiArrayView <N-1, T, StridedArrayTag>
(shape, stride, m_ptr + d * m_stride[n]); (shape, stride, m_ptr + d * m_stride[n]);
} }
template <unsigned int N, class T, class C> template <unsigned int N, class T, class C>
MultiArrayView <N + 1, T, C>
MultiArrayView <N, T, C>::insertSingletonDimension (difference_type_1 i) co
nst
{
vigra_precondition (
0 <= i && i <= static_cast <difference_type_1> (N),
"MultiArrayView <N, T, C>::insertSingletonDimension(): index out of
range.");
TinyVector <MultiArrayIndex, N+1> shape, stride;
std::copy (m_shape.begin (), m_shape.begin () + i, shape.begin ());
std::copy (m_shape.begin () + i, m_shape.end (), shape.begin () + i + 1
);
std::copy (m_stride.begin (), m_stride.begin () + i, stride.begin ());
std::copy (m_stride.begin () + i, m_stride.end (), stride.begin () + i
+ 1);
shape[i] = 1;
stride[i] = 1;
return MultiArrayView <N+1, T, C>(shape, stride, m_ptr);
}
template <unsigned int N, class T, class C>
typename NormTraits<MultiArrayView <N, T, C> >::NormType typename NormTraits<MultiArrayView <N, T, C> >::NormType
MultiArrayView <N, T, C>::norm(int type, bool useSquaredNorm) const MultiArrayView <N, T, C>::norm(int type, bool useSquaredNorm) const
{ {
typedef typename NormTraits<MultiArrayView>::NormType NormType; typedef typename NormTraits<MultiArrayView>::NormType NormType;
switch(type) switch(type)
{ {
case 0: case 0:
{ {
NormType res = NumericTraits<NormType>::zero(); NormType res = NumericTraits<NormType>::zero();
skipping to change at line 1914 skipping to change at line 2090
/** init elements with a constant /** init elements with a constant
*/ */
template <class U> template <class U>
MultiArray & init(const U & init) MultiArray & init(const U & init)
{ {
view_type::init(init); view_type::init(init);
return *this; return *this;
} }
/** change the shape and allocate new memory.<br> /** Allocate new memory with the given shape and initialize with ze ros.<br>
<em>Note:</em> this operation invalidates all dependent objects <em>Note:</em> this operation invalidates all dependent objects
(array views and iterators) (array views and iterators)
*/ */
void reshape (const difference_type &shape) void reshape (const difference_type &shape)
{ {
reshape (shape, NumericTraits <T>::zero ()); reshape (shape, NumericTraits <T>::zero ());
} }
/** change the shape, allocate new memory and initialize it /** Allocate new memory with the given shape and initialize it
with the given value.<br> with the given value.<br>
<em>Note:</em> this operation invalidates all dependent objects <em>Note:</em> this operation invalidates all dependent objects
(array views and iterators) (array views and iterators)
*/ */
void reshape (const difference_type &shape, const_reference init); void reshape (const difference_type &shape, const_reference init);
/** Swap the contents with another MultiArray. This is fast, /** Swap the contents with another MultiArray. This is fast,
because no data are copied, but only pointers and shapes swappe d. because no data are copied, but only pointers and shapes swappe d.
<em>Note:</em> this operation invalidates all dependent objects <em>Note:</em> this operation invalidates all dependent objects
(array views and iterators) (array views and iterators)
skipping to change at line 2255 skipping to change at line 2431
template <unsigned int N, class T, class C, class Accessor> template <unsigned int N, class T, class C, class Accessor>
inline pair<typename MultiArrayView<N,T,C>::traverser, inline pair<typename MultiArrayView<N,T,C>::traverser,
Accessor > Accessor >
destMultiArray( MultiArrayView<N,T,C> & array, Accessor a ) destMultiArray( MultiArrayView<N,T,C> & array, Accessor a )
{ {
return pair<typename MultiArrayView<N,T,C>::traverser, return pair<typename MultiArrayView<N,T,C>::traverser,
Accessor > Accessor >
( array.traverser_begin(), a ); ( array.traverser_begin(), a );
} }
/********************************************************************/
template <class PixelType, class Accessor>
inline triple<ConstStridedImageIterator<PixelType>,
ConstStridedImageIterator<PixelType>, Accessor>
srcImageRange(const MultiArrayView<2, PixelType, StridedArrayTag> & img, Ac
cessor a)
{
ConstStridedImageIterator<PixelType>
ul(img.data(), 1, img.stride(0), img.stride(1));
return triple<ConstStridedImageIterator<PixelType>,
ConstStridedImageIterator<PixelType>,
Accessor>(
ul, ul + Size2D(img.shape(0), img.shape(1)), a);
}
template <class PixelType, class Accessor>
inline pair<ConstStridedImageIterator<PixelType>, Accessor>
srcImage(const MultiArrayView<2, PixelType, StridedArrayTag> & img, Accesso
r a)
{
ConstStridedImageIterator<PixelType>
ul(img.data(), 1, img.stride(0), img.stride(1));
return pair<ConstStridedImageIterator<PixelType>, Accessor>
(ul, a);
}
template <class PixelType, class Accessor>
inline triple<StridedImageIterator<PixelType>,
StridedImageIterator<PixelType>, Accessor>
destImageRange(MultiArrayView<2, PixelType, StridedArrayTag> & img, Accesso
r a)
{
StridedImageIterator<PixelType>
ul(img.data(), 1, img.stride(0), img.stride(1));
return triple<StridedImageIterator<PixelType>,
StridedImageIterator<PixelType>,
Accessor>(
ul, ul + Size2D(img.shape(0), img.shape(1)), a);
}
template <class PixelType, class Accessor>
inline pair<StridedImageIterator<PixelType>, Accessor>
destImage(MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
{
StridedImageIterator<PixelType>
ul(img.data(), 1, img.stride(0), img.stride(1));
return pair<StridedImageIterator<PixelType>, Accessor>
(ul, a);
}
template <class PixelType, class Accessor>
inline pair<StridedImageIterator<PixelType>, Accessor>
maskImage(MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
{
StridedImageIterator<PixelType>
ul(img.data(), 1, img.stride(0), img.stride(1));
return pair<StridedImageIterator<PixelType>, Accessor>
(ul, a);
}
// -------------------------------------------------------------------
template <class PixelType>
inline triple<ConstStridedImageIterator<PixelType>,
ConstStridedImageIterator<PixelType>,
typename AccessorTraits<PixelType>::default_const_accessor>
srcImageRange(MultiArrayView<2, PixelType, StridedArrayTag> const & img)
{
ConstStridedImageIterator<PixelType>
ul(img.data(), 1, img.stride(0), img.stride(1));
typedef typename AccessorTraits<PixelType>::default_const_accessor Acce
ssor;
return triple<ConstStridedImageIterator<PixelType>,
ConstStridedImageIterator<PixelType>,
Accessor>
(ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
}
template <class PixelType>
inline triple<ConstImageIterator<PixelType>,
ConstImageIterator<PixelType>,
typename AccessorTraits<PixelType>::default_const_accessor>
srcImageRange(MultiArrayView<2, PixelType, UnstridedArrayTag> const & img)
{
ConstImageIterator<PixelType>
ul(img.data(), img.stride(1));
typedef typename AccessorTraits<PixelType>::default_const_accessor Acce
ssor;
return triple<ConstImageIterator<PixelType>,
ConstImageIterator<PixelType>,
Accessor>
(ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
}
template <class PixelType>
inline pair< ConstStridedImageIterator<PixelType>,
typename AccessorTraits<PixelType>::default_const_accessor>
srcImage(MultiArrayView<2, PixelType, StridedArrayTag> const & img)
{
ConstStridedImageIterator<PixelType>
ul(img.data(), 1, img.stride(0), img.stride(1));
typedef typename AccessorTraits<PixelType>::default_const_accessor Acce
ssor;
return pair<ConstStridedImageIterator<PixelType>,
Accessor>
(ul, Accessor());
}
template <class PixelType>
inline pair< ConstImageIterator<PixelType>,
typename AccessorTraits<PixelType>::default_const_accessor>
srcImage(MultiArrayView<2, PixelType, UnstridedArrayTag> const & img)
{
ConstImageIterator<PixelType>
ul(img.data(), img.stride(1));
typedef typename AccessorTraits<PixelType>::default_const_accessor Acce
ssor;
return pair<ConstImageIterator<PixelType>,
Accessor>
(ul, Accessor());
}
template <class PixelType>
inline triple< StridedImageIterator<PixelType>,
StridedImageIterator<PixelType>,
typename AccessorTraits<PixelType>::default_accessor>
destImageRange(MultiArrayView<2, PixelType, StridedArrayTag> & img)
{
StridedImageIterator<PixelType>
ul(img.data(), 1, img.stride(0), img.stride(1));
typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
return triple<StridedImageIterator<PixelType>,
StridedImageIterator<PixelType>,
Accessor>
(ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
}
template <class PixelType>
inline triple< ImageIterator<PixelType>,
ImageIterator<PixelType>,
typename AccessorTraits<PixelType>::default_accessor>
destImageRange(MultiArrayView<2, PixelType, UnstridedArrayTag> & img)
{
ImageIterator<PixelType>
ul(img.data(), img.stride(1));
typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
return triple<ImageIterator<PixelType>,
ImageIterator<PixelType>,
Accessor>
(ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
}
template <class PixelType>
inline pair< StridedImageIterator<PixelType>,
typename AccessorTraits<PixelType>::default_accessor>
destImage(MultiArrayView<2, PixelType, StridedArrayTag> & img)
{
StridedImageIterator<PixelType>
ul(img.data(), 1, img.stride(0), img.stride(1));
typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
return pair<StridedImageIterator<PixelType>, Accessor>
(ul, Accessor());
}
template <class PixelType>
inline pair< ImageIterator<PixelType>,
typename AccessorTraits<PixelType>::default_accessor>
destImage(MultiArrayView<2, PixelType, UnstridedArrayTag> & img)
{
ImageIterator<PixelType> ul(img.data(), img.stride(1));
typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
return pair<ImageIterator<PixelType>, Accessor>(ul, Accessor());
}
template <class PixelType>
inline pair< ConstStridedImageIterator<PixelType>,
typename AccessorTraits<PixelType>::default_accessor>
maskImage(MultiArrayView<2, PixelType, StridedArrayTag> const & img)
{
ConstStridedImageIterator<PixelType>
ul(img.data(), 1, img.stride(0), img.stride(1));
typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
return pair<ConstStridedImageIterator<PixelType>, Accessor>
(ul, Accessor());
}
template <class PixelType>
inline pair< ConstImageIterator<PixelType>,
typename AccessorTraits<PixelType>::default_accessor>
maskImage(MultiArrayView<2, PixelType, UnstridedArrayTag> const & img)
{
ConstImageIterator<PixelType>
ul(img.data(), img.stride(1));
typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
return pair<ConstImageIterator<PixelType>, Accessor>
(ul, Accessor());
}
/********************************************************/ /********************************************************/
/* */ /* */
/* makeBasicImageView */ /* makeBasicImageView */
/* */ /* */
/********************************************************/ /********************************************************/
/** \addtogroup MultiArrayToImage Wrap a \ref vigra::MultiArrayView in /** \addtogroup MultiArrayToImage Wrap a \ref vigra::MultiArrayView in
a \ref vigra::BasicImageView a \ref vigra::BasicImageView
*/ */
//@{ //@{
skipping to change at line 2317 skipping to change at line 2685
vigra_precondition ( vigra_precondition (
array.shape (0) == 3, "makeRGBImageView(): array.shape(0) must be 3 ."); array.shape (0) == 3, "makeRGBImageView(): array.shape(0) must be 3 .");
return BasicImageView <RGBValue<T> > ( return BasicImageView <RGBValue<T> > (
reinterpret_cast <RGBValue <T> *> (array.data ()), reinterpret_cast <RGBValue <T> *> (array.data ()),
array.shape (1), array.shape (2)); array.shape (1), array.shape (2));
} }
//@} //@}
} // namespace vigra } // namespace vigra
#undef VIGRA_ASSERT_INSIDE
#endif // VIGRA_MULTI_ARRAY_HXX #endif // VIGRA_MULTI_ARRAY_HXX
 End of changes. 45 change blocks. 
43 lines changed or deleted 442 lines changed or added


 multi_convolution.hxx   multi_convolution.hxx 
//-- -*- c++ -*- //-- -*- c++ -*-
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2003 by Christian-Dennis Rahn */ /* Copyright 2003 by Christian-Dennis Rahn */
/* and Ullrich Koethe */ /* and Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 51 skipping to change at line 49
#define VIGRA_MULTI_CONVOLUTION_H #define VIGRA_MULTI_CONVOLUTION_H
#include "separableconvolution.hxx" #include "separableconvolution.hxx"
#include "array_vector.hxx" #include "array_vector.hxx"
#include "multi_array.hxx" #include "multi_array.hxx"
#include "accessor.hxx" #include "accessor.hxx"
#include "numerictraits.hxx" #include "numerictraits.hxx"
#include "navigator.hxx" #include "navigator.hxx"
#include "metaprogramming.hxx" #include "metaprogramming.hxx"
#include "multi_pointoperators.hxx" #include "multi_pointoperators.hxx"
#include "functorexpression.hxx"
namespace vigra namespace vigra
{ {
namespace detail namespace detail
{ {
/********************************************************/ /********************************************************/
/* */ /* */
/* internalSeparableConvolveMultiArray */ /* internalSeparableConvolveMultiArray */
skipping to change at line 171 skipping to change at line 170
\code \code
namespace vigra { namespace vigra {
// apply the same kernel to all dimensions // apply the same kernel to all dimensions
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor, class T> class DestIterator, class DestAccessor, class T>
void void
separableConvolveMultiArray(SrcIterator siter, SrcShape const & sha pe, SrcAccessor src, separableConvolveMultiArray(SrcIterator siter, SrcShape const & sha pe, SrcAccessor src,
DestIterator diter, DestAccessor dest, DestIterator diter, DestAccessor dest,
Kernel1D<T> const & kernel); Kernel1D<T> const & kernel);
// apply each kernel from the sequence `kernels // apply each kernel from the sequence 'kernels' in turn
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor, class KernelItera tor> class DestIterator, class DestAccessor, class KernelItera tor>
void void
separableConvolveMultiArray(SrcIterator siter, SrcShape const & sha pe, SrcAccessor src, separableConvolveMultiArray(SrcIterator siter, SrcShape const & sha pe, SrcAccessor src,
DestIterator diter, DestAccessor dest, DestIterator diter, DestAccessor dest,
KernelIterator kernels); KernelIterator kernels);
} }
\endcode \endcode
use argument objects in conjunction with \ref ArgumentObjectFactories : use argument objects in conjunction with \ref ArgumentObjectFactories :
\code \code
namespace vigra { namespace vigra {
// apply the same kernel to all dimensions // apply the same kernel to all dimensions
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor, class T> class DestIterator, class DestAccessor, class T>
void void
separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccess or> const & source, separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccess or> const & source,
pair<DestIterator, DestAccessor> const & dest, pair<DestIterator, DestAccessor> const & dest,
Kernel1D<T> const & kernel); Kernel1D<T> const & kernel);
// apply each kernel from the sequence `kernels // apply each kernel from the sequence 'kernels' in turn
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor, class KernelItera tor> class DestIterator, class DestAccessor, class KernelItera tor>
void void
separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccess or> const & source, separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccess or> const & source,
pair<DestIterator, DestAccessor> const & dest, pair<DestIterator, DestAccessor> const & dest,
KernelIterator kernels); KernelIterator kernels);
} }
\endcode \endcode
<b> Usage:</b> <b> Usage:</b>
skipping to change at line 371 skipping to change at line 370
typedef MultiArrayNavigator<SrcIterator, N> SNavigator; typedef MultiArrayNavigator<SrcIterator, N> SNavigator;
typedef MultiArrayNavigator<DestIterator, N> DNavigator; typedef MultiArrayNavigator<DestIterator, N> DNavigator;
SNavigator snav( s, shape, dim ); SNavigator snav( s, shape, dim );
DNavigator dnav( d, shape, dim ); DNavigator dnav( d, shape, dim );
for( ; snav.hasMore(); snav++, dnav++ ) for( ; snav.hasMore(); snav++, dnav++ )
{ {
// first copy source to temp for maximum cache efficiency // first copy source to temp for maximum cache efficiency
copyLine( snav.begin(), snav.end(), src, copyLine( snav.begin(), snav.end(), src,
tmp.begin(), typename AccessorTraits<TmpType>::default_ac cessor() ); tmp.begin(), typename AccessorTraits<TmpType>::default_accessor( ) );
convolveLine( srcIterRange( tmp.begin(), tmp.end(), typename Acces sorTraits<TmpType>::default_const_accessor()), convolveLine( srcIterRange( tmp.begin(), tmp.end(), typename Acces sorTraits<TmpType>::default_const_accessor()),
destIter( dnav.begin(), dest ), destIter( dnav.begin(), dest ),
kernel1d( kernel ) ); kernel1d( kernel ) );
} }
} }
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor, class T> class DestIterator, class DestAccessor, class T>
inline void inline void
skipping to change at line 444 skipping to change at line 443
<b> Usage:</b> <b> Usage:</b>
<b>\#include</b> \<<a href="multi__convolution_8hxx-source.html">vigra/ multi_convolution.hxx</a>\> <b>\#include</b> \<<a href="multi__convolution_8hxx-source.html">vigra/ multi_convolution.hxx</a>\>
\code \code
MultiArray<3, unsigned char>::size_type shape(width, height, depth); MultiArray<3, unsigned char>::size_type shape(width, height, depth);
MultiArray<3, unsigned char> source(shape); MultiArray<3, unsigned char> source(shape);
MultiArray<3, float> dest(shape); MultiArray<3, float> dest(shape);
... ...
// perform isotropic Gaussian smoothing at scale `sigma // perform isotropic Gaussian smoothing at scale 'sigma'
gaussianSmoothMultiArray(srcMultiArrayRange(source), destMultiArray(des t), sigma); gaussianSmoothMultiArray(srcMultiArrayRange(source), destMultiArray(des t), sigma);
\endcode \endcode
\see separableConvolveMultiArray() \see separableConvolveMultiArray()
*/ */
doxygen_overloaded_function(template <...> void gaussianSmoothMultiArray) doxygen_overloaded_function(template <...> void gaussianSmoothMultiArray)
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
gaussianSmoothMultiArray( SrcIterator s, SrcShape const & shape, SrcAccesso r src, gaussianSmoothMultiArray( SrcIterator s, SrcShape const & shape, SrcAccesso r src,
DestIterator d, DestAccessor dest, double sigma ) DestIterator d, DestAccessor dest, double sigma )
{ {
typedef typename NumericTraits<typename DestAccessor::value_type>::Real Kernel1D<double> gauss;
Promote kernel_type;
Kernel1D<kernel_type> gauss;
gauss.initGaussian( sigma ); gauss.initGaussian( sigma );
separableConvolveMultiArray( s, shape, src, d, dest, gauss); separableConvolveMultiArray( s, shape, src, d, dest, gauss);
} }
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline void inline void
gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
pair<DestIterator, DestAccessor> const & dest, pair<DestIterator, DestAccessor> const & dest,
skipping to change at line 537 skipping to change at line 535
MultiArray<3, unsigned char>::size_type shape(width, height, depth); MultiArray<3, unsigned char>::size_type shape(width, height, depth);
MultiArray<3, unsigned char> source(shape); MultiArray<3, unsigned char> source(shape);
MultiArray<3, TinyVector<float, 3> > dest(shape); MultiArray<3, TinyVector<float, 3> > dest(shape);
... ...
// compute Gaussian gradient at scale sigma // compute Gaussian gradient at scale sigma
gaussianGradientMultiArray(srcMultiArrayRange(source), destMultiArray(d est), sigma); gaussianGradientMultiArray(srcMultiArrayRange(source), destMultiArray(d est), sigma);
\endcode \endcode
<b> Required Interface:</b> <b> Required Interface:</b>
see \ref convolveImage(), in addition: see \ref separableConvolveMultiArray(), in addition:
\code \code
int dimension = 0; int dimension = 0;
VectorElementAccessor<DestAccessor> elementAccessor(0, dest); VectorElementAccessor<DestAccessor> elementAccessor(0, dest);
\endcode \endcode
\see separableConvolveMultiArray() \see separableConvolveMultiArray()
*/ */
doxygen_overloaded_function(template <...> void gaussianGradientMultiArray) doxygen_overloaded_function(template <...> void gaussianGradientMultiArray)
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
gaussianGradientMultiArray( SrcIterator si, SrcShape const & shape, SrcAcce gaussianGradientMultiArray(SrcIterator si, SrcShape const & shape, SrcAcces
ssor src, sor src,
DestIterator di, DestAccessor dest, double sigma DestIterator di, DestAccessor dest, double sigma
) )
{ {
typedef typename DestAccessor::value_type DestType; typedef typename DestAccessor::value_type DestType;
typedef typename NumericTraits<typename DestType::value_type>::RealProm typedef typename DestType::value_type DestValueType;
ote kernel_type; typedef typename NumericTraits<DestValueType>::RealPromote KernelType;
Kernel1D<kernel_type> gauss, derivative; static const int N = SrcShape::static_size;
for(int k=0; k<N; ++k)
if(shape[k] <=0)
return;
vigra_precondition(N == dest.size(di),
"gaussianGradientMultiArray(): Wrong number of channels in output a
rray.");
vigra_precondition(sigma > 0.0, "gaussianGradientMultiArray(): Scale mu
st be positive.");
Kernel1D<KernelType> gauss, derivative;
gauss.initGaussian(sigma); gauss.initGaussian(sigma);
derivative.initGaussianDerivative(sigma, 1);
typedef VectorElementAccessor<DestAccessor> ElementAccessor; typedef VectorElementAccessor<DestAccessor> ElementAccessor;
// compute gradient components // compute gradient components
for(unsigned int d = 0; d < shape.size(); ++d ) for(int d = 0; d < N; ++d )
{ {
ArrayVector<Kernel1D<kernel_type> > kernels(shape.size(), gauss); ArrayVector<Kernel1D<KernelType> > kernels(N, gauss);
kernels[d] = derivative; kernels[d].initGaussianDerivative(sigma, 1);
separableConvolveMultiArray( si, shape, src, di, ElementAccessor(d, dest), kernels.begin()); separableConvolveMultiArray( si, shape, src, di, ElementAccessor(d, dest), kernels.begin());
} }
} }
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline void inline void
gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
pair<DestIterator, DestAccessor> const & dest, double sig ma ) pair<DestIterator, DestAccessor> const & dest, d ouble sigma )
{ {
gaussianGradientMultiArray( source.first, source.second, source.third, gaussianGradientMultiArray( source.first, source.second, source.third,
dest.first, dest.second, sigma ); dest.first, dest.second, sigma );
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* symmetricGradientMultiArray */ /* symmetricGradientMultiArray */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Calculate gradient of a multi-dimensional arrays using symmetric difference filters. /** \brief Calculate gradient of a multi-dimensional arrays using symmetric difference filters.
skipping to change at line 637 skipping to change at line 646
MultiArray<3, unsigned char>::size_type shape(width, height, depth); MultiArray<3, unsigned char>::size_type shape(width, height, depth);
MultiArray<3, unsigned char> source(shape); MultiArray<3, unsigned char> source(shape);
MultiArray<3, TinyVector<float, 3> > dest(shape); MultiArray<3, TinyVector<float, 3> > dest(shape);
... ...
// compute gradient // compute gradient
symmetricGradientMultiArray(srcMultiArrayRange(source), destMultiArray( dest)); symmetricGradientMultiArray(srcMultiArrayRange(source), destMultiArray( dest));
\endcode \endcode
<b> Required Interface:</b> <b> Required Interface:</b>
see \ref convolveImage(), in addition: see \ref convolveMultiArrayOneDimension(), in addition:
\code \code
int dimension = 0; int dimension = 0;
VectorElementAccessor<DestAccessor> elementAccessor(0, dest); VectorElementAccessor<DestAccessor> elementAccessor(0, dest);
\endcode \endcode
\see convolveMultiArrayOneDimension() \see convolveMultiArrayOneDimension()
*/ */
doxygen_overloaded_function(template <...> void symmetricGradientMultiArray ) doxygen_overloaded_function(template <...> void symmetricGradientMultiArray )
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
symmetricGradientMultiArray(SrcIterator si, SrcShape const & shape, SrcAcce ssor src, symmetricGradientMultiArray(SrcIterator si, SrcShape const & shape, SrcAcce ssor src,
DestIterator di, DestAccessor dest) DestIterator di, DestAccessor dest)
{ {
typedef typename DestAccessor::value_type DestType; typedef typename DestAccessor::value_type DestType;
typedef typename NumericTraits<typename DestType::value_type>::RealProm typedef typename DestType::value_type DestValueType;
ote kernel_type; typedef typename NumericTraits<DestValueType>::RealPromote KernelType;
Kernel1D<kernel_type> filter; static const int N = SrcShape::static_size;
for(int k=0; k<N; ++k)
if(shape[k] <=0)
return;
vigra_precondition(N == dest.size(di),
"symmetricGradientMultiArray(): Wrong number of channels in output
array.");
Kernel1D<KernelType> filter;
filter.initSymmetricGradient(); filter.initSymmetricGradient();
typedef VectorElementAccessor<DestAccessor> ElementAccessor; typedef VectorElementAccessor<DestAccessor> ElementAccessor;
// compute gradient components // compute gradient components
for(unsigned int d = 0; d < shape.size(); ++d ) for(int d = 0; d < N; ++d )
{ {
convolveMultiArrayOneDimension(si, shape, src, convolveMultiArrayOneDimension(si, shape, src,
di, ElementAccessor(d di, ElementAccessor(d, dest),
, dest), d, filter);
d, filter);
} }
} }
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline void inline void
symmetricGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons t & source, symmetricGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons t & source,
pair<DestIterator, DestAccessor> const & dest ) pair<DestIterator, DestAccessor> const & dest )
{ {
symmetricGradientMultiArray(source.first, source.second, source.third, symmetricGradientMultiArray(source.first, source.second, source.third,
dest.first, dest.second); dest.first, dest.second);
} }
/********************************************************/
/* */
/* laplacianOfGaussianMultiArray */
/* */
/********************************************************/
/** \brief Calculate Laplacian of a N-dimensional arrays using Gaussian der
ivative filters.
This function computes the Laplacian the given N-dimensional
array with a sequence of second-derivative-of-Gaussian filters at the g
iven
standard deviation <tt>sigma</tt>. Both source and destination arrays
are represented by iterators, shape objects and accessors. Both source
and destination
arrays must have scalar value_type. This function is implemented by cal
ls to
\ref separableConvolveMultiArray() with the appropriate kernels, follow
ed by summation.
<b> Declarations:</b>
pass arguments explicitly:
\code
namespace vigra {
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
void
laplacianOfGaussianMultiArray(SrcIterator siter, SrcShape const & s
hape, SrcAccessor src,
DestIterator diter, DestAccessor dest
,
double sigma);
}
\endcode
use argument objects in conjunction with \ref ArgumentObjectFactories :
\code
namespace vigra {
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
void
laplacianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAcce
ssor> const & source,
pair<DestIterator, DestAccessor> cons
t & dest,
double sigma);
}
\endcode
<b> Usage:</b>
<b>\#include</b> \<<a href="multi__convolution_8hxx-source.html">vigra/
multi_convolution.hxx</a>\>
\code
MultiArray<3, float> source(shape);
MultiArray<3, float> laplacian(shape);
...
// compute Laplacian at scale sigma
laplacianOfGaussianMultiArray(srcMultiArrayRange(source), destMultiArra
y(laplacian), sigma);
\endcode
<b> Required Interface:</b>
see \ref separableConvolveMultiArray(), in addition:
\code
int dimension = 0;
VectorElementAccessor<DestAccessor> elementAccessor(0, dest);
\endcode
\see separableConvolveMultiArray()
*/
doxygen_overloaded_function(template <...> void laplacianOfGaussianMultiArr
ay)
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
void
laplacianOfGaussianMultiArray(SrcIterator si, SrcShape const & shape, SrcAc
cessor src,
DestIterator di, DestAccessor dest, double si
gma )
{
using namespace functor;
typedef typename DestAccessor::value_type DestType;
typedef typename NumericTraits<DestType>::RealPromote KernelType;
typedef typename AccessorTraits<KernelType>::default_accessor Derivativ
eAccessor;
static const int N = SrcShape::static_size;
vigra_precondition(sigma > 0.0, "laplacianOfGaussianMultiArray(): Scale
must be positive.");
Kernel1D<KernelType> gauss;
gauss.initGaussian(sigma);
MultiArray<N, KernelType> derivative(shape);
// compute 2nd derivatives and sum them up
for(int d = 0; d < N; ++d )
{
ArrayVector<Kernel1D<KernelType> > kernels(N, gauss);
kernels[d].initGaussianDerivative(sigma, 2);
if(d == 0)
{
separableConvolveMultiArray( si, shape, src,
di, dest, kernels.begin());
}
else
{
separableConvolveMultiArray( si, shape, src,
derivative.traverser_begin(), Deri
vativeAccessor(),
kernels.begin());
combineTwoMultiArrays(di, shape, dest, derivative.traverser_beg
in(), DerivativeAccessor(),
di, dest, Arg1() + Arg2() );
}
}
}
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
inline void
laplacianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> co
nst & source,
pair<DestIterator, DestAccessor> const & dest,
double sigma )
{
laplacianOfGaussianMultiArray( source.first, source.second, source.thir
d,
dest.first, dest.second, sigma );
}
/********************************************************/
/* */
/* hessianOfGaussianMultiArray */
/* */
/********************************************************/
/** \brief Calculate Hessian matrix of a N-dimensional arrays using Gaussia
n derivative filters.
This function computes the Hessian matrix the given scalar N-dimensiona
l
array with a sequence of second-derivative-of-Gaussian filters at the g
iven
standard deviation <tt>sigma</tt>. Both source and destination arrays
are represented by iterators, shape objects and accessors. The destinat
ion array must
have a vector valued element type with N*(N+1)/2 elements (it represent
s the
upper triangular part of the symmetric Hessian matrix). This function i
s implemented by calls to
\ref separableConvolveMultiArray() with the appropriate kernels.
<b> Declarations:</b>
pass arguments explicitly:
\code
namespace vigra {
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
void
hessianOfGaussianMultiArray(SrcIterator siter, SrcShape const & sha
pe, SrcAccessor src,
DestIterator diter, DestAccessor dest,
double sigma);
}
\endcode
use argument objects in conjunction with \ref ArgumentObjectFactories :
\code
namespace vigra {
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
void
hessianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccess
or> const & source,
pair<DestIterator, DestAccessor> const
& dest,
double sigma);
}
\endcode
<b> Usage:</b>
<b>\#include</b> \<<a href="multi__convolution_8hxx-source.html">vigra/
multi_convolution.hxx</a>\>
\code
MultiArray<3, float> source(shape);
MultiArray<3, TinyVector<float, 6> > dest(shape);
...
// compute Hessian at scale sigma
hessianOfGaussianMultiArray(srcMultiArrayRange(source), destMultiArray(
dest), sigma);
\endcode
<b> Required Interface:</b>
see \ref separableConvolveMultiArray(), in addition:
\code
int dimension = 0;
VectorElementAccessor<DestAccessor> elementAccessor(0, dest);
\endcode
\see separableConvolveMultiArray(), vectorToTensorMultiArray()
*/
doxygen_overloaded_function(template <...> void hessianOfGaussianMultiArray
)
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
void
hessianOfGaussianMultiArray(SrcIterator si, SrcShape const & shape, SrcAcce
ssor src,
DestIterator di, DestAccessor dest, double sigm
a )
{
typedef typename DestAccessor::value_type DestType;
typedef typename DestType::value_type DestValueType;
typedef typename NumericTraits<DestValueType>::RealPromote KernelType;
static const int N = SrcShape::static_size;
static const int M = N*(N+1)/2;
for(int k=0; k<N; ++k)
if(shape[k] <=0)
return;
vigra_precondition(M == dest.size(di),
"hessianOfGaussianMultiArray(): Wrong number of channels in output
array.");
vigra_precondition(sigma > 0.0, "hessianOfGaussianMultiArray(): Scale m
ust be positive.");
Kernel1D<KernelType> gauss;
gauss.initGaussian(sigma);
typedef VectorElementAccessor<DestAccessor> ElementAccessor;
// compute elements of the Hessian matrix
for(int b=0, i=0; i<N; ++i)
{
for(int j=i; j<N; ++j, ++b)
{
ArrayVector<Kernel1D<KernelType> > kernels(N, gauss);
if(i == j)
{
kernels[i].initGaussianDerivative(sigma, 2);
}
else
{
kernels[i].initGaussianDerivative(sigma, 1);
kernels[j].initGaussianDerivative(sigma, 1);
}
separableConvolveMultiArray(si, shape, src, di, ElementAccessor
(b, dest),
kernels.begin());
}
}
}
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
inline void
hessianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons
t & source,
pair<DestIterator, DestAccessor> const & dest,
double sigma )
{
hessianOfGaussianMultiArray( source.first, source.second, source.third,
dest.first, dest.second, sigma );
}
namespace detail {
template<int N, class VectorType>
struct StructurTensorFunctor
{
typedef VectorType result_type;
typedef typename VectorType::value_type ValueType;
template <class T>
VectorType operator()(T const & in) const
{
VectorType res;
for(int b=0, i=0; i<N; ++i)
{
for(int j=i; j<N; ++j, ++b)
{
res[b] = detail::RequiresExplicitCast<ValueType>::cast(in[i
]*in[j]);
}
}
return res;
}
};
} // namespace detail
/********************************************************/
/* */
/* structureTensorMultiArray */
/* */
/********************************************************/
/** \brief Calculate th structure tensor of a multi-dimensional arrays.
This function computes the gradient (outer product) tensor for each ele
ment
of the given N-dimensional array with first-derivative-of-Gaussian filt
ers at
the given <tt>innerScale</tt>, followed by Gaussian smoothing at <tt>ou
terScale</tt>.
Both source and destination arrays are represented by iterators, shape
objects and
accessors. The destination array must have a vector valued pixel type w
ith
N*(N+1)/2 elements (it represents the upper triangular part of the symm
etric
structure tensor matrix). If the source array is also vector valued, th
e
resulting structure tensor is the sum of the individual tensors for eac
h channel.
This function is implemented by calls to
\ref separableConvolveMultiArray() with the appropriate kernels.
<b> Declarations:</b>
pass arguments explicitly:
\code
namespace vigra {
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
void
structureTensorMultiArray(SrcIterator siter, SrcShape const & shape
, SrcAccessor src,
DestIterator diter, DestAccessor dest,
double innerScale, double outerScale);
}
\endcode
use argument objects in conjunction with \ref ArgumentObjectFactories :
\code
namespace vigra {
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
void
structureTensorMultiArray(triple<SrcIterator, SrcShape, SrcAccessor
> const & source,
pair<DestIterator, DestAccessor> const &
dest,
double innerScale, double outerScale);
}
\endcode
<b> Usage:</b>
<b>\#include</b> \<<a href="multi__convolution_8hxx-source.html">vigra/
multi_convolution.hxx</a>\>
\code
MultiArray<3, RGBValue<float> > source(shape);
MultiArray<3, TinyVector<float, 6> > dest(shape);
...
// compute structure tensor at scales innerScale and outerScale
structureTensorMultiArray(srcMultiArrayRange(source), destMultiArray(de
st), innerScale, outerScale);
\endcode
<b> Required Interface:</b>
see \ref separableConvolveMultiArray(), in addition:
\code
int dimension = 0;
VectorElementAccessor<DestAccessor> elementAccessor(0, dest);
\endcode
\see separableConvolveMultiArray(), vectorToTensorMultiArray()
*/
doxygen_overloaded_function(template <...> void structureTensorMultiArray)
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
void
structureTensorMultiArray(SrcIterator si, SrcShape const & shape, SrcAccess
or src,
DestIterator di, DestAccessor dest,
double innerScale, double outerScale)
{
static const int N = SrcShape::static_size;
static const int M = N*(N+1)/2;
typedef typename DestAccessor::value_type DestType;
typedef typename DestType::value_type DestValueType;
typedef typename NumericTraits<DestValueType>::RealPromote KernelType;
typedef TinyVector<KernelType, N> GradientVector;
typedef typename AccessorTraits<GradientVector>::default_accessor Gradi
entAccessor;
for(int k=0; k<N; ++k)
if(shape[k] <=0)
return;
vigra_precondition(M == dest.size(di),
"structureTensorMultiArray(): Wrong number of channels in output ar
ray.");
vigra_precondition(innerScale > 0.0 && outerScale >= 0.0,
"structureTensorMultiArray(): Scale must be positive.");
MultiArray<N, GradientVector> gradient(shape);
gaussianGradientMultiArray(si, shape, src,
gradient.traverser_begin(), GradientAccessor
(),
innerScale);
transformMultiArray(gradient.traverser_begin(), shape, GradientAccessor
(),
di, dest,
detail::StructurTensorFunctor<N, DestType>());
gaussianSmoothMultiArray(di, shape, dest, di, dest, outerScale);
}
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
inline void
structureTensorMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const
& source,
pair<DestIterator, DestAccessor> const & dest,
double innerScale, double outerScale)
{
structureTensorMultiArray( source.first, source.second, source.third,
dest.first, dest.second, innerScale, outerSc
ale );
}
//@} //@}
} //-- namespace vigra } //-- namespace vigra
#endif //-- VIGRA_MULTI_CONVOLUTION_H #endif //-- VIGRA_MULTI_CONVOLUTION_H
 End of changes. 25 change blocks. 
33 lines changed or deleted 499 lines changed or added


 multi_distance.hxx   multi_distance.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2003-2007 by Kasim Terzic, Christian-Dennis Rahn */ /* Copyright 2003-2007 by Kasim Terzic, Christian-Dennis Rahn */
/* and Ullrich Koethe */ /* and Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 59 skipping to change at line 57
#include "metaprogramming.hxx" #include "metaprogramming.hxx"
#include "multi_pointoperators.hxx" #include "multi_pointoperators.hxx"
#include "functorexpression.hxx" #include "functorexpression.hxx"
namespace vigra namespace vigra
{ {
namespace detail namespace detail
{ {
template <class Value>
struct DistParabolaStackEntry
{
double left, center, right;
Value prevVal;
DistParabolaStackEntry(Value const & p, double l, double c, double r)
: left(l), center(c), right(r), prevVal(p)
{}
};
/********************************************************/ /********************************************************/
/* */ /* */
/* distParabola */ /* distParabola */
/* */ /* */
/* Version with sigma (parabola spread) for morphology */ /* Version with sigma (parabola spread) for morphology */
/* */ /* */
/********************************************************/ /********************************************************/
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor > class DestIterator, class DestAccessor >
void distParabola(SrcIterator is, SrcIterator iend, SrcAccessor sa, void distParabola(SrcIterator is, SrcIterator iend, SrcAccessor sa,
DestIterator id, DestAccessor da, float sigma ) DestIterator id, DestAccessor da, double sigma )
{ {
// We assume that the data in the input is distance squared and treat i t as such // We assume that the data in the input is distance squared and treat i t as such
int w = iend - is; double w = iend - is;
double sigma2 = sigma * sigma;
typedef typename NumericTraits<typename DestAccessor::value_type>::Valu double sigma22 = 2.0 * sigma2;
eType ValueType;
typedef typename NumericTraits<typename DestAccessor::value_type>::Real
Promote SumType;
// Define the stack we use to determine the nearest background row
// (from previous dimension), the items on the stack will separate this
column into
// separate regions of influence. Each region of influence is closest t
o the same
// background row from the previous dimension.
typedef triple<int, ValueType, int> influence;
std::vector<influence> _stack;
SrcIterator ibegin = is; typedef typename SrcAccessor::value_type SrcType;
_stack.push_back(influence(0, sa(is), w)); typedef DistParabolaStackEntry<SrcType> Influence;
std::vector<Influence> _stack;
_stack.push_back(Influence(sa(is), 0.0, 0.0, w));
++is; ++is;
int current = 1; double current = 1.0;
while(current < w )
int y0, y1, y2, y_dash, delta_y;
sigma = sigma * sigma;
bool nosigma = closeAtTolerance( sigma, 1.0 );
y0 = 0; // The beginning of the influence of row y1
while( is != iend && current < w )
{ {
y1 = _stack.back().first; Influence & s = _stack.back();
y2 = current; double diff = current - s.center;
delta_y = y2 - y1; double intersection = current + (sa(is) - s.prevVal - sigma2*sq(dif
f)) / (sigma22 * diff);
// If sigma is 1 (common case) avoid float multiplication here.
if(nosigma)
y_dash = (int)(sa(is) - _stack.back().second) - delta_y*delta_y
;
else
y_dash = (int)(sigma * (sa(is) - _stack.back().second)) - delta
_y*delta_y;
y_dash = y_dash / (delta_y + delta_y);
y_dash += y2;
if( y_dash > y0) if( intersection < s.left) // previous point has no influence
{ {
if( y_dash <= w ) // CASE 2 -- A new region of influence _stack.pop_back();
if(_stack.empty())
{ {
y0 = y_dash; _stack.push_back(Influence(sa(is), 0.0, current, w));
_stack.back().third = y_dash;
_stack.push_back(influence(current, sa(is), w));
} }
// CASE 1 -- This parabola is never active
++is;
++current;
continue;
}
else // CASE 3 -- Parabola shadows the previous one completely
{
_stack.pop_back();
if(_stack.size() < 2)
y0=0;
else else
y0=_stack[_stack.size()-2].third;
if(_stack.empty()) // This row influences all previous rows.
{ {
_stack.push_back(influence(current, sa(is), w)); continue; // try new top of stack without advancing current
++is;
++current;
continue;
} }
} }
else if(intersection < s.right)
{
s.right = intersection;
_stack.push_back(Influence(sa(is), intersection, current, w));
}
++is;
++current;
} }
// Now we have the stack indicating which rows are influenced by (and t herefore // Now we have the stack indicating which rows are influenced by (and t herefore
// closest to) which row. We can go through the stack and calculate the // closest to) which row. We can go through the stack and calculate the
// distance squared for each element of the column. // distance squared for each element of the column.
typename std::vector<Influence>::iterator it = _stack.begin();
typename std::vector<influence>::iterator it = _stack.begin(); for(current = 0.0; current < w; ++current, ++id)
ValueType distance = 0; // The distance squared
current = 0;
delta_y = 0;
is = ibegin;
for(; is != iend; ++current, ++id, ++is)
{ {
// FIXME FIXME Bound checking incorrect here? vvv while( current >= it->right)
if( current >= (*it).third && it != _stack.end()) ++it; ++it;
da.set(sigma2 * sq(current - it->center) + it->prevVal, id);
// FIXME FIXME The following check speeds things up for distance, b
ut completely
// messes up the grayscale morphology. Use an extra flag???
/* if( *is == 0 ) // Skip background pixels
{
*id = 0;
continue;
}
*/
delta_y = current - (*it).first;
distance = delta_y * delta_y + (*it).second;
*id = distance;
} }
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline void distParabola(triple<SrcIterator, SrcIterator, SrcAccessor> src, inline void distParabola(triple<SrcIterator, SrcIterator, SrcAccessor> src,
pair<DestIterator, DestAccessor> dest, float sigma ) pair<DestIterator, DestAccessor> dest, double sigm a)
{ {
distParabola(src.first, src.second, src.third, distParabola(src.first, src.second, src.third,
dest.first, dest.second, sigma); dest.first, dest.second, sigma);
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* internalSeparableMultiArrayDistTmp */ /* internalSeparableMultiArrayDistTmp */
/* */ /* */
/********************************************************/ /********************************************************/
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor, class Array>
void internalSeparableMultiArrayDistTmp( void internalSeparableMultiArrayDistTmp(
SrcIterator si, SrcShape const & shape, SrcAccessor s rc, SrcIterator si, SrcShape const & shape, SrcAccessor s rc,
DestIterator di, DestAccessor dest, float sigma, bool invert) DestIterator di, DestAccessor dest, Array const & sig mas, bool invert)
{ {
// Sigma is the spread of the parabolas and is only used for ND morphol // Sigma is the spread of the parabolas. It determines the structuring
ogy. When element size
// calculating the distance transform, it is set to 1 // for ND morphology. When calculating the distance transforms, sigma i
enum { N = 1 + SrcIterator::level }; s usually set to 1,
// unless one wants to account for anisotropic pixel pitch
enum { N = SrcShape::static_size};
// we need the Promote type here if we want to invert the image (dilati on) // we need the Promote type here if we want to invert the image (dilati on)
typedef typename NumericTraits<typename DestAccessor::value_type>::Prom ote TmpType; typedef typename NumericTraits<typename DestAccessor::value_type>::Real Promote TmpType;
// temporary array to hold the current line to enable in-place operatio n // temporary array to hold the current line to enable in-place operatio n
ArrayVector<TmpType> tmp( shape[0] ); ArrayVector<TmpType> tmp( shape[0] );
typedef MultiArrayNavigator<SrcIterator, N> SNavigator; typedef MultiArrayNavigator<SrcIterator, N> SNavigator;
typedef MultiArrayNavigator<DestIterator, N> DNavigator; typedef MultiArrayNavigator<DestIterator, N> DNavigator;
// only operate on first dimension here // only operate on first dimension here
SNavigator snav( si, shape, 0 ); SNavigator snav( si, shape, 0 );
DNavigator dnav( di, shape, 0 ); DNavigator dnav( di, shape, 0 );
skipping to change at line 232 skipping to change at line 187
if(invert) if(invert)
transformLine( snav.begin(), snav.end(), src, tmp.begin(), transformLine( snav.begin(), snav.end(), src, tmp.begin(),
typename AccessorTraits<TmpType>::default_ac cessor(), typename AccessorTraits<TmpType>::default_ac cessor(),
Param(NumericTraits<TmpType>::zero())-Arg1() ); Param(NumericTraits<TmpType>::zero())-Arg1() );
else else
copyLine( snav.begin(), snav.end(), src, tmp.begin(), copyLine( snav.begin(), snav.end(), src, tmp.begin(),
typename AccessorTraits<TmpType>::default_accesso r() ); typename AccessorTraits<TmpType>::default_accesso r() );
detail::distParabola( srcIterRange(tmp.begin(), tmp.end(), detail::distParabola( srcIterRange(tmp.begin(), tmp.end(),
typename AccessorTraits<TmpType>::default_const_a ccessor()), typename AccessorTraits<TmpType>::default_const_a ccessor()),
destIter( dnav.begin(), dest ), sigma ); destIter( dnav.begin(), dest ), sigmas[0] );
} }
// operate on further dimensions // operate on further dimensions
for( int d = 1; d < N; ++d ) for( int d = 1; d < N; ++d )
{ {
DNavigator dnav( di, shape, d ); DNavigator dnav( di, shape, d );
tmp.resize( shape[d] ); tmp.resize( shape[d] );
for( ; dnav.hasMore(); dnav++ ) for( ; dnav.hasMore(); dnav++ )
{ {
// first copy source to temp for maximum cache efficiency // first copy source to temp for maximum cache efficiency
copyLine( dnav.begin(), dnav.end(), dest, copyLine( dnav.begin(), dnav.end(), dest,
tmp.begin(), typename AccessorTraits<TmpType>::defau lt_accessor() ); tmp.begin(), typename AccessorTraits<TmpType>::defau lt_accessor() );
detail::distParabola( srcIterRange(tmp.begin(), tmp.end(), detail::distParabola( srcIterRange(tmp.begin(), tmp.end(),
typename AccessorTraits<TmpType>::default_const_ accessor()), typename AccessorTraits<TmpType>::default_const_ accessor()),
destIter( dnav.begin(), dest ), sigma ); destIter( dnav.begin(), dest ), sigmas[d] );
} }
} }
if(invert) transformMultiArray( di, shape, dest, di, dest, -Arg1()); if(invert) transformMultiArray( di, shape, dest, di, dest, -Arg1());
} }
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor, class Array>
inline void internalSeparableMultiArrayDistTmp( SrcIterator si, SrcShape co nst & shape, SrcAccessor src, inline void internalSeparableMultiArrayDistTmp( SrcIterator si, SrcShape co nst & shape, SrcAccessor src,
DestIterator di, DestAccess or dest, float sigma) DestIterator di, DestAccess or dest, Array const & sigmas)
{ {
internalSeparableMultiArrayDistTmp( si, shape, src, di, dest, sigma, fa lse ); internalSeparableMultiArrayDistTmp( si, shape, src, di, dest, sigmas, f alse );
} }
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline void internalSeparableMultiArrayDistTmp( SrcIterator si, SrcShape co nst & shape, SrcAccessor src, inline void internalSeparableMultiArrayDistTmp( SrcIterator si, SrcShape co nst & shape, SrcAccessor src,
DestIterator di, DestAccess or dest) DestIterator di, DestAccess or dest)
{ {
internalSeparableMultiArrayDistTmp( si, shape, src, di, dest, 1, false ArrayVector<double> sigmas(shape.size(), 1.0);
); internalSeparableMultiArrayDistTmp( si, shape, src, di, dest, sigmas, f
alse );
} }
} // namespace detail } // namespace detail
/** \addtogroup MultiArrayDistanceTransform Euclidean distance transform fo r multi-dimensional arrays. /** \addtogroup MultiArrayDistanceTransform Euclidean distance transform fo r multi-dimensional arrays.
These functions perform the Euclidean distance transform an arbitrary d imensional These functions perform the Euclidean distance transform an arbitrary d imensional
array that is specified by iterators (compatible to \ref MultiIteratorP age) array that is specified by iterators (compatible to \ref MultiIteratorP age)
and shape objects. It can therefore be applied to a wide range of data structures and shape objects. It can therefore be applied to a wide range of data structures
(\ref vigra::MultiArrayView, \ref vigra::MultiArray etc.). (\ref vigra::MultiArrayView, \ref vigra::MultiArray etc.).
skipping to change at line 291 skipping to change at line 247
//@{ //@{
/********************************************************/ /********************************************************/
/* */ /* */
/* separableMultiDistSquared */ /* separableMultiDistSquared */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Euclidean distance squared on multi-dimensional arrays. /** \brief Euclidean distance squared on multi-dimensional arrays.
The algorithm is taken from Donald Bailey: "An Efficient Euclidean Dist
ance Transform",
Proc. IWCIA'04, Springer LNCS 3322, 2004.
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
// apply the same kernel to all dimensions // explicitly specify pixel pitch for each coordinate
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor, class Array>
void
separableMultiDistSquared( SrcIterator s, SrcShape const & shape, S
rcAccessor src,
DestIterator d, DestAccessor dest,
bool background,
Array const & pixelPitch);
// use default pixel pitch = 1.0 for each coordinate
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
separableMultiDistSquared(SrcIterator siter, SrcShape const & shape , SrcAccessor src, separableMultiDistSquared(SrcIterator siter, SrcShape const & shape , SrcAccessor src,
DestIterator diter, DestAccessor dest, DestIterator diter, DestAccessor dest,
bool background); bool background);
} }
\endcode \endcode
use argument objects in conjunction with \ref ArgumentObjectFactories : use argument objects in conjunction with \ref ArgumentObjectFactories :
\code \code
namespace vigra { namespace vigra {
// explicitly specify pixel pitch for each coordinate
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor, class Array>
void
separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAccesso
r> const & source,
pair<DestIterator, DestAccessor> const &
dest,
bool background,
Array const & pixelPitch);
// use default pixel pitch = 1.0 for each coordinate
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
separableMultiDistance(triple<SrcIterator, SrcShape, SrcAccessor> c separableMultiDistSquared(triple<SrcIterator, SrcShape, SrcAccessor
onst & source, > const & source,
pair<DestIterator, DestAccessor> const pair<DestIterator, DestAccessor> const &
& dest, dest,
bool background); bool background);
} }
\endcode \endcode
This function performs a Euclidean distance squared transform on the gi ven This function performs a squared Euclidean squared distance transform o n the given
multi-dimensional array. Both source and destination multi-dimensional array. Both source and destination
arrays are represented by iterators, shape objects and accessors. arrays are represented by iterators, shape objects and accessors.
The destination array is required to already have the correct size. The destination array is required to already have the correct size.
This function expects a mask as its source, where background pixels are This function expects a mask as its source, where background pixels are
marked as zero, and non-background pixels as non-zero. If the parameter marked as zero, and non-background pixels as non-zero. If the parameter
<i>background</i> is true, then the squared distance of all background <i>background</i> is true, then the squared distance of all background
pixels to the nearest object is calculated. Otherwise, the distance of all pixels to the nearest object is calculated. Otherwise, the distance of all
object pixels to the nearest background pixel is calculated. object pixels to the nearest background pixel is calculated.
Optionally, one can pass an array that specifies the pixel pitch in eac
h direction.
This is necessary when the data have non-uniform resolution (as is comm
on in confocal
microscopy, for example).
This function may work in-place, which means that <tt>siter == diter</t t> is allowed. This function may work in-place, which means that <tt>siter == diter</t t> is allowed.
A full-sized internal array is only allocated if working on the destina tion A full-sized internal array is only allocated if working on the destina tion
array directly would cause overflow errors (i.e. if array directly would cause overflow errors (i.e. if
<tt> typeid(typename DestAccessor::value_type) < N * M*M</tt>, where M is the <tt> NumericTraits<typename DestAccessor::value_type>::max() < N * M*M< /tt>, where M is the
size of the largest dimension of the array. size of the largest dimension of the array.
<b> Usage:</b> <b> Usage:</b>
<b>\#include</b> \<<a href="multi__distance_8hxx-source.html">vigra/mul ti_distance.hxx</a>\> <b>\#include</b> \<<a href="multi__distance_8hxx-source.html">vigra/mul ti_distance.hxx</a>\>
\code \code
MultiArray<3, unsigned char>::size_type shape(width, height, depth); MultiArray<3, unsigned char>::size_type shape(width, height, depth);
MultiArray<3, unsigned char> source(shape); MultiArray<3, unsigned char> source(shape);
MultiArray<3, unsigned int> dest(shape); MultiArray<3, unsigned int> dest(shape);
... ...
// Calculate Euclidean distance squared for all background pixels // Calculate Euclidean distance squared for all background pixels
separableMultiDistSquared(srcMultiArrayRange(source), destMultiArray(de st), true); separableMultiDistSquared(srcMultiArrayRange(source), destMultiArray(de st), true);
\endcode \endcode
\see vigra::distanceTransform() \see vigra::distanceTransform(), vigra::separableMultiDistance()
*/ */
doxygen_overloaded_function(template <...> void separableMultiDistSquared) doxygen_overloaded_function(template <...> void separableMultiDistSquared)
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor, class Array>
void separableMultiDistSquared( SrcIterator s, SrcShape const & shape, SrcA ccessor src, void separableMultiDistSquared( SrcIterator s, SrcShape const & shape, SrcA ccessor src,
DestIterator d, DestAccessor dest, bool bac DestIterator d, DestAccessor dest, bool bac
kground) kground,
Array const & pixelPitch)
{ {
typedef typename NumericTraits<typename DestAccessor::value_type>::Valu int N = shape.size();
eType DestType;
typedef typename NumericTraits<typename DestAccessor::value_type>::Prom
ote TmpType;
DestType MaxValue = NumericTraits<DestType>::max();
enum { N = 1 + SrcIterator::level };
int MaxDim = 0; typedef typename SrcAccessor::value_type SrcType;
for( int i=0; i<N; i++) typedef typename DestAccessor::value_type DestType;
if(MaxDim < shape[i]) MaxDim = shape[i]; typedef typename NumericTraits<DestType>::RealPromote Real;
int MaxDist = MaxDim*MaxDim;
SrcType zero = NumericTraits<SrcType>::zero();
double dmax = 0.0;
bool pixelPitchIsReal = false;
for( int k=0; k<N; ++k)
{
if(int(pixelPitch[k]) != pixelPitch[k])
pixelPitchIsReal = true;
dmax += sq(pixelPitch[k]*shape[k]);
}
using namespace vigra::functor; using namespace vigra::functor;
if(N*MaxDim*MaxDim > MaxValue) // need a temporary array to avoid overf if(dmax > NumericTraits<DestType>::toRealPromote(NumericTraits<DestType
lows >::max())
|| pixelPitchIsReal) // need a temporary array to avoid overflows
{ {
// Threshold the values so all objects have infinity value in the b eginning // Threshold the values so all objects have infinity value in the b eginning
MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); Real maxDist = (Real)dmax, rzero = (Real)0.0;
MultiArray<SrcShape::static_size, Real> tmpArray(shape);
if(background == true) if(background == true)
transformMultiArray( s, shape, src, tmpArray.traverser_begin(), transformMultiArray( s, shape, src,
typename AccessorTraits<TmpType>::default_ tmpArray.traverser_begin(), typename Acces
accessor(), sorTraits<Real>::default_accessor(),
ifThenElse( Arg1() == Param(0), Param(MaxD ifThenElse( Arg1() == Param(zero), Param(m
ist), Param(0) )); axDist), Param(rzero) ));
else else
transformMultiArray( s, shape, src, tmpArray.traverser_begin(), transformMultiArray( s, shape, src,
typename AccessorTraits<TmpType>::default_ tmpArray.traverser_begin(), typename Acces
accessor(), sorTraits<Real>::default_accessor(),
ifThenElse( Arg1() != Param(0), Param(MaxD ifThenElse( Arg1() != Param(zero), Param(m
ist), Param(0) )); axDist), Param(rzero) ));
detail::internalSeparableMultiArrayDistTmp( tmpArray.traverser_begi n(), detail::internalSeparableMultiArrayDistTmp( tmpArray.traverser_begi n(),
shape, typename AccessorTraits<TmpType>::default_accessor() , shape, typename AccessorTraits<Real>::default_accessor(),
tmpArray.traverser_begin(), tmpArray.traverser_begin(),
typename AccessorTraits<TmpType>::default_accessor()); typename AccessorTraits<Real>::default_accessor(), pixelPit
ch);
//copyMultiArray(srcMultiArrayRange(tmpArray), destIter(d, dest));
transformMultiArray( tmpArray.traverser_begin(), shape,
typename AccessorTraits<TmpType>::default_acce
ssor(), d, dest,
ifThenElse( Arg1() > Param(MaxValue), Param(Ma
xValue), Arg1() ) );
copyMultiArray(srcMultiArrayRange(tmpArray), destIter(d, dest));
} }
else // work directly on the destination array else // work directly on the destination array
{ {
// Threshold the values so all objects have infinity value in the b eginning // Threshold the values so all objects have infinity value in the b eginning
DestType maxDist = DestType(std::ceil(dmax)), rzero = (DestType)0;
if(background == true) if(background == true)
transformMultiArray( s, shape, src, d, dest, transformMultiArray( s, shape, src, d, dest,
ifThenElse( Arg1() == Param(0), Param(MaxD ist), Param(0) )); ifThenElse( Arg1() == Param(zero), Param(m axDist), Param(rzero) ));
else else
transformMultiArray( s, shape, src, d, dest, transformMultiArray( s, shape, src, d, dest,
ifThenElse( Arg1() != Param(0), Param(MaxD ist), Param(0) )); ifThenElse( Arg1() != Param(zero), Param(m axDist), Param(rzero) ));
detail::internalSeparableMultiArrayDistTmp( d, shape, dest, d, dest ); detail::internalSeparableMultiArrayDistTmp( d, shape, dest, d, dest , pixelPitch);
} }
} }
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor, class Array>
inline void separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAcc
essor> const & source,
pair<DestIterator, DestAccessor> con
st & dest, bool background,
Array const & pixelPitch)
{
separableMultiDistSquared( source.first, source.second, source.third,
dest.first, dest.second, background, pixelPi
tch );
}
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
inline
void separableMultiDistSquared( SrcIterator s, SrcShape const & shape, SrcA
ccessor src,
DestIterator d, DestAccessor dest, bool bac
kground)
{
ArrayVector<double> pixelPitch(shape.size(), 1.0);
separableMultiDistSquared( s, shape, src, d, dest, background, pixelPit
ch );
}
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline void separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAcc essor> const & source, inline void separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAcc essor> const & source,
pair<DestIterator, DestAccessor> con st & dest, bool background) pair<DestIterator, DestAccessor> con st & dest, bool background)
{ {
separableMultiDistSquared( source.first, source.second, source.third, separableMultiDistSquared( source.first, source.second, source.third,
dest.first, dest.second, background ); dest.first, dest.second, background );
} }
/********************************************************/ /********************************************************/
/* */ /* */
skipping to change at line 431 skipping to change at line 441
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Euclidean distance on multi-dimensional arrays. /** \brief Euclidean distance on multi-dimensional arrays.
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
// apply the same kernel to all dimensions // explicitly specify pixel pitch for each coordinate
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor, class Array>
void
separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcA
ccessor src,
DestIterator d, DestAccessor dest,
bool background,
Array const & pixelPitch);
// use default pixel pitch = 1.0 for each coordinate
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
separableMultiDistance(SrcIterator siter, SrcShape const & shape, S rcAccessor src, separableMultiDistance(SrcIterator siter, SrcShape const & shape, S rcAccessor src,
DestIterator diter, DestAccessor dest, DestIterator diter, DestAccessor dest,
bool background); bool background);
} }
\endcode \endcode
use argument objects in conjunction with \ref ArgumentObjectFactories : use argument objects in conjunction with \ref ArgumentObjectFactories :
\code \code
namespace vigra { namespace vigra {
// explicitly specify pixel pitch for each coordinate
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor, class Array>
void
separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccessor>
const & source,
pair<DestIterator, DestAccessor> const & de
st,
bool background,
Array const & pixelPitch);
// use default pixel pitch = 1.0 for each coordinate
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
separableMultiDistance(triple<SrcIterator, SrcShape, SrcAccessor> c onst & source, separableMultiDistance(triple<SrcIterator, SrcShape, SrcAccessor> c onst & source,
pair<DestIterator, DestAccessor> const pair<DestIterator, DestAccessor> const & des
& dest, t,
bool background); bool background);
} }
\endcode \endcode
This function performs a Euclidean distance transform on the given This function performs a Euclidean distance transform on the given
multi-dimensional array. Both source and destination multi-dimensional array. It simply calls \ref separableMultiDistSquared
arrays are represented by iterators, shape objects and accessors. ()
The destination array is required to already have the correct size. and takes the pixel-wise square root of the result. See \ref separableM
ultiDistSquared()
This function expects a mask as its source, where background pixels are for more documentation.
marked as zero, and non-background pixels as non-zero. If the parameter
<i>background</i> is true, then the squared distance of all background
pixels to the nearest object is calculated. Otherwise, the distance of
all
object pixels to the nearest background pixel is calculated.
This function may work in-place, which means that <tt>siter == diter</t
t> is allowed.
A full-sized internal array is only allocated if working on the destina
tion
array directly would cause overflow errors (i.e. if
<tt> typeid(typename DestAccessor::value_type) < N * M*M</tt>, where M
is the
size of the largest dimension of the array.
<b> Usage:</b> <b> Usage:</b>
<b>\#include</b> \<<a href="multi__distance_8hxx-source.html">vigra/mul ti_distance.hxx</a>\> <b>\#include</b> \<<a href="multi__distance_8hxx-source.html">vigra/mul ti_distance.hxx</a>\>
\code \code
MultiArray<3, unsigned char>::size_type shape(width, height, depth); MultiArray<3, unsigned char>::size_type shape(width, height, depth);
MultiArray<3, unsigned char> source(shape); MultiArray<3, unsigned char> source(shape);
MultiArray<3, unsigned float> dest(shape); MultiArray<3, float> dest(shape);
... ...
// Calculate Euclidean distance squared for all background pixels // Calculate Euclidean distance squared for all background pixels
separableMultiDistance(srcMultiArrayRange(source), destMultiArray(dest) , true); separableMultiDistance(srcMultiArrayRange(source), destMultiArray(dest) , true);
\endcode \endcode
\see vigra::distanceTransform() \see vigra::distanceTransform(), vigra::separableMultiDistSquared()
*/ */
doxygen_overloaded_function(template <...> void separableMultiDistance) doxygen_overloaded_function(template <...> void separableMultiDistance)
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor, class Array>
void separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcAcce
ssor src,
DestIterator d, DestAccessor dest, bool backgr
ound,
Array const & pixelPitch)
{
separableMultiDistSquared( s, shape, src, d, dest, background, pixelPit
ch);
// Finally, calculate the square root of the distances
using namespace vigra::functor;
transformMultiArray( d, shape, dest, d, dest, sqrt(Arg1()) );
}
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcAcce ssor src, void separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcAcce ssor src,
DestIterator d, DestAccessor dest, bool backgr ound) DestIterator d, DestAccessor dest, bool backgr ound)
{ {
separableMultiDistSquared( s, shape, src, d, dest, background); separableMultiDistSquared( s, shape, src, d, dest, background);
// Finally, calculate the square root of the distances // Finally, calculate the square root of the distances
transformMultiArray( d, shape, dest, d, dest, (double(*)(double))&std:: using namespace vigra::functor;
sqrt );
transformMultiArray( d, shape, dest, d, dest, sqrt(Arg1()) );
}
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor, class Array>
inline void separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccess
or> const & source,
pair<DestIterator, DestAccessor> const
& dest, bool background,
Array const & pixelPitch)
{
separableMultiDistance( source.first, source.second, source.third,
dest.first, dest.second, background, pixelPitch
);
} }
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline void separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccess or> const & source, inline void separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccess or> const & source,
pair<DestIterator, DestAccessor> const & dest, bool background) pair<DestIterator, DestAccessor> const & dest, bool background)
{ {
separableMultiDistance( source.first, source.second, source.third, separableMultiDistance( source.first, source.second, source.third,
dest.first, dest.second, background ); dest.first, dest.second, background );
} }
 End of changes. 64 change blocks. 
188 lines changed or deleted 240 lines changed or added


 multi_impex.hxx   multi_impex.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2003 by Gunnar Kedenburg */ /* Copyright 2003 by Gunnar Kedenburg */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 62 skipping to change at line 60
#include "multi_pointoperators.hxx" #include "multi_pointoperators.hxx"
#ifdef _MSC_VER #ifdef _MSC_VER
# include <direct.h> # include <direct.h>
#else #else
# include <unistd.h> # include <unistd.h>
#endif #endif
namespace vigra { namespace vigra {
/** \addtogroup VolumeImpex Import/export of volume data.
*/
//@{
/** \brief Argument object for the function importVolume().
See \ref importVolume() for usage example. This object can be used
to define the properties of a volume data set to be read from disk.
Sorry, no \ref detailedDocumentation() available yet.
<b>\#include</b> \<<a href="imageinfo_8hxx-source.html">vigra/multi_imp
ex.hxx</a>\><br>
Namespace: vigra
**/
class VolumeImportInfo class VolumeImportInfo
{ {
public: public:
typedef ImageImportInfo::PixelType PixelType; typedef ImageImportInfo::PixelType PixelType;
/// type of volume size returned by shape() /// type of volume size returned by shape()
typedef MultiArrayShape<3>::type ShapeType; typedef MultiArrayShape<3>::type ShapeType;
/// provided for backwards-compatibility (deprecated) /// provided for backwards-compatibility (deprecated)
typedef ShapeType size_type; typedef ShapeType size_type;
/// 3D resolution type returned by resolution() /// 3D resolution type returned by resolution()
typedef TinyVector<float, 3> Resolution; typedef TinyVector<float, 3> Resolution;
VIGRA_EXPORT VolumeImportInfo(const std::string &filename); VIGRA_EXPORT VolumeImportInfo(const std::string &filename);
VIGRA_EXPORT VolumeImportInfo(const std::string &baseName, const std::s tring &extension); VIGRA_EXPORT VolumeImportInfo(const std::string &baseName, const std::s tring &extension);
VIGRA_EXPORT ShapeType shape() const { return shape_; } VIGRA_EXPORT ShapeType shape() const;
/** Get width of the volume.
**/
VIGRA_EXPORT MultiArrayIndex width() const;
/** Get height of the volume.
**/
VIGRA_EXPORT MultiArrayIndex height() const;
/** Get depth of the volume.
**/
VIGRA_EXPORT MultiArrayIndex depth() const;
/** /**
* resolution() contains the alignment and resolution of the * resolution() contains the alignment and resolution of the
* volume. resolution()[0] is the x increment in a left-handed * volume. resolution()[0] is the x increment in a left-handed
* world coordinate system of one unstrided step in the volume * world coordinate system of one unstrided step in the volume
* memory. The [1] and [2] elements contain the y resp. z * memory. The [1] and [2] elements contain the y resp. z
* increments of the strided row resp. slice steps in the * increments of the strided row resp. slice steps in the
* volume. * volume.
* *
* EXAMPLES: (1.f, 1.f, 4.f) means that the slices are four * EXAMPLES: (1.f, 1.f, 4.f) means that the slices are four
* times thicker than the x/y resolution. * times thicker than the x/y resolution.
* (1.f, -1.f, 1.f) means that the volume coordinate system is * (1.f, -1.f, 1.f) means that the volume coordinate system is
* right-handed. * right-handed.
*/ */
VIGRA_EXPORT Resolution resolution() const { return resolution_; } VIGRA_EXPORT Resolution resolution() const;
VIGRA_EXPORT PixelType pixelType() const { return pixelType_; } /** Query the pixel type of the image.
VIGRA_EXPORT int numBands() const { return numBands_; } Possible values are:
VIGRA_EXPORT bool isGrayscale() const { return numBands_ == 1; } <DL>
VIGRA_EXPORT bool isColor() const { return numBands_ > 1; } <DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char)
<DT>"INT16"<DD> 16-bit signed integer (short)
<DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short)
<DT>"INT32"<DD> 32-bit signed integer (long)
<DT>"UINT32"<DD> 32-bit unsigned integer (unsigned long)
<DT>"FLOAT"<DD> 32-bit floating point (float)
<DT>"DOUBLE"<DD> 64-bit floating point (double)
</DL>
**/
VIGRA_EXPORT const char * getPixelType() const;
/** Query the pixel type of the image.
Same as getPixelType(), but the result is returned as a
ImageImportInfo::PixelType enum. This is useful to implement
a switch() on the pixel type.
Possible values are:
<DL>
<DT>UINT8<DD> 8-bit unsigned integer (unsigned char)
<DT>INT16<DD> 16-bit signed integer (short)
<DT>UINT16<DD> 16-bit unsigned integer (unsigned short)
<DT>INT32<DD> 32-bit signed integer (long)
<DT>UINT32<DD> 32-bit unsigned integer (unsigned long)
<DT>FLOAT<DD> 32-bit floating point (float)
<DT>DOUBLE<DD> 64-bit floating point (double)
</DL>
**/
VIGRA_EXPORT PixelType pixelType() const;
VIGRA_EXPORT MultiArrayIndex numBands() const;
VIGRA_EXPORT bool isGrayscale() const;
VIGRA_EXPORT bool isColor() const;
// get base file name without path, image index, and extension // get base file name without path, image index, and extension
VIGRA_EXPORT const std::string &name() const { return name_; } VIGRA_EXPORT const std::string &name() const;
VIGRA_EXPORT const std::string &description() const { return descriptio n_; } VIGRA_EXPORT const std::string &description() const;
template <class T, class Allocator> template <class T, class Stride>
void importImpl(MultiArray <3, T, Allocator> &volume) const; void importImpl(MultiArrayView <3, T, Stride> &volume) const;
protected: protected:
void getVolumeInfoFromFirstSlice(const std::string &filename); void getVolumeInfoFromFirstSlice(const std::string &filename);
size_type shape_; size_type shape_;
Resolution resolution_; Resolution resolution_;
PixelType pixelType_; //PixelType pixelType_;
int numBands_; int numBands_;
std::string path_, name_, description_; std::string path_, name_, description_, pixelType_;
std::string rawFilename_; std::string rawFilename_;
std::string baseName_, extension_; std::string baseName_, extension_;
std::vector<std::string> numbers_; std::vector<std::string> numbers_;
}; };
template <class T, class Allocator> /********************************************************/
void VolumeImportInfo::importImpl(MultiArray <3, T, Allocator> &volume) con /* */
st /* VolumeExportInfo */
/* */
/********************************************************/
/** \brief Argument object for the function exportVolume().
See \ref exportVolume() for usage example. This object must be used
to define the properties of a volume to be written to disk.
<b>\#include</b> \<<a href="imageinfo_8hxx-source.html">vigra/imageinfo
.hxx</a>\><br>
Namespace: vigra
**/
class VolumeExportInfo
{ {
volume.reshape(this->shape()); public:
/** Construct VolumeExportInfo object.
The volume will be stored in a by-slice manner, where the numbe
r of slices
equals the depth of the volume. The file names will be enumerat
ed like
<tt>name_base+"000"+name_ext</tt>, <tt>name_base+"001"+name_ext
</tt> etc.
(the actual number of zeros depends on the depth). If the targe
t image type
does not support the source voxel type, all slices will be mapp
ed
simultaneously to the appropriate target range.
The file type will be guessed from the extension unless overrid
den
by \ref setFileType(). Recognized extensions: '.bmp', '.gif',
'.jpeg', '.jpg', '.p7', '.png', '.pbm', '.pgm', '.pnm', '.ppm',
'.ras',
'.tif', '.tiff', '.xv', '.hdr'.
JPEG support requires libjpeg, PNG support requires libpng, and
TIFF support requires libtiff.
**/
VIGRA_EXPORT VolumeExportInfo( const char * name_base, const char * nam
e_ext );
VIGRA_EXPORT ~VolumeExportInfo();
/** Set volume file name base.
**/
VIGRA_EXPORT VolumeExportInfo & setFileNameBase(const char * name_base)
;
/** Set volume file name extension.
The file type will be guessed from the extension unless overrid
den
by \ref setFileType(). Recognized extensions: '.bmp', '.gif',
'.jpeg', '.jpg', '.p7', '.png', '.pbm', '.pgm', '.pnm', '.ppm',
'.ras',
'.tif', '.tiff', '.xv', '.hdr'.
JPEG support requires libjpeg, PNG support requires libpng, and
TIFF support requires libtiff.
**/
VIGRA_EXPORT VolumeExportInfo & setFileNameExt(const char * name_ext);
VIGRA_EXPORT const char * getFileNameBase() const;
VIGRA_EXPORT const char * getFileNameExt() const;
/** Store volume as given file type.
This will override any type guessed
from the file name's extension. Recognized file types:
<DL>
<DT>"BMP"<DD> Microsoft Windows bitmap image file.
<DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit col
or.
<DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format;
compressed 24-bit color (only available if libjpeg is installed
).
<DT>"PNG"<DD> Portable Network Graphic
(only available if libpng is installed).
<DT>"PBM"<DD> Portable bitmap format (black and white).
<DT>"PGM"<DD> Portable graymap format (gray scale).
<DT>"PNM"<DD> Portable anymap.
<DT>"PPM"<DD> Portable pixmap format (color).
<DT>"SUN"<DD> SUN Rasterfile.
<DT>"TIFF"<DD> Tagged Image File Format.
(only available if libtiff is installed.)
<DT>"VIFF"<DD> Khoros Visualization image file.
</DL>
With the exception of TIFF, VIFF, PNG, and PNM all file types s
tore
1 byte (gray scale and mapped RGB) or 3 bytes (RGB) per
pixel.
PNG can store UInt8 and UInt16 values, and supports 1 and 3 cha
nnel
images. One additional alpha channel is also supported.
PNM can store 1 and 3 channel images with UInt8, UInt16 and UIn
t32
values in each channel.
TIFF and VIFF are aditionally able to store short and long
integers (2 or 4 bytes) and real values (32 bit float and
64 bit double) without conversion. So you will need to use
TIFF or VIFF if you need to store images with high
accuracy (the appropriate type to write is automatically
derived from the image type to be exported). However, many
other programs using TIFF (e.g. ImageMagick) have not
implemented support for those pixel types. So don't be
surprised if the generated TIFF is not readable in some
cases. If this happens, export the image as 'unsigned
char' or 'RGBValue\<unsigned char\>' by calling
\ref ImageExportInfo::setPixelType().
Support to reading and writing ICC color profiles is
provided for TIFF, JPEG, and PNG images.
**/
VIGRA_EXPORT VolumeExportInfo & setFileType( const char * );
VIGRA_EXPORT const char * getFileType() const;
/** Set compression type.
Recognized strings: "" (no compression), "LZW",
"RunLength", "1" ... "100". A number is interpreted as the
compression quality for JPEG compression. JPEG compression is
supported by the JPEG and TIFF formats. "LZW" is only available
if libtiff was installed with LZW enabled. By default, libtiff
came
with LZW disabled due to Unisys patent enforcement. In this cas
e,
VIGRA stores the image uncompressed.
Valid Compression for TIFF files:
JPEG jpeg compression, call setQuality as well!
RLE runlength compression
LZW lzw compression
DEFLATE deflate compression
**/
VIGRA_EXPORT VolumeExportInfo & setCompression( const char * );
VIGRA_EXPORT const char * getCompression() const;
/** Set the pixel type of the volume file(s). Possible values are:
<DL>
<DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char)
<DT>"INT16"<DD> 16-bit signed integer (short)
<DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short)
<DT>"INT32"<DD> 32-bit signed integer (long)
<DT>"UINT32"<DD> 32-bit unsigned integer (unsigned long)
<DT>"FLOAT"<DD> 32-bit floating point (float)
<DT>"DOUBLE"<DD> 64-bit floating point (double)
</DL>
**/
VIGRA_EXPORT VolumeExportInfo & setPixelType( const char * );
/** Get the pixel type of the images in the volume. Possible values
are:
<DL>
<DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char)
<DT>"INT16"<DD> 16-bit signed integer (short)
<DT>"INT32"<DD> 32-bit signed integer (long)
<DT>"FLOAT"<DD> 32-bit floating point (float)
<DT>"DOUBLE"<DD> 64-bit floating point (double)
</DL>
**/
VIGRA_EXPORT const char * getPixelType() const;
VIGRA_EXPORT VolumeExportInfo & setForcedRangeMapping(double fromMin, d
ouble fromMax,
double toMin, double t
oMax);
VIGRA_EXPORT bool hasForcedRangeMapping() const;
VIGRA_EXPORT double getFromMin() const;
VIGRA_EXPORT double getFromMax() const;
VIGRA_EXPORT double getToMin() const;
VIGRA_EXPORT double getToMax() const;
/** Set the volume resolution in horizontal direction
**/
VIGRA_EXPORT VolumeExportInfo & setXResolution( float );
VIGRA_EXPORT float getXResolution() const;
/** Set the image resolution in vertical direction
**/
VIGRA_EXPORT VolumeExportInfo & setYResolution( float );
VIGRA_EXPORT float getYResolution() const;
/** Set the image resolution in depth direction
**/
VIGRA_EXPORT VolumeExportInfo & setZResolution( float );
VIGRA_EXPORT float getZResolution() const;
/** Set the position of the upper Left corner on a global
canvas.
Currently only supported by TIFF and PNG files.
The offset is encoded in the XPosition and YPosition TIFF tags.
@param pos position of the upper left corner in pixels
(must be >= 0)
**/
// FIXME: mhanselm: we might want to support 3D positions
VIGRA_EXPORT VolumeExportInfo & setPosition(const Diff2D & pos);
/** Get the position of the upper left corner on
a global canvas.
**/
// FIXME: mhanselm: we might want to support 3D positions
VIGRA_EXPORT Diff2D getPosition() const;
/**
ICC profiles (handled as raw data so far).
see getICCProfile()/setICCProfile()
**/
typedef ArrayVector<unsigned char> ICCProfile;
/** Returns a reference to the ICC profile.
*/
VIGRA_EXPORT const ICCProfile & getICCProfile() const;
/** Sets the ICC profile.
ICC profiles are currently supported by TIFF, PNG and JPEG imag
es.
(Otherwise, the profile data is silently ignored.)
**/
VIGRA_EXPORT VolumeExportInfo & setICCProfile(const ICCProfile & profil
e);
private:
float m_x_res, m_y_res, m_z_res;
std::string m_filetype, m_filename_base, m_filename_ext, m_pixeltype, m
_comp;
Diff2D m_pos;
ICCProfile m_icc_profile;
double fromMin_, fromMax_, toMin_, toMax_;
};
namespace detail {
template <class DestIterator, class Shape, class T>
inline void
readVolumeImpl(DestIterator d, Shape const & shape, std::ifstream & s, Arra
yVector<T> & buffer, MetaInt<0>)
{
s.read((char*)buffer.begin(), shape[0]*sizeof(T));
DestIterator dend = d + shape[0];
int k = 0;
for(; d < dend; ++d, k++)
{
*d = buffer[k];
}
}
template <class DestIterator, class Shape, class T, int N>
void
readVolumeImpl(DestIterator d, Shape const & shape, std::ifstream & s, Arra
yVector<T> & buffer, MetaInt<N>)
{
DestIterator dend = d + shape[N];
for(; d < dend; ++d)
{
readVolumeImpl(d.begin(), shape, s, buffer, MetaInt<N-1>());
}
}
} // namespace detail
template <class T, class Stride>
void VolumeImportInfo::importImpl(MultiArrayView <3, T, Stride> &volume) co
nst
{
vigra_precondition(this->shape() == volume.shape(), "importVolume(): Vo
lume must be shaped according to VolumeImportInfo.");
if(rawFilename_.size()) if(rawFilename_.size())
{ {
std::string dirName, baseName; std::string dirName, baseName;
char oldCWD[2048]; char oldCWD[2048];
#ifdef _MSC_VER #ifdef _MSC_VER
_getcwd(oldCWD, 2048); if(_getcwd(oldCWD, 2048) == 0)
{
perror("getcwd");
vigra_fail("VolumeImportInfo: Unable to query current directory
(getcwd).");
}
if(_chdir(path_.c_str())) if(_chdir(path_.c_str()))
{
perror("chdir"); perror("chdir");
vigra_fail("VolumeImportInfo: Unable to change to new directory
(chdir).");
}
#else #else
getcwd(oldCWD, 2048); if(getcwd(oldCWD, 2048) == 0)
{
perror("getcwd");
vigra_fail("VolumeImportInfo: Unable to query current directory
(getcwd).");
}
if(chdir(path_.c_str())) if(chdir(path_.c_str()))
{
perror("chdir"); perror("chdir");
vigra_fail("VolumeImportInfo: Unable to change to new directory
(chdir).");
}
#endif #endif
std::ifstream s(rawFilename_.c_str(), std::ios::binary); std::ifstream s(rawFilename_.c_str(), std::ios::binary);
vigra_precondition(s.good(), "RAW file could not be opened"); vigra_precondition(s.good(), "RAW file could not be opened");
s.read((char*)volume.begin(), shape_[0]*shape_[1]*shape_[2]*sizeof(
T)); ArrayVector<T> buffer(shape_[0]);
detail::readVolumeImpl(volume.traverser_begin(), shape_, s, buffer,
vigra::MetaInt<2>());
//vigra_precondition(s.good(), "RAW file could not be opened");
//s.read((char*)volume.data(), shape_[0]*shape_[1]*shape_[2]*sizeof
(T));
#ifdef _MSC_VER #ifdef _MSC_VER
_chdir(oldCWD); if(_chdir(oldCWD))
perror("chdir");
#else #else
chdir(oldCWD); if(chdir(oldCWD))
perror("chdir");
#endif #endif
vigra_postcondition( vigra_postcondition(
volume.shape() == shape(), "imported volume has wrong size"); volume.shape() == shape(), "imported volume has wrong size");
} }
else else
{ {
for (unsigned int i = 0; i < numbers_.size(); ++i) for (unsigned int i = 0; i < numbers_.size(); ++i)
{ {
// build the filename // build the filename
std::string name = baseName_ + numbers_[i] + extension_; std::string name = baseName_ + numbers_[i] + extension_;
// import the image // import the image
ImageImportInfo info (name.c_str ()); ImageImportInfo info (name.c_str ());
// generate a basic image view to the current layer // generate a basic image view to the current layer
MultiArrayView <2, T> array_view (volume.bindOuter (i)); MultiArrayView <2, T, Stride> view (volume.bindOuter (i));
BasicImageView <T> view = makeBasicImageView (array_view); vigra_precondition(view.shape() == info.shape(),
vigra_precondition(view.size() == info.size(), "importVolume(): the images have inconsistent sizes.");
"importVolume(): image size mismatch.");
importImage (info, destImage(view)); importImage (info, destImage(view));
} }
} }
} }
VIGRA_EXPORT void findImageSequence(const std::string &name_base, VIGRA_EXPORT void findImageSequence(const std::string &name_base,
const std::string &name_ext, const std::string &name_ext,
std::vector<std::string> & numbers); std::vector<std::string> & numbers);
/** \addtogroup VolumeImpex Import/export of volume data.
*/
//@{
/********************************************************/ /********************************************************/
/* */ /* */
/* importVolume */ /* importVolume */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Function for importing a 3D volume. /** \brief Function for importing a 3D volume.
The data are expected to be stored in a by-slice manner, The data are expected to be stored in a by-slice manner,
where the slices are enumerated from <tt>name_base+"[0-9]+"+name_ext</t t>. where the slices are enumerated from <tt>name_base+"[0-9]+"+name_ext</t t>.
skipping to change at line 216 skipping to change at line 529
\<<a href="multi__impex_8hxx-source.html">vigra/multi_impex.hxx</a>\> \<<a href="multi__impex_8hxx-source.html">vigra/multi_impex.hxx</a>\>
Namespace: vigra Namespace: vigra
*/ */
template <class T, class Allocator> template <class T, class Allocator>
void importVolume (MultiArray <3, T, Allocator> & volume, void importVolume (MultiArray <3, T, Allocator> & volume,
const std::string &name_base, const std::string &name_base,
const std::string &name_ext) const std::string &name_ext)
{ {
VolumeImportInfo info(name_base, name_ext); VolumeImportInfo info(name_base, name_ext);
volume.reshape(info.shape());
info.importImpl(volume); info.importImpl(volume);
} }
/** \brief Function for importing a 3D volume. /** \brief Function for importing a 3D volume.
The data can be given in two ways: The data can be given in two ways:
<UL> <UL>
<LI> If the volume is stored in a by-slice manner (e.g. one image per s lice), <LI> If the volume is stored in a by-slice manner (e.g. one image per s lice),
skipping to change at line 262 skipping to change at line 576
<b>\#include</b> <b>\#include</b>
\<<a href="multi__impex_8hxx-source.html">vigra/multi_impex.hxx</a>\> \<<a href="multi__impex_8hxx-source.html">vigra/multi_impex.hxx</a>\>
Namespace: vigra Namespace: vigra
*/ */
template <class T, class Allocator> template <class T, class Allocator>
void importVolume(MultiArray <3, T, Allocator> &volume, void importVolume(MultiArray <3, T, Allocator> &volume,
const std::string &filename) const std::string &filename)
{ {
VolumeImportInfo info(filename); VolumeImportInfo info(filename);
volume.reshape(info.shape());
info.importImpl(volume); info.importImpl(volume);
} }
/** \brief Function for importing a 3D volume. /** \brief Function for importing a 3D volume.
Read the volume data set <tt>info</tt> refers to. Explicit construction Read the volume data set <tt>info</tt> refers to. Explicit construction
of the info object allows to allocate a <tt>volume</tt> object type who se of the info object allows to allocate a <tt>volume</tt> object type who se
<tt>value_type</tt> matches the voxel type of the stored data. <tt>value_type</tt> matches the voxel type of the stored data.
The <tt>volume</tt> will be reshaped to match the count and The <tt>volume</tt> will be reshaped to match the count and
size of the slices found. size of the slices found.
<b>\#include</b> <b>\#include</b>
\<<a href="multi__impex_8hxx-source.html">vigra/multi_impex.hxx</a>\> \<<a href="multi__impex_8hxx-source.html">vigra/multi_impex.hxx</a>\>
Namespace: vigra Namespace: vigra
*/ */
template <class T, class Allocator> template <class T, class Stride>
void importVolume(VolumeImportInfo const & info, MultiArray <3, T, Allocato void importVolume(VolumeImportInfo const & info, MultiArrayView <3, T, Stri
r> &volume) de> &volume)
{ {
info.importImpl(volume); info.importImpl(volume);
} }
namespace detail { namespace detail {
template <class T> template <class T>
void setRangeMapping(std::string const & pixeltype, void setRangeMapping(std::string const & pixeltype,
FindMinMax<T> const & minmax, ImageExportInfo & info) FindMinMax<T> const & minmax, ImageExportInfo & info)
{ {
if(pixeltype == "UINT8") if(pixeltype == "UINT8")
info.setForcedRangeMapping(minmax.min, minmax.max, info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
(double)NumericTraits<Int8>::min(), (double)NumericTraits<UInt8>::min(),
(double)NumericTraits<Int8>::max()); (double)NumericTraits<UInt8>::max());
else if(pixeltype == "INT16") else if(pixeltype == "INT16")
info.setForcedRangeMapping(minmax.min, minmax.max, info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
(double)NumericTraits<Int16>::min(), (double)NumericTraits<Int16>::min(),
(double)NumericTraits<Int16>::max()); (double)NumericTraits<Int16>::max());
else if(pixeltype == "UINT16") else if(pixeltype == "UINT16")
info.setForcedRangeMapping(minmax.min, minmax.max, info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
(double)NumericTraits<UInt16>::min(), (double)NumericTraits<UInt16>::min(),
(double)NumericTraits<UInt16>::max()); (double)NumericTraits<UInt16>::max());
else if(pixeltype == "INT32") else if(pixeltype == "INT32")
info.setForcedRangeMapping(minmax.min, minmax.max, info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
(double)NumericTraits<Int32>::min(), (double)NumericTraits<Int32>::min(),
(double)NumericTraits<Int32>::max()); (double)NumericTraits<Int32>::max());
else if(pixeltype == "UINT32") else if(pixeltype == "UINT32")
info.setForcedRangeMapping(minmax.min, minmax.max, info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
(double)NumericTraits<UInt32>::min(), (double)NumericTraits<UInt32>::min(),
(double)NumericTraits<UInt32>::max()); (double)NumericTraits<UInt32>::max());
else if(pixeltype == "FLOAT") else if(pixeltype == "FLOAT")
info.setForcedRangeMapping(minmax.min, minmax.max, 0.0, 1.0); info.setForcedRangeMapping((double)minmax.min, (double)minmax.max, 0.0, 1.0);
else if(pixeltype == "DOUBLE") else if(pixeltype == "DOUBLE")
info.setForcedRangeMapping(minmax.min, minmax.max, 0.0, 1.0); info.setForcedRangeMapping((double)minmax.min, (double)minmax.max, 0.0, 1.0);
} }
template <class T, class Tag> template <class T, class Tag>
void setRangeMapping(MultiArrayView <3, T, Tag> const & volume, void setRangeMapping(MultiArrayView <3, T, Tag> const & volume,
ImageExportInfo & info, VigraTrueType /* isScalar */) ImageExportInfo & info, VigraTrueType /* isScalar */)
{ {
std::string pixeltype = info.getPixelType(); std::string pixeltype = info.getPixelType();
bool downcast = negotiatePixelType(getEncoderType(info.getFileName(), i nfo.getFileType()), bool downcast = negotiatePixelType(getEncoderType(info.getFileName(), i nfo.getFileType()),
TypeAsString<T>::result(), pixeltype ); TypeAsString<T>::result(), pixeltype );
skipping to change at line 379 skipping to change at line 694
does not support the source voxel type, all slices will be mapped simul taneously does not support the source voxel type, all slices will be mapped simul taneously
to the appropriate target range. to the appropriate target range.
<b>\#include</b> <b>\#include</b>
\<<a href="multi__impex_8hxx-source.html">vigra/multi_impex.hxx</a>\> \<<a href="multi__impex_8hxx-source.html">vigra/multi_impex.hxx</a>\>
Namespace: vigra Namespace: vigra
*/ */
template <class T, class Tag> template <class T, class Tag>
void exportVolume (MultiArrayView <3, T, Tag> const & volume, void exportVolume (MultiArrayView <3, T, Tag> const & volume,
const std::string &name_base, const VolumeExportInfo & volinfo)
const std::string &name_ext)
{ {
std::string name = name_base + name_ext; std::string name = std::string(volinfo.getFileNameBase()) + std::string (volinfo.getFileNameExt());
ImageExportInfo info(name.c_str()); ImageExportInfo info(name.c_str());
info.setCompression(volinfo.getCompression());
info.setPixelType(volinfo.getPixelType());
detail::setRangeMapping(volume, info, typename NumericTraits<T>::isScal ar()); detail::setRangeMapping(volume, info, typename NumericTraits<T>::isScal ar());
const unsigned int depth = volume.shape (2); const unsigned int depth = volume.shape (2);
int numlen = static_cast <int> (std::ceil (std::log10 ((double)depth))) ; int numlen = static_cast <int> (std::ceil (std::log10 ((double)depth))) ;
for (unsigned int i = 0; i < depth; ++i) for (unsigned int i = 0; i < depth; ++i)
{ {
// build the filename // build the filename
std::stringstream stream; std::stringstream stream;
stream << std::setfill ('0') << std::setw (numlen) << i; stream << std::setfill ('0') << std::setw (numlen) << i;
std::string name_num; std::string name_num;
stream >> name_num; stream >> name_num;
std::string name = name_base + name_num + name_ext; std::string name = std::string(volinfo.getFileNameBase()) + name_nu
m + std::string(volinfo.getFileNameExt());
if(i == 0)
{
}
// generate a basic image view to the current layer MultiArrayView <2, T, Tag> view (volume.bindOuter (i));
MultiArrayView <2, T, Tag> array_view (volume.bindOuter (i));
BasicImageView <T> view = makeBasicImageView (array_view);
// export the image // export the image
info.setFileName(name.c_str ()); info.setFileName(name.c_str ());
exportImage(srcImageRange(view), info); exportImage(srcImageRange(view), info);
} }
} }
// for backward compatibility
template <class T, class Tag>
inline
void exportVolume (MultiArrayView <3, T, Tag> const & volume,
const std::string &name_base,
const std::string &name_ext)
{
VolumeExportInfo volinfo(name_base.c_str(), name_ext.c_str());
exportVolume(volume, volinfo);
}
//@} //@}
} // namespace vigra } // namespace vigra
#endif // VIGRA_MULTI_IMPEX_HXX #endif // VIGRA_MULTI_IMPEX_HXX
 End of changes. 42 change blocks. 
57 lines changed or deleted 413 lines changed or added


 multi_iterator.hxx   multi_iterator.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2003-2008 by Gunnar Kedenburg and Ullrich Koethe */ /* Copyright 2003-2008 by Gunnar Kedenburg and Ullrich Koethe */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* ( Version 1.3.0, Sep 10 2004 ) */ /* ( Version 1.3.0, Sep 10 2004 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 2 change blocks. 
2 lines changed or deleted 1 lines changed or added


 multi_morphology.hxx   multi_morphology.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2003-2007 by Kasim Terzic, Christian-Dennis Rahn */ /* Copyright 2003-2007 by Kasim Terzic, Christian-Dennis Rahn */
/* and Ullrich Koethe */ /* and Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 57 skipping to change at line 55
#include "accessor.hxx" #include "accessor.hxx"
#include "numerictraits.hxx" #include "numerictraits.hxx"
#include "navigator.hxx" #include "navigator.hxx"
#include "metaprogramming.hxx" #include "metaprogramming.hxx"
#include "multi_pointoperators.hxx" #include "multi_pointoperators.hxx"
#include "functorexpression.hxx" #include "functorexpression.hxx"
namespace vigra namespace vigra
{ {
namespace detail {
// this class simplfies the design, but more importantly, it makes sure
// that the in-place code doesn't get compiled for boolean arrays
// (were it would never executed anyway -- see the specializations below)
template <class DestType, class TmpType>
struct MultiBinaryMorphologyImpl
{
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
static void
exec( SrcIterator s, SrcShape const & shape, SrcAccessor src,
DestIterator d, DestAccessor dest,
double radius, bool dilation)
{
using namespace vigra::functor;
// Allocate a new temporary array if the distances squared wouldn't
fit
MultiArray<SrcShape::static_size, TmpType> tmpArray(shape);
separableMultiDistSquared(s, shape, src,
tmpArray.traverser_begin(), typename Acce
ssorTraits<TmpType>::default_accessor(), dilation );
// threshold everything less than radius away from the edge
double radius2 = radius * radius;
DestType foreground = dilation
? NumericTraits<DestType>::zero()
: NumericTraits<DestType>::one(),
background = dilation
? NumericTraits<DestType>::one()
: NumericTraits<DestType>::zero();
transformMultiArray( tmpArray.traverser_begin(), shape, StandardVal
ueAccessor<double>(),
d, dest,
ifThenElse( Arg1() >= Param(radius2),
Param(foreground), Param(backgroun
d) ) );
}
};
template <class DestType>
struct MultiBinaryMorphologyImpl<DestType, DestType>
{
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
static void
exec( SrcIterator s, SrcShape const & shape, SrcAccessor src,
DestIterator d, DestAccessor dest,
double radius, bool dilation)
{
using namespace vigra::functor;
separableMultiDistSquared( s, shape, src, d, dest, dilation );
// threshold everything less than radius away from the edge
DestType radius2 = detail::RequiresExplicitCast<DestType>::cast(rad
ius * radius);
DestType foreground = dilation
? NumericTraits<DestType>::zero()
: NumericTraits<DestType>::one(),
background = dilation
? NumericTraits<DestType>::one()
: NumericTraits<DestType>::zero();
transformMultiArray( d, shape, dest, d, dest,
ifThenElse( Arg1() > Param(radius2),
Param(foreground), Param(backgroun
d) ) );
}
};
template <>
struct MultiBinaryMorphologyImpl<bool, bool>
{
template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor>
static void
exec( SrcIterator s, SrcShape const & shape, SrcAccessor src,
DestIterator d, DestAccessor dest, double radius, bool dilation)
{
vigra_fail("multiBinaryMorphology(): Internal error (this function
should never be called).");
}
};
} // namespace detail
/** \addtogroup MultiArrayMorphology Morphological operators for multi-dime nsional arrays. /** \addtogroup MultiArrayMorphology Morphological operators for multi-dime nsional arrays.
These functions perform morphological operations on an arbitrary These functions perform morphological operations on an arbitrary
dimensional array that is specified by iterators (compatible to \ref Mu ltiIteratorPage) dimensional array that is specified by iterators (compatible to \ref Mu ltiIteratorPage)
and shape objects. It can therefore be applied to a wide range of data structures and shape objects. It can therefore be applied to a wide range of data structures
(\ref vigra::MultiArrayView, \ref vigra::MultiArray etc.). (\ref vigra::MultiArrayView, \ref vigra::MultiArray etc.).
*/ */
//@{ //@{
/********************************************************/ /********************************************************/
/* */ /* */
/* multiBinaryErosion */ /* multiBinaryErosion */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Binary erosion on multi-dimensional arrays. /** \brief Binary erosion on multi-dimensional arrays.
This function applies a flat circular erosion operator with a given rad ius. The This function applies a flat circular erosion operator with a given rad ius. The
operation is isotropic. operation is isotropic. The input is intepreted as a binary multi-dimen
The input is a binary multi-dimensional array where non-zero pixels rep sional
resent array where non-zero pixels represent foreground and zero pixels repres
foreground and zero pixels represent background. ent
background. In the output, foregound is always represented by ones
(i.e. NumericTrais<typename DestAccessor::value_type>::one()).
This function may work in-place, which means that <tt>siter == diter</t t> is allowed. This function may work in-place, which means that <tt>siter == diter</t t> is allowed.
A full-sized internal array is only allocated if working on the destina A temporary internal array is only allocated if working on the destinat
tion ion
array directly would cause overflow errors (i.e. if array directly would cause overflow errors (that is if
<tt> typeid(typename DestAccessor::value_type) < N * M*M</tt>, where M <tt> NumericTraits<typename DestAccessor::value_type>::max() < squaredN
is the orm(shape)</tt>,
size of the largest dimension of the array. i.e. the squared length of the image diagonal doesn't fit into the dest
ination type).
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
multiBinaryErosion(SrcIterator siter, SrcShape const & shape, SrcAc cessor src, multiBinaryErosion(SrcIterator siter, SrcShape const & shape, SrcAc cessor src,
skipping to change at line 133 skipping to change at line 213
\endcode \endcode
\see vigra::discErosion() \see vigra::discErosion()
*/ */
doxygen_overloaded_function(template <...> void multiBinaryErosion) doxygen_overloaded_function(template <...> void multiBinaryErosion)
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
multiBinaryErosion( SrcIterator s, SrcShape const & shape, SrcAccessor src, multiBinaryErosion( SrcIterator s, SrcShape const & shape, SrcAccessor src,
DestIterator d, DestAccessor dest, float radiu s) DestIterator d, DestAccessor dest, double radi us)
{ {
typedef typename NumericTraits<typename DestAccessor::value_type>::Valu typedef typename DestAccessor::value_type DestType;
eType DestType; typedef Int32 TmpType;
typedef typename NumericTraits<typename DestAccessor::value_type>::Prom
ote TmpType;
DestType MaxValue = NumericTraits<DestType>::max();
float radius2 = (float) radius * radius;
enum { N = 1 + SrcIterator::level };
int MaxDim = 0;
for( int i=0; i<N; i++)
if(MaxDim < shape[i]) MaxDim = shape[i];
using namespace vigra::functor; double dmax = squaredNorm(shape);
// Get the distance squared transform of the image // Get the distance squared transform of the image
if(N*MaxDim*MaxDim > MaxValue) if(dmax > NumericTraits<DestType>::toRealPromote(NumericTraits<DestType >::max()))
{ {
// Allocate a new temporary array if the distances squared wouldn't detail::MultiBinaryMorphologyImpl<DestType, TmpType>::exec(s, shape
fit , src, d, dest, radius, false);
MultiArray<SrcShape::static_size, TmpType> tmpArray(shape);
//detail::internalSeparableMultiArrayDistTmp( s, shape, src, tmpArr
ay.traverser_begin(),
// typename AccessorTraits<TmpType>::default_accessor()/*, false
*/ );
separableMultiDistSquared(s, shape, src, tmpArray.traverser_begin()
,
typename AccessorTraits<TmpType>::default_accessor(), false
);
// threshold everything less than radius away from the edge
// std::cerr << "Thresholding!!!!!" << std::endl;
transformMultiArray( tmpArray.traverser_begin(), shape,
typename AccessorTraits<TmpType>::default_accessor(), d, dest,
ifThenElse( Arg1() > Param(radius2),
Param(MaxValue), Param(0) ) );
} }
else // work directly on the destination array else // work directly on the destination array
{ {
//detail::internalSeparableMultiArrayDistTmp( s, shape, src, d, des detail::MultiBinaryMorphologyImpl<DestType, DestType>::exec(s, shap
t/*, false*/ ); e, src, d, dest, radius, false);
separableMultiDistSquared( s, shape, src, d, dest, false );
// threshold everything less than radius away from the edge
transformMultiArray( d, shape, dest, d, dest,
ifThenElse( Arg1() > Param(radius2),
Param(MaxValue), Param(0) ) );
} }
} }
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline inline
void multiBinaryErosion( void multiBinaryErosion(
triple<SrcIterator, SrcShape, SrcAccessor> const & source, triple<SrcIterator, SrcShape, SrcAccessor> const & source,
pair<DestIterator, DestAccessor> const & dest, int radius) pair<DestIterator, DestAccessor> const & dest, double radius)
{ {
multiBinaryErosion( source.first, source.second, source.third, multiBinaryErosion( source.first, source.second, source.third,
dest.first, dest.second, radius ); dest.first, dest.second, radius );
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* multiBinaryDilation */ /* multiBinaryDilation */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Binary dilation on multi-dimensional arrays. /** \brief Binary dilation on multi-dimensional arrays.
This function applies a flat circular dilation operator with a given ra dius. The This function applies a flat circular dilation operator with a given ra dius. The
operation is isotropic. operation is isotropic. The input is intepreted as a binary multi-dimen
The input is a binary multi-dimensional array where non-zero pixels rep sional
resent array where non-zero pixels represent foreground and zero pixels repres
foreground and zero pixels represent background. ent
background. In the output, foregound is always represented by ones
(i.e. NumericTrais<typename DestAccessor::value_type>::one()).
This function may work in-place, which means that <tt>siter == diter</t t> is allowed. This function may work in-place, which means that <tt>siter == diter</t t> is allowed.
A full-sized internal array is only allocated if working on the destina A temporary internal array is only allocated if working on the destinat
tion ion
array directly would cause overflow errors (i.e. if array directly would cause overflow errors (that is if
<tt> typeid(typename DestAccessor::value_type) < N * M*M</tt>, where M <tt> NumericTraits<typename DestAccessor::value_type>::max() < squaredN
is the orm(shape)</tt>,
size of the largest dimension of the array. i.e. the squared length of the image diagonal doesn't fit into the dest
ination type).
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
multiBinaryDilation(SrcIterator siter, SrcShape const & shape, SrcA ccessor src, multiBinaryDilation(SrcIterator siter, SrcShape const & shape, SrcA ccessor src,
skipping to change at line 256 skipping to change at line 311
\endcode \endcode
\see vigra::discDilation() \see vigra::discDilation()
*/ */
doxygen_overloaded_function(template <...> void multiBinaryDilation) doxygen_overloaded_function(template <...> void multiBinaryDilation)
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
multiBinaryDilation( SrcIterator s, SrcShape const & shape, SrcAccessor src , multiBinaryDilation( SrcIterator s, SrcShape const & shape, SrcAccessor src ,
DestIterator d, DestAccessor dest, float radiu s) DestIterator d, DestAccessor dest, double radi us)
{ {
typedef typename NumericTraits<typename DestAccessor::value_type>::Valu typedef typename DestAccessor::value_type DestType;
eType DestType; typedef Int32 TmpType;
typedef typename NumericTraits<typename DestAccessor::value_type>::Prom
ote TmpType;
DestType MaxValue = NumericTraits<DestType>::max();
float radius2 = (float) radius * radius;
enum { N = 1 + SrcIterator::level };
int MaxDim = 0;
for( int i=0; i<N; i++)
if(MaxDim < shape[i]) MaxDim = shape[i];
using namespace vigra::functor; double dmax = squaredNorm(shape);
// Get the distance squared transform of the image // Get the distance squared transform of the image
if(N*MaxDim*MaxDim > MaxValue) if(dmax > NumericTraits<DestType>::toRealPromote(NumericTraits<DestType >::max()))
{ {
// Allocate a new temporary array if the distances squared wouldn't detail::MultiBinaryMorphologyImpl<DestType, TmpType>::exec(s, shape
fit , src, d, dest, radius, true);
MultiArray<SrcShape::static_size, TmpType> tmpArray(shape);
//detail::internalSeparableMultiArrayDistTmp( s, shape, src, tmpArr
ay.traverser_begin(),
// typename AccessorTraits<TmpType>::default_accessor(), true );
separableMultiDistSquared(s, shape, src, tmpArray.traverser_begin()
,
typename AccessorTraits<TmpType>::default_accessor(), true );
// threshold everything less than radius away from the edge
transformMultiArray( tmpArray.traverser_begin(), shape,
typename AccessorTraits<TmpType>::default_accessor(), d, dest,
ifThenElse( Arg1() > Param(radius2),
Param(0), Param(MaxValue) ) );
} }
else // work directly on the destination array else // work directly on the destination array
{ {
//detail::internalSeparableMultiArrayDistTmp( s, shape, src, d, des detail::MultiBinaryMorphologyImpl<DestType, DestType>::exec(s, shap
t, true ); e, src, d, dest, radius, true);
separableMultiDistSquared( s, shape, src, d, dest, true );
// threshold everything less than radius away from the edge
transformMultiArray( d, shape, dest, d, dest,
ifThenElse( Arg1() > Param(radius2),
Param(0), Param(MaxValue) ) );
} }
} }
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline inline
void multiBinaryDilation( void multiBinaryDilation(
triple<SrcIterator, SrcShape, SrcAccessor> const & source, triple<SrcIterator, SrcShape, SrcAccessor> const & source,
pair<DestIterator, DestAccessor> const & dest, int radius) pair<DestIterator, DestAccessor> const & dest, double radius)
{ {
multiBinaryDilation( source.first, source.second, source.third, multiBinaryDilation( source.first, source.second, source.third,
dest.first, dest.second, radius ); dest.first, dest.second, radius );
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* multiGrayscaleErosion */ /* multiGrayscaleErosion */
/* */ /* */
/********************************************************/ /********************************************************/
skipping to change at line 336 skipping to change at line 366
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
multiGrayscaleErosion(SrcIterator siter, SrcShape const & shape, Sr cAccessor src, multiGrayscaleErosion(SrcIterator siter, SrcShape const & shape, Sr cAccessor src,
DestIterator diter, DestAccessor dest, float sigma); DestIterator diter, DestAccessor dest, double sigma);
} }
\endcode \endcode
use argument objects in conjunction with \ref ArgumentObjectFactories : use argument objects in conjunction with \ref ArgumentObjectFactories :
\code \code
namespace vigra { namespace vigra {
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
multiGrayscaleErosion(triple<SrcIterator, SrcShape, SrcAccessor> co nst & source, multiGrayscaleErosion(triple<SrcIterator, SrcShape, SrcAccessor> co nst & source,
pair<DestIterator, DestAccessor> const & dest, pair<DestIterator, DestAccessor> const & dest,
float sigma); double sigma);
} }
\endcode \endcode
<b> Usage:</b> <b> Usage:</b>
<b>\#include</b> \<<a href="multi__morphology_8hxx-source.html">vigra/m ulti_morphology.hxx</a>\> <b>\#include</b> \<<a href="multi__morphology_8hxx-source.html">vigra/m ulti_morphology.hxx</a>\>
\code \code
MultiArray<3, unsigned char>::size_type shape(width, height, depth); MultiArray<3, unsigned char>::size_type shape(width, height, depth);
skipping to change at line 376 skipping to change at line 406
\endcode \endcode
\see vigra::discErosion() \see vigra::discErosion()
*/ */
doxygen_overloaded_function(template <...> void multiGrayscaleErosion) doxygen_overloaded_function(template <...> void multiGrayscaleErosion)
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
multiGrayscaleErosion( SrcIterator s, SrcShape const & shape, SrcAccessor s rc, multiGrayscaleErosion( SrcIterator s, SrcShape const & shape, SrcAccessor s rc,
DestIterator d, DestAccessor dest, float sigma) DestIterator d, DestAccessor dest, double sigma)
{ {
typedef typename NumericTraits<typename DestAccessor::value_type>::Valu eType DestType; typedef typename NumericTraits<typename DestAccessor::value_type>::Valu eType DestType;
typedef typename NumericTraits<typename DestAccessor::value_type>::Prom ote TmpType; typedef typename NumericTraits<typename DestAccessor::value_type>::Prom ote TmpType;
DestType MaxValue = NumericTraits<DestType>::max(); DestType MaxValue = NumericTraits<DestType>::max();
enum { N = 1 + SrcIterator::level }; enum { N = 1 + SrcIterator::level };
// temporay array to hold the current line to enable in-place operation // temporay array to hold the current line to enable in-place operation
ArrayVector<TmpType> tmp( shape[0] ); ArrayVector<TmpType> tmp( shape[0] );
typedef MultiArrayNavigator<SrcIterator, N> SNavigator; typedef MultiArrayNavigator<SrcIterator, N> SNavigator;
typedef MultiArrayNavigator<DestIterator, N> DNavigator; typedef MultiArrayNavigator<DestIterator, N> DNavigator;
int MaxDim = 0; int MaxDim = 0;
for( int i=0; i<N; i++) for( int i=0; i<N; i++)
if(MaxDim < shape[i]) MaxDim = shape[i]; if(MaxDim < shape[i]) MaxDim = shape[i];
using namespace vigra::functor; using namespace vigra::functor;
ArrayVector<double> sigmas(shape.size(), sigma);
// Allocate a new temporary array if the distances squared wouldn't fit // Allocate a new temporary array if the distances squared wouldn't fit
if(N*MaxDim*MaxDim > MaxValue) if(N*MaxDim*MaxDim > MaxValue)
{ {
MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); MultiArray<SrcShape::static_size, TmpType> tmpArray(shape);
detail::internalSeparableMultiArrayDistTmp( s, shape, src, tmpArray .traverser_begin(), detail::internalSeparableMultiArrayDistTmp( s, shape, src, tmpArray .traverser_begin(),
typename AccessorTraits<TmpType>::default_accessor(), sigma ); typename AccessorTraits<TmpType>::default_accessor(), sigmas );
transformMultiArray( tmpArray.traverser_begin(), shape, transformMultiArray( tmpArray.traverser_begin(), shape,
typename AccessorTraits<TmpType>::default_accessor(), d, de st, typename AccessorTraits<TmpType>::default_accessor(), d, de st,
ifThenElse( Arg1() > Param(MaxValue), Param(MaxValue), Arg1 () ) ); ifThenElse( Arg1() > Param(MaxValue), Param(MaxValue), Arg1 () ) );
//copyMultiArray( tmpArray.traverser_begin(), shape, //copyMultiArray( tmpArray.traverser_begin(), shape,
// typename AccessorTraits<TmpType>::default_accessor(), d, dest ); // typename AccessorTraits<TmpType>::default_accessor(), d, dest );
} }
else else
{ {
detail::internalSeparableMultiArrayDistTmp( s, shape, src, d, dest, sigma ); detail::internalSeparableMultiArrayDistTmp( s, shape, src, d, dest, sigmas );
} }
} }
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline inline
void multiGrayscaleErosion( void multiGrayscaleErosion(
triple<SrcIterator, SrcShape, SrcAccessor> const & source, triple<SrcIterator, SrcShape, SrcAccessor> const & source,
pair<DestIterator, DestAccessor> const & dest, float sigma) pair<DestIterator, DestAccessor> const & dest, double sigma)
{ {
multiGrayscaleErosion( source.first, source.second, source.third, multiGrayscaleErosion( source.first, source.second, source.third,
dest.first, dest.second, sigma); dest.first, dest.second, sigma);
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* multiGrayscaleDilation */ /* multiGrayscaleDilation */
/* */ /* */
/********************************************************/ /********************************************************/
skipping to change at line 453 skipping to change at line 485
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
multiGrayscaleDilation(SrcIterator siter, SrcShape const & shape, S rcAccessor src, multiGrayscaleDilation(SrcIterator siter, SrcShape const & shape, S rcAccessor src,
DestIterator diter, DestAccessor dest, float sigma); DestIterator diter, DestAccessor dest, double sigma);
} }
\endcode \endcode
use argument objects in conjunction with \ref ArgumentObjectFactories : use argument objects in conjunction with \ref ArgumentObjectFactories :
\code \code
namespace vigra { namespace vigra {
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
multiGrayscaleDilation(triple<SrcIterator, SrcShape, SrcAccessor> c onst & source, multiGrayscaleDilation(triple<SrcIterator, SrcShape, SrcAccessor> c onst & source,
pair<DestIterator, DestAccessor> const & dest, pair<DestIterator, DestAccessor> const & dest,
float sigma); double sigma);
} }
\endcode \endcode
<b> Usage:</b> <b> Usage:</b>
<b>\#include</b> \<<a href="multi__morphology_8hxx-source.html">vigra/m ulti_morphology.hxx</a>\> <b>\#include</b> \<<a href="multi__morphology_8hxx-source.html">vigra/m ulti_morphology.hxx</a>\>
\code \code
MultiArray<3, unsigned char>::size_type shape(width, height, depth); MultiArray<3, unsigned char>::size_type shape(width, height, depth);
skipping to change at line 492 skipping to change at line 524
multiGrayscaleDilation(srcMultiArrayRange(source), destMultiArray(dest) , 3.0); multiGrayscaleDilation(srcMultiArrayRange(source), destMultiArray(dest) , 3.0);
\endcode \endcode
\see vigra::discErosion() \see vigra::discErosion()
*/ */
doxygen_overloaded_function(template <...> void multiGrayscaleDilation) doxygen_overloaded_function(template <...> void multiGrayscaleDilation)
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void multiGrayscaleDilation( SrcIterator s, SrcShape const & shape, SrcAcce ssor src, void multiGrayscaleDilation( SrcIterator s, SrcShape const & shape, SrcAcce ssor src,
DestIterator d, DestAccessor dest, float sigma ) DestIterator d, DestAccessor dest, double sigm a)
{ {
typedef typename NumericTraits<typename DestAccessor::value_type>::Valu eType DestType; typedef typename NumericTraits<typename DestAccessor::value_type>::Valu eType DestType;
typedef typename NumericTraits<typename DestAccessor::value_type>::Prom ote TmpType; typedef typename NumericTraits<typename DestAccessor::value_type>::Prom ote TmpType;
DestType MinValue = NumericTraits<DestType>::min(); DestType MinValue = NumericTraits<DestType>::min();
DestType MaxValue = NumericTraits<DestType>::max(); DestType MaxValue = NumericTraits<DestType>::max();
enum { N = 1 + SrcIterator::level }; enum { N = 1 + SrcIterator::level };
// temporay array to hold the current line to enable in-place operation // temporay array to hold the current line to enable in-place operation
ArrayVector<TmpType> tmp( shape[0] ); ArrayVector<TmpType> tmp( shape[0] );
typedef MultiArrayNavigator<SrcIterator, N> SNavigator; typedef MultiArrayNavigator<SrcIterator, N> SNavigator;
typedef MultiArrayNavigator<DestIterator, N> DNavigator; typedef MultiArrayNavigator<DestIterator, N> DNavigator;
int MaxDim = 0; int MaxDim = 0;
for( int i=0; i<N; i++) for( int i=0; i<N; i++)
if(MaxDim < shape[i]) MaxDim = shape[i]; if(MaxDim < shape[i]) MaxDim = shape[i];
using namespace vigra::functor; using namespace vigra::functor;
ArrayVector<double> sigmas(shape.size(), sigma);
// Allocate a new temporary array if the distances squared wouldn't fit // Allocate a new temporary array if the distances squared wouldn't fit
if(-N*MaxDim*MaxDim < MinValue || N*MaxDim*MaxDim > MaxValue) if(-N*MaxDim*MaxDim < MinValue || N*MaxDim*MaxDim > MaxValue)
{ {
MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); MultiArray<SrcShape::static_size, TmpType> tmpArray(shape);
detail::internalSeparableMultiArrayDistTmp( s, shape, src, tmpArray .traverser_begin(), detail::internalSeparableMultiArrayDistTmp( s, shape, src, tmpArray .traverser_begin(),
typename AccessorTraits<TmpType>::default_accessor(), sigma, tr ue ); typename AccessorTraits<TmpType>::default_accessor(), sigmas, t rue );
transformMultiArray( tmpArray.traverser_begin(), shape, transformMultiArray( tmpArray.traverser_begin(), shape,
typename AccessorTraits<TmpType>::default_accessor(), d, de st, typename AccessorTraits<TmpType>::default_accessor(), d, de st,
ifThenElse( Arg1() > Param(MaxValue), Param(MaxValue), ifThenElse( Arg1() > Param(MaxValue), Param(MaxValue),
ifThenElse( Arg1() < Param(MinValue), Param(MinValue), Arg1() ) ) ); ifThenElse( Arg1() < Param(MinValue), Param(MinValue), Arg1() ) ) );
} }
else else
{ {
detail::internalSeparableMultiArrayDistTmp( s, shape, src, d, dest, sigma, true ); detail::internalSeparableMultiArrayDistTmp( s, shape, src, d, dest, sigmas, true );
} }
} }
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline inline
void multiGrayscaleDilation( void multiGrayscaleDilation(
triple<SrcIterator, SrcShape, SrcAccessor> const & source, triple<SrcIterator, SrcShape, SrcAccessor> const & source,
pair<DestIterator, DestAccessor> const & dest, float sigma) pair<DestIterator, DestAccessor> const & dest, double sigma)
{ {
multiGrayscaleDilation( source.first, source.second, source.third, multiGrayscaleDilation( source.first, source.second, source.third,
dest.first, dest.second, sigma); dest.first, dest.second, sigma);
} }
//@} //@}
} //-- namespace vigra } //-- namespace vigra
#endif //-- VIGRA_MULTI_MORPHOLOGY_HXX #endif //-- VIGRA_MULTI_MORPHOLOGY_HXX
 End of changes. 36 change blocks. 
116 lines changed or deleted 151 lines changed or added


 multi_pointoperators.hxx   multi_pointoperators.hxx 
//-- -*- c++ -*- //-- -*- c++ -*-
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2003 by Ullrich Koethe, B. Seppke, F. Heinrich */ /* Copyright 2003 by Ullrich Koethe, B. Seppke, F. Heinrich */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 441 skipping to change at line 439
/********************************************************/ /********************************************************/
/* */ /* */
/* transformMultiArray */ /* transformMultiArray */
/* */ /* */
/********************************************************/ /********************************************************/
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestShape, class DestAccessor, class DestIterator, class DestShape, class DestAccessor,
class Functor> class Functor>
void void
transformMultiArrayReduceImpl(SrcIterator s, SrcShape const & sshape, SrcAc cessor src, transformMultiArrayReduceImpl(SrcIterator s, SrcShape const &, SrcAccessor src,
DestIterator d, DestShape const & dshape, DestAccessor dest, DestIterator d, DestShape const & dshape, DestAccessor dest,
SrcShape const & reduceShape, SrcShape const & reduceShape,
Functor const & ff, MetaInt<0>) Functor const & ff, MetaInt<0>)
{ {
DestIterator dend = d + dshape[0]; DestIterator dend = d + dshape[0];
for(; d < dend; ++s.template dim<0>(), ++d) for(; d < dend; ++s.template dim<0>(), ++d)
{ {
Functor f = ff; Functor f = ff;
inspectMultiArray(s, reduceShape, src, f); inspectMultiArray(s, reduceShape, src, f);
dest.set(f(), d); dest.set(f(), d);
skipping to change at line 708 skipping to change at line 706
Array src(Array::size_type(100, 200, 50)), Array src(Array::size_type(100, 200, 50)),
dest(Array::size_type(1, 1, 50)); dest(Array::size_type(1, 1, 50));
... ...
vigra::transformMultiArray(srcMultiArrayRange(src), vigra::transformMultiArray(srcMultiArrayRange(src),
destMultiArrayRange(dest), destMultiArrayRange(dest),
vigra::FindAverage<float>() ); vigra::FindAverage<float>() );
\endcode \endcode
Note that the functor must define the appropriate traits described belo
w in order to be
recognized as a reduce functor. This is most easily achieved by derivin
g from
<tt>UnaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits).
<b> Required Interface:</b> <b> Required Interface:</b>
In standard and expand mode, the functor must be a model of UnaryFuncti on In standard and expand mode, the functor must be a model of UnaryFuncti on
(i.e. support function call with one argument and a return value (i.e. support function call with one argument and a return value
<tt>res = functor(arg)</tt>): <tt>res = functor(arg)</tt>):
\code \code
MultiIterator src_begin, src_end, dest_begin; MultiIterator src_begin, src_end, dest_begin;
SrcAccessor src_accessor; SrcAccessor src_accessor;
skipping to change at line 731 skipping to change at line 733
dest_accessor.set(functor(src_accessor(src_begin)), dest_begin); dest_accessor.set(functor(src_accessor(src_begin)), dest_begin);
\endcode \endcode
In reduce mode, it must be a model of UnaryAnalyser (i.e. support funct ion call In reduce mode, it must be a model of UnaryAnalyser (i.e. support funct ion call
with one argument and no return vakue <tt>functor(arg)</tt>) and Initia lizer with one argument and no return vakue <tt>functor(arg)</tt>) and Initia lizer
(i.e. support function call with no argument, but return value (i.e. support function call with no argument, but return value
<tt>res = functor()</tt>). Internally, such functors are recognized by the <tt>res = functor()</tt>). Internally, such functors are recognized by the
meta functions <tt>FunctorTraits<FUNCTOR>::isUnaryAnalyser</tt> and meta functions <tt>FunctorTraits<FUNCTOR>::isUnaryAnalyser</tt> and
<tt>FunctorTraits<FUNCTOR>::isInitializer</tt> which must both yield <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> which must both yield
<tt>VigraTrueType</tt>. Make sure that your functor correctly defines <tt>VigraTrueType</tt>. Make sure that your functor correctly defines
<tt>FunctorTraits</tt> because otherwise reduce mode will not work. In <tt>FunctorTraits</tt> because otherwise reduce mode will not work.
addition, This is most easily achieved by deriving the functor from
the functor must be copy constructible in order to start each reduction <tt>UnaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits).
In addition, the functor must be copy constructible in order to start e
ach reduction
with a fresh functor. with a fresh functor.
\code \code
MultiIterator src_begin, src_end, dest_begin; MultiIterator src_begin, src_end, dest_begin;
SrcAccessor src_accessor; SrcAccessor src_accessor;
DestAccessor dest_accessor; DestAccessor dest_accessor;
FUNCTOR initial_functor, functor(initial_functor); FUNCTOR initial_functor, functor(initial_functor);
assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTru eType)); assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTru eType));
skipping to change at line 817 skipping to change at line 821
/* combineTwoMultiArrays */ /* combineTwoMultiArrays */
/* */ /* */
/********************************************************/ /********************************************************/
template <class SrcIterator1, class SrcShape, class SrcAccessor1, template <class SrcIterator1, class SrcShape, class SrcAccessor1,
class SrcIterator2, class SrcAccessor2, class SrcIterator2, class SrcAccessor2,
class DestIterator, class DestShape, class DestAccessor, class DestIterator, class DestShape, class DestAccessor,
class Functor> class Functor>
void void
combineTwoMultiArraysReduceImpl( combineTwoMultiArraysReduceImpl(
SrcIterator1 s1, SrcShape const & sshape, SrcAccessor1 src1, SrcIterator1 s1, SrcShape const & , SrcAccessor1 src1,
SrcIterator2 s2, SrcAccessor2 src2, SrcIterator2 s2, SrcAccessor2 src2,
DestIterator d, DestShape const & dshape, DestAccessor dest , DestIterator d, DestShape const & dshape, DestAccessor dest ,
SrcShape const & reduceShape, SrcShape const & reduceShape,
Functor const & ff, MetaInt<0>) Functor const & ff, MetaInt<0>)
{ {
DestIterator dend = d + dshape[0]; DestIterator dend = d + dshape[0];
for(; d < dend; ++s1.template dim<0>(), ++s2.template dim<0>(), ++d) for(; d < dend; ++s1.template dim<0>(), ++s2.template dim<0>(), ++d)
{ {
Functor f = ff; Functor f = ff;
inspectTwoMultiArrays(s1, reduceShape, src1, s2, src2, f); inspectTwoMultiArrays(s1, reduceShape, src1, s2, src2, f);
skipping to change at line 1144 skipping to change at line 1148
vigra::combineTwoMultiArrays( vigra::combineTwoMultiArrays(
srcMultiArrayRange(src1), srcMultiArrayRange(src1),
srcMultiArray(src2), srcMultiArray(src2),
destMultiArray(dest), destMultiArray(dest),
reduceFunctor(Arg1() + abs(Arg2() - Arg3()), 0) ); reduceFunctor(Arg1() + abs(Arg2() - Arg3()), 0) );
// Arg1() is the sum accumulated so far, initialzed with 0 // Arg1() is the sum accumulated so far, initialzed with 0
\endcode \endcode
Note that the functor must define the appropriate traits described belo
w in order to be
recognized as a reduce functor. This is most easily achieved by derivin
g from
<tt>BinaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits).
<b> Required Interface:</b> <b> Required Interface:</b>
In standard and expand mode, the functor must be a model of BinaryFunct ion In standard and expand mode, the functor must be a model of BinaryFunct ion
(i.e. support function call with two arguments and a return value (i.e. support function call with two arguments and a return value
<tt>res = functor(arg1, arg2)</tt>): <tt>res = functor(arg1, arg2)</tt>):
\code \code
MultiIterator src1_begin, src2_begin, dest_begin; MultiIterator src1_begin, src2_begin, dest_begin;
SrcAccessor1 src1_accessor; SrcAccessor1 src1_accessor;
skipping to change at line 1172 skipping to change at line 1180
\endcode \endcode
In reduce mode, it must be a model of BinaryAnalyser (i.e. support func tion call In reduce mode, it must be a model of BinaryAnalyser (i.e. support func tion call
with two arguments and no return vakue <tt>functor(arg1, arg2)</tt>) an d Initializer with two arguments and no return vakue <tt>functor(arg1, arg2)</tt>) an d Initializer
(i.e. support function call with no argument, but return value (i.e. support function call with no argument, but return value
<tt>res = functor()</tt>). Internally, such functors are recognized by the <tt>res = functor()</tt>). Internally, such functors are recognized by the
meta functions <tt>FunctorTraits<FUNCTOR>::isBinaryAnalyser</tt> and meta functions <tt>FunctorTraits<FUNCTOR>::isBinaryAnalyser</tt> and
<tt>FunctorTraits<FUNCTOR>::isInitializer</tt> which must both yield <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> which must both yield
<tt>VigraTrueType</tt>. Make sure that your functor correctly defines <tt>VigraTrueType</tt>. Make sure that your functor correctly defines
<tt>FunctorTraits</tt> because otherwise reduce mode will not work. In <tt>FunctorTraits</tt> because otherwise reduce mode will not work.
addition, This is most easily achieved by deriving the functor from
the functor must be copy constructible in order to start each reduction <tt>BinaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits).
In addition, the functor must be copy constructible in order to start e
ach reduction
with a fresh functor. with a fresh functor.
\code \code
MultiIterator src1_begin, src2_begin, dest_begin; MultiIterator src1_begin, src2_begin, dest_begin;
SrcAccessor1 src1_accessor; SrcAccessor1 src1_accessor;
SrcAccessor2 src2_accessor; SrcAccessor2 src2_accessor;
DestAccessor dest_accessor; DestAccessor dest_accessor;
FUNCTOR initial_functor, functor(initial_functor); FUNCTOR initial_functor, functor(initial_functor);
 End of changes. 9 change blocks. 
11 lines changed or deleted 25 lines changed or added


 multi_resize.hxx   multi_resize.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2004 by Ullrich Koethe */ /* Copyright 1998-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 43 skipping to change at line 41
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_MULTI_RESIZE_HXX #ifndef VIGRA_MULTI_RESIZE_HXX
#define VIGRA_MULTI_RESIZE_HXX #define VIGRA_MULTI_RESIZE_HXX
#include <vector> #include <vector>
#include "resizeimage.hxx" #include "resizeimage.hxx"
#include "navigator.hxx"
namespace vigra { namespace vigra {
namespace detail { namespace detail {
template <class SrcIterator, class Shape, class SrcAccessor, template <class SrcIterator, class Shape, class SrcAccessor,
class DestIterator, class DestAccessor, class Kernel> class DestIterator, class DestAccessor, class Kernel>
void void
internalResizeMultiArrayOneDimension( internalResizeMultiArrayOneDimension(
SrcIterator si, Shape const & sshape, SrcAccessor src , SrcIterator si, Shape const & sshape, SrcAccessor src ,
skipping to change at line 84 skipping to change at line 83
Rational<int> offset(0); Rational<int> offset(0);
resampling_detail::MapTargetToSourceCoordinate mapCoordinate(ratio, off set); resampling_detail::MapTargetToSourceCoordinate mapCoordinate(ratio, off set);
int period = lcm(ratio.numerator(), ratio.denominator()); int period = lcm(ratio.numerator(), ratio.denominator());
ArrayVector<double> const & prefilterCoeffs = spline.prefilterCoefficie nts(); ArrayVector<double> const & prefilterCoeffs = spline.prefilterCoefficie nts();
ArrayVector<Kernel1D<double> > kernels(period); ArrayVector<Kernel1D<double> > kernels(period);
createResamplingKernels(spline, mapCoordinate, kernels); createResamplingKernels(spline, mapCoordinate, kernels);
// temporay array to hold the current line to enable in-place operation // temporay array to hold the current line to enable in-place operation
ArrayVector<TmpType> tmp( ssize ); ArrayVector<TmpType> tmp( ssize );
ArrayVector<TmpType>::iterator t = tmp.begin(), tend = tmp.end(); typename ArrayVector<TmpType>::iterator t = tmp.begin(), tend = tmp.end ();
typename AccessorTraits<TmpType>::default_accessor ta; typename AccessorTraits<TmpType>::default_accessor ta;
for( ; snav.hasMore(); snav++, dnav++ ) for( ; snav.hasMore(); snav++, dnav++ )
{ {
// first copy source to temp for maximum cache efficiency // first copy source to temp for maximum cache efficiency
copyLine( snav.begin(), snav.end(), src, t, ta); copyLine( snav.begin(), snav.end(), src, t, ta);
for(unsigned int b = 0; b < prefilterCoeffs.size(); ++b) for(unsigned int b = 0; b < prefilterCoeffs.size(); ++b)
{ {
recursiveFilterLine(t, tend, ta, t, ta, recursiveFilterLine(t, tend, ta, t, ta,
 End of changes. 5 change blocks. 
4 lines changed or deleted 3 lines changed or added


 navigator.hxx   navigator.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2004 by Ullrich Koethe */ /* Copyright 2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 noise_normalization.hxx   noise_normalization.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2006 by Ullrich Koethe */ /* Copyright 1998-2006 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 581 skipping to change at line 579
void noiseVarianceListMedianCut(Vector1 const & noise, Vector2 & clusters, void noiseVarianceListMedianCut(Vector1 const & noise, Vector2 & clusters,
unsigned int maxClusterCount) unsigned int maxClusterCount)
{ {
typedef typename Vector2::value_type Result; typedef typename Vector2::value_type Result;
clusters.push_back(Result(0, noise.size())); clusters.push_back(Result(0, noise.size()));
while(clusters.size() <= maxClusterCount) while(clusters.size() <= maxClusterCount)
{ {
// find biggest cluster // find biggest cluster
unsigned int kMax; unsigned int kMax = 0;
double diffMax = 0.0; double diffMax = 0.0;
for(unsigned int k=0; k < clusters.size(); ++k) for(unsigned int k=0; k < clusters.size(); ++k)
{ {
double diff = noise[clusters[k][1]-1][0] - noise[clusters[k][0] ][0]; double diff = noise[clusters[k][1]-1][0] - noise[clusters[k][0] ][0];
if(diff > diffMax) if(diff > diffMax)
{ {
diffMax = diff; diffMax = diff;
kMax = k; kMax = k;
} }
} }
 End of changes. 4 change blocks. 
4 lines changed or deleted 2 lines changed or added


 nonlineardiffusion.hxx   nonlineardiffusion.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 106 skipping to change at line 104
NumericTraits<typename WeightAccessor::value_type>::RealPromote NumericTraits<typename WeightAccessor::value_type>::RealPromote
WeightType; WeightType;
// calculate width and height of the image // calculate width and height of the image
int w = slr.x - sul.x; int w = slr.x - sul.x;
int h = slr.y - sul.y; int h = slr.y - sul.y;
int d = (w < h) ? h : w; int d = (w < h) ? h : w;
std::vector<WeightType> lower(d), std::vector<WeightType> lower(d),
diag(d), diag(d),
upper(d); upper(d),
res(d);
std::vector<DestType> res(d);
int x,y; int x,y;
WeightType one = NumericTraits<WeightType>::one(); WeightType one = NumericTraits<WeightType>::one();
// create y iterators // create y iterators
SrcIterator ys = sul; SrcIterator ys = sul;
WeightIterator yw = wul; WeightIterator yw = wul;
DestIterator yd = dul; DestIterator yd = dul;
 End of changes. 4 change blocks. 
6 lines changed or deleted 3 lines changed or added


 numerictraits.hxx   numerictraits.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 41 skipping to change at line 39
/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_NUMERICTRAITS_HXX #ifndef VIGRA_NUMERICTRAITS_HXX
#define VIGRA_NUMERICTRAITS_HXX #define VIGRA_NUMERICTRAITS_HXX
#include <limits.h> #include <climits>
#include <limits>
#include <cfloat> #include <cfloat>
#include <complex> #include <complex>
#include "metaprogramming.hxx" #include "metaprogramming.hxx"
#include "sized_int.hxx" #include "sized_int.hxx"
/********************************************************/ /********************************************************/
/* */ /* */
/* NumericTraits */ /* NumericTraits */
/* */ /* */
/********************************************************/ /********************************************************/
skipping to change at line 936 skipping to change at line 935
static long long max() { return LLONG_MAX; } static long long max() { return LLONG_MAX; }
#ifdef NO_INLINE_STATIC_CONST_DEFINITION #ifdef NO_INLINE_STATIC_CONST_DEFINITION
enum { minConst = LLONG_MIN, maxConst = LLONG_MAX }; enum { minConst = LLONG_MIN, maxConst = LLONG_MAX };
#else #else
static const long long minConst = LLONG_MIN; static const long long minConst = LLONG_MIN;
static const long long maxConst = LLONG_MAX; static const long long maxConst = LLONG_MAX;
#endif #endif
static Promote toPromote(long long v) { return v; } static Promote toPromote(long long v) { return v; }
static RealPromote toRealPromote(long long v) { return v; } static RealPromote toRealPromote(long long v) { return (RealPromote)v; }
static long long fromPromote(Promote v) { return v; } static long long fromPromote(Promote v) { return v; }
static long long fromRealPromote(RealPromote v) { static long long fromRealPromote(RealPromote v) {
return ((v < 0.0) return ((v < 0.0)
? ((v < (RealPromote)LLONG_MIN) ? ((v < (RealPromote)LLONG_MIN)
? LLONG_MIN ? LLONG_MIN
: static_cast<long long>(v - 0.5)) : static_cast<long long>(v - 0.5))
: ((v > (RealPromote)LLONG_MAX) : ((v > (RealPromote)LLONG_MAX)
? LLONG_MAX ? LLONG_MAX
: static_cast<long long>(v + 0.5))); : static_cast<long long>(v + 0.5)));
} }
skipping to change at line 979 skipping to change at line 978
static unsigned long long max() { return ULLONG_MAX; } static unsigned long long max() { return ULLONG_MAX; }
#ifdef NO_INLINE_STATIC_CONST_DEFINITION #ifdef NO_INLINE_STATIC_CONST_DEFINITION
enum { minConst = 0, maxConst = ULLONG_MAX }; enum { minConst = 0, maxConst = ULLONG_MAX };
#else #else
static const unsigned long long minConst = 0; static const unsigned long long minConst = 0;
static const unsigned long long maxConst = ULLONG_MAX; static const unsigned long long maxConst = ULLONG_MAX;
#endif #endif
static Promote toPromote(unsigned long long v) { return v; } static Promote toPromote(unsigned long long v) { return v; }
static RealPromote toRealPromote(unsigned long long v) { return v; } static RealPromote toRealPromote(unsigned long long v) { return (RealPr omote)v; }
static unsigned long long fromPromote(Promote v) { return v; } static unsigned long long fromPromote(Promote v) { return v; }
static unsigned long long fromRealPromote(RealPromote v) { static unsigned long long fromRealPromote(RealPromote v) {
return ((v < 0.0) return ((v < 0.0)
? 0 ? 0
: ((v > (RealPromote)ULLONG_MAX) : ((v > (RealPromote)ULLONG_MAX)
? ULONG_MAX ? ULONG_MAX
: static_cast<unsigned long long>(v + 0.5))); : static_cast<unsigned long long>(v + 0.5)));
} }
}; };
#endif // LLONG_MAX #endif // LLONG_MAX
skipping to change at line 1317 skipping to change at line 1316
VIGRA_SPECIALIZED_CAST(signed char) VIGRA_SPECIALIZED_CAST(signed char)
VIGRA_SPECIALIZED_CAST(unsigned char) VIGRA_SPECIALIZED_CAST(unsigned char)
VIGRA_SPECIALIZED_CAST(short) VIGRA_SPECIALIZED_CAST(short)
VIGRA_SPECIALIZED_CAST(unsigned short) VIGRA_SPECIALIZED_CAST(unsigned short)
VIGRA_SPECIALIZED_CAST(int) VIGRA_SPECIALIZED_CAST(int)
VIGRA_SPECIALIZED_CAST(unsigned int) VIGRA_SPECIALIZED_CAST(unsigned int)
VIGRA_SPECIALIZED_CAST(long) VIGRA_SPECIALIZED_CAST(long)
VIGRA_SPECIALIZED_CAST(unsigned long) VIGRA_SPECIALIZED_CAST(unsigned long)
template <> template <>
struct RequiresExplicitCast<bool> {
template <class U>
static bool cast(U v)
{ return v == NumericTraits<U>::zero()
? false
: true; }
};
template <>
struct RequiresExplicitCast<float> { struct RequiresExplicitCast<float> {
static float cast(int v)
{ return (float)v; }
static float cast(unsigned int v)
{ return (float)v; }
static float cast(long v)
{ return (float)v; }
static float cast(unsigned long v)
{ return (float)v; }
static float cast(long long v)
{ return (float)v; }
static float cast(unsigned long long v)
{ return (float)v; }
static float cast(double v)
{ return (float)v; }
static float cast(long double v)
{ return (float)v; }
template <class U> template <class U>
static U cast(U v) static U cast(U v)
{ return v; } { return v; }
}; };
template <> template <>
struct RequiresExplicitCast<double> { struct RequiresExplicitCast<double> {
static double cast(Int64 v)
{ return (double)v; }
static double cast(UInt64 v)
{ return (double)v; }
template <class U> template <class U>
static U cast(U v) static U cast(U v)
{ return v; } { return v; }
}; };
#undef VIGRA_SPECIALIZED_CAST #undef VIGRA_SPECIALIZED_CAST
} // namespace detail } // namespace detail
} // namespace vigra } // namespace vigra
 End of changes. 9 change blocks. 
6 lines changed or deleted 44 lines changed or added


 orientedtensorfilters.hxx   orientedtensorfilters.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2002-2004 by Ullrich Koethe */ /* Copyright 2002-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 63 skipping to change at line 61
/* */ /* */
/* hourGlassFilter */ /* hourGlassFilter */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Anisotropic tensor smoothing with the hourglass filter. /** \brief Anisotropic tensor smoothing with the hourglass filter.
This function implements anisotropic tensor smoothing by an This function implements anisotropic tensor smoothing by an
hourglass-shaped filters as described in hourglass-shaped filters as described in
U. K&ouml;the: <a href="http://kogs-www.informatik.uni-hamburg.de/~koet he/papers/abstracts/structureTensor.html"> U. K&ouml;the: <a href="http://hci.iwr.uni-heidelberg.de/people/ukoethe /papers/index.php#cite_structureTensor">
<i>"Edge and Junction Detection with an Improved Structure Tensor"</i>< /a>, <i>"Edge and Junction Detection with an Improved Structure Tensor"</i>< /a>,
in: Proc. of 25th DAGM Symposium, Magdeburg 2003, Lecture Notes in Com puter Science 2781, in: Proc. of 25th DAGM Symposium, Magdeburg 2003, Lecture Notes in Com puter Science 2781,
pp. 25-32, Heidelberg: Springer, 2003 pp. 25-32, Heidelberg: Springer, 2003
It is closely related to the structure tensor (see \ref structureTensor ()), but It is closely related to the structure tensor (see \ref structureTensor ()), but
replaces the linear tensor smoothing with a smoothing along edges only. replaces the linear tensor smoothing with a smoothing along edges only.
Smoothing accross edges is largely suppressed. This means that the Smoothing accross edges is largely suppressed. This means that the
image structure is preserved much better because nearby features image structure is preserved much better because nearby features
such as parallel edges are not blended into each other. such as parallel edges are not blended into each other.
skipping to change at line 163 skipping to change at line 161
for(int y=0; y<h; ++y, ++sul.y, ++dul.y) for(int y=0; y<h; ++y, ++sul.y, ++dul.y)
{ {
SrcIterator s = sul; SrcIterator s = sul;
DestIterator d = dul; DestIterator d = dul;
for(int x=0; x<w; ++x, ++s.x, ++d.x) for(int x=0; x<w; ++x, ++s.x, ++d.x)
{ {
double phi = 0.5 * VIGRA_CSTD::atan2( double phi = 0.5 * VIGRA_CSTD::atan2(
2.0*src.getComponent(s,1), 2.0*src.getComponent(s,1),
(double)src.getComponent(s,0) - src.ge tComponent(s,2)); (double)src.getComponent(s,0) - src.ge tComponent(s,2));
double u = -VIGRA_CSTD::sin(phi); double u = VIGRA_CSTD::sin(phi);
double v = VIGRA_CSTD::cos(phi); double v = VIGRA_CSTD::cos(phi);
double x0 = x - radius < 0 ? -x : -radius; double x0 = x - radius < 0 ? -x : -radius;
double y0 = y - radius < 0 ? -y : -radius; double y0 = y - radius < 0 ? -y : -radius;
double x1 = x + radius >= w ? w - x - 1 : radius; double x1 = x + radius >= w ? w - x - 1 : radius;
double y1 = y + radius >= h ? h - y - 1 : radius; double y1 = y + radius >= h ? h - y - 1 : radius;
DestIterator dwul = d + Diff2D((int)x0, (int)y0); DestIterator dwul = d + Diff2D((int)x0, (int)y0);
for(double yy=y0; yy <= y1; ++yy, ++dwul.y) for(double yy=y0; yy <= y1; ++yy, ++dwul.y)
skipping to change at line 244 skipping to change at line 242
typedef typename typedef typename
NumericTraits<typename SrcAccessor::component_type>::RealPro mote TmpType; NumericTraits<typename SrcAccessor::component_type>::RealPro mote TmpType;
TmpType d1 = src.getComponent(s,0) + src.getComponent(s,2); TmpType d1 = src.getComponent(s,0) + src.getComponent(s,2);
TmpType d2 = src.getComponent(s,0) - src.getComponent(s,2); TmpType d2 = src.getComponent(s,0) - src.getComponent(s,2);
TmpType d3 = 2.0 * src.getComponent(s,1); TmpType d3 = 2.0 * src.getComponent(s,1);
TmpType d4 = VIGRA_CSTD::sqrt(sq(d2) + sq(d3)); TmpType d4 = VIGRA_CSTD::sqrt(sq(d2) + sq(d3));
TmpType excentricity = 1.0 - (d1 - d4) / (d1 + d4); TmpType excentricity = 1.0 - (d1 - d4) / (d1 + d4);
double sigmax2 = -0.5 / sq((sigmax - sigmin)*excentricity + sig min); double sigmax2 = -0.5 / sq((sigmax - sigmin)*excentricity + sig min);
double phi = 0.5 * VIGRA_CSTD::atan2(d3, d2); double phi = 0.5 * VIGRA_CSTD::atan2(d3, d2);
double u = -VIGRA_CSTD::sin(phi); double u = VIGRA_CSTD::sin(phi);
double v = VIGRA_CSTD::cos(phi); double v = VIGRA_CSTD::cos(phi);
double x0 = x - radius < 0 ? -x : -radius; double x0 = x - radius < 0 ? -x : -radius;
double y0 = y - radius < 0 ? -y : -radius; double y0 = y - radius < 0 ? -y : -radius;
double x1 = x + radius >= w ? w - x - 1 : radius; double x1 = x + radius >= w ? w - x - 1 : radius;
double y1 = y + radius >= h ? h - y - 1 : radius; double y1 = y + radius >= h ? h - y - 1 : radius;
DestIterator dwul = d + Diff2D((int)x0, (int)y0); DestIterator dwul = d + Diff2D((int)x0, (int)y0);
for(double yy=y0; yy <= y1; ++yy, ++dwul.y) for(double yy=y0; yy <= y1; ++yy, ++dwul.y)
skipping to change at line 291 skipping to change at line 289
/* kernels for orientedTrigonometricFilter */ /* kernels for orientedTrigonometricFilter */
/* */ /* */
/********************************************************/ /********************************************************/
class FoerstnerKernelBase class FoerstnerKernelBase
{ {
public: public:
typedef double ResultType; typedef double ResultType;
typedef double WeightType; typedef double WeightType;
typedef DVector2Image::value_type VectorType; typedef DVector2Image::value_type VectorType;
typedef VectorType::value_type ValueType;
FoerstnerKernelBase(double scale, bool ringShaped = false) FoerstnerKernelBase(double scale, bool ringShaped = false)
: radius_((int)(3.0*scale+0.5)), : radius_((int)(3.0*scale+0.5)),
weights_(2*radius_+1, 2*radius_+1), weights_(2*radius_+1, 2*radius_+1),
vectors_(2*radius_+1, 2*radius_+1) vectors_(2*radius_+1, 2*radius_+1)
{ {
double norm = 1.0 / (2.0 * M_PI * scale * scale); double norm = 1.0 / (2.0 * M_PI * scale * scale);
double s2 = -0.5 / scale / scale; double s2 = -0.5 / scale / scale;
for(int y = -radius_; y <= radius_; ++y) for(int y = -radius_; y <= radius_; ++y)
{ {
for(int x = -radius_; x <= radius_; ++x) for(int x = -radius_; x <= radius_; ++x)
{ {
double d2 = x*x + y*y; double d2 = x*x + y*y;
double d = VIGRA_CSTD::sqrt(d2); double d = VIGRA_CSTD::sqrt(d2);
vectors_(x+radius_,y+radius_) = d != 0.0 ? vectors_(x+radius_,y+radius_) = d != 0.0 ?
VectorType(x/d, -y/d) : VectorType(x/d, -y/d) :
VectorType(0, 0); VectorType(ValueType(0), ValueType(0));
weights_(x+radius_,y+radius_) = ringShaped ? weights_(x+radius_,y+radius_) = ringShaped ?
norm * d2 * VIGRA_CSTD::exp(d2 * s2) : norm * d2 * VIGRA_CSTD::exp(d2 * s2) :
norm * VIGRA_CSTD::exp(d2 * s2); norm * VIGRA_CSTD::exp(d2 * s2);
} }
} }
} }
ResultType operator()(int x, int y, VectorType const &) const ResultType operator()(int x, int y, VectorType const &) const
{ {
// isotropic filtering // isotropic filtering
 End of changes. 8 change blocks. 
7 lines changed or deleted 6 lines changed or added


 pixelneighborhood.hxx   pixelneighborhood.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2005 by Hans Meine, Ullrich Koethe */ /* Copyright 1998-2005 by Hans Meine, Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 199 skipping to change at line 197
AntiCausalFirst = South, ///< &nbsp; AntiCausalFirst = South, ///< &nbsp;
AntiCausalLast = East, ///< &nbsp; AntiCausalLast = East, ///< &nbsp;
InitialDirection = East, InitialDirection = East,
OppositeDirPrefix = 1, OppositeDirPrefix = 1,
OppositeOffset = West OppositeOffset = West
}; };
static unsigned int directionBit(Direction d) static unsigned int directionBit(Direction d)
{ {
static unsigned int b[] = {1 << (East + 1), static unsigned int b[] = {1 << East,
1 << (North + 1), 1 << North,
1 << (West + 1), 1 << West,
1 << (South + 1)}; 1 << South };
return b[d]; return b[d];
}; };
/** The number of valid neighbors if the current center is at the i mage border. /** The number of valid neighbors if the current center is at the i mage border.
*/ */
static unsigned int nearBorderDirectionCount(AtImageBorder b) static unsigned int nearBorderDirectionCount(AtImageBorder b)
{ {
static unsigned int c[] = { 4, 3, 3, 0, 3, 2, 2, 0, 3, 2, 2}; static unsigned int c[] = { 4, 3, 3, 0, 3, 2, 2, 0, 3, 2, 2};
return c[b]; return c[b];
} }
skipping to change at line 341 skipping to change at line 339
static Diff2D const & east() { return diff(East); } /**< Offs et to the east neighbor */ static Diff2D const & east() { return diff(East); } /**< Offs et to the east neighbor */
static Diff2D const & north() { return diff(North); } /**< Offs et to the north neighbor */ static Diff2D const & north() { return diff(North); } /**< Offs et to the north neighbor */
static Diff2D const & west() { return diff(West); } /**< Offs et to the west neighbor */ static Diff2D const & west() { return diff(West); } /**< Offs et to the west neighbor */
static Diff2D const & south() { return diff(South); } /**< Offs et to the south neighbor */ static Diff2D const & south() { return diff(South); } /**< Offs et to the south neighbor */
}; };
/** Export NeighborCode::Direction into the scope of namespace FourNeig hborhood. /** Export NeighborCode::Direction into the scope of namespace FourNeig hborhood.
*/ */
typedef NeighborCode::Direction Direction; typedef NeighborCode::Direction Direction;
static const Direction Error = NeighborCode::Error; /**< Export NeighborCode::Error to namespace FourNeighborhood */
static const Direction East = NeighborCode::East; /**< Export NeighborCode::East to namespace FourNeighborhood */ static const Direction East = NeighborCode::East; /**< Export NeighborCode::East to namespace FourNeighborhood */
static const Direction North = NeighborCode::North; /**< Export NeighborCode::North to namespace FourNeighborhood */ static const Direction North = NeighborCode::North; /**< Export NeighborCode::North to namespace FourNeighborhood */
static const Direction West = NeighborCode::West; /**< Export NeighborCode::West to namespace FourNeighborhood */ static const Direction West = NeighborCode::West; /**< Export NeighborCode::West to namespace FourNeighborhood */
static const Direction South = NeighborCode::South; /**< Export NeighborCode::South to namespace FourNeighborhood */ static const Direction South = NeighborCode::South; /**< Export NeighborCode::South to namespace FourNeighborhood */
static const Direction DirectionCount = NeighborCode::DirectionCount; /**< Export NeighborCode::DirectionCount to namespace FourNeighborhood */ static const Direction DirectionCount = NeighborCode::DirectionCount; /**< Export NeighborCode::DirectionCount to namespace FourNeighborhood */
inline Diff2D const & east() { return NeighborCode::diff(East); } /**< Offset to the east neighbor */ inline Diff2D const & east() { return NeighborCode::diff(East); } /**< Offset to the east neighbor */
inline Diff2D const & north() { return NeighborCode::diff(North); } /**< Offset to the north neighbor */ inline Diff2D const & north() { return NeighborCode::diff(North); } /**< Offset to the north neighbor */
inline Diff2D const & west() { return NeighborCode::diff(West); } /**< Offset to the west neighbor */ inline Diff2D const & west() { return NeighborCode::diff(West); } /**< Offset to the west neighbor */
inline Diff2D const & south() { return NeighborCode::diff(South); } /**< Offset to the south neighbor */ inline Diff2D const & south() { return NeighborCode::diff(South); } /**< Offset to the south neighbor */
skipping to change at line 434 skipping to change at line 433
AntiCausalFirst = SouthWest, ///< &nbsp; AntiCausalFirst = SouthWest, ///< &nbsp;
AntiCausalLast = East, ///< &nbsp; AntiCausalLast = East, ///< &nbsp;
InitialDirection = East, InitialDirection = East,
OppositeDirPrefix = 1, OppositeDirPrefix = 1,
OppositeOffset = West OppositeOffset = West
}; };
static unsigned int directionBit(Direction d) static unsigned int directionBit(Direction d)
{ {
static unsigned int b[] = {1 << (East + 1), static unsigned int b[] = {1 << East,
1 << (NorthEast + 1), 1 << NorthEast,
1 << (North + 1), 1 << North,
1 << (NorthWest + 1), 1 << NorthWest,
1 << (West + 1), 1 << West,
1 << (SouthWest + 1), 1 << SouthWest,
1 << (South + 1), 1 << South,
1 << (SouthEast + 1)}; 1 << SouthEast};
return b[d]; return b[d];
}; };
/** The number of valid neighbors if the current center is at the i mage border. /** The number of valid neighbors if the current center is at the i mage border.
*/ */
static unsigned int nearBorderDirectionCount(AtImageBorder b) static unsigned int nearBorderDirectionCount(AtImageBorder b)
{ {
static unsigned int c[] = { 8, 5, 5, 0, 5, 3, 3, 0, 5, 3, 3}; static unsigned int c[] = { 8, 5, 5, 0, 5, 3, 3, 0, 5, 3, 3};
return c[b]; return c[b];
} }
 End of changes. 6 change blocks. 
15 lines changed or deleted 14 lines changed or added


 polynomial.hxx   polynomial.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2004 by Ullrich Koethe */ /* Copyright 1998-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 promote_traits.hxx   promote_traits.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2008 by Ullrich Koethe */ /* Copyright 1998-2008 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 random.hxx   random.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2008 by Ullrich Koethe */ /* Copyright 2008 by Ullrich Koethe */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 142 skipping to change at line 141
for(UInt32 i=0; i<N; ++i) for(UInt32 i=0; i<N; ++i)
state_[i] = seeds[i]; state_[i] = seeds[i];
} }
protected: protected:
UInt32 get() const UInt32 get() const
{ {
if(current_ == N) if(current_ == N)
generateNumbers(); generateNumbers<void>();
UInt32 y = state_[current_++]; UInt32 y = state_[current_++];
y ^= (y << 7) & 0x2b5b2500; y ^= (y << 7) & 0x2b5b2500;
y ^= (y << 15) & 0xdb8b0000; y ^= (y << 15) & 0xdb8b0000;
return y ^ (y >> 16); return y ^ (y >> 16);
} }
template <class DUMMY>
void generateNumbers() const; void generateNumbers() const;
void seedImpl(RandomSeedTag) void seedImpl(RandomSeedTag)
{ {
seed(RandomSeed, *this); seed(RandomSeed, *this);
} }
void seedImpl(UInt32 theSeed) void seedImpl(UInt32 theSeed)
{ {
seed(theSeed, *this); seed(theSeed, *this);
} }
template<class Iterator> template<class Iterator>
void seedImpl(Iterator init, UInt32 length) void seedImpl(Iterator init, UInt32 length)
{ {
seed(init, length, *this); seed(init, length, *this);
} }
}; };
template <class DUMMY>
void RandomState<TT800>::generateNumbers() const void RandomState<TT800>::generateNumbers() const
{ {
UInt32 mag01[2]= { 0x0, 0x8ebfd028 }; UInt32 mag01[2]= { 0x0, 0x8ebfd028 };
for(UInt32 i=0; i<N-M; ++i) for(UInt32 i=0; i<N-M; ++i)
{ {
state_[i] = state_[i+M] ^ (state_[i] >> 1) ^ mag01[state_[i] % 2]; state_[i] = state_[i+M] ^ (state_[i] >> 1) ^ mag01[state_[i] % 2];
} }
for (UInt32 i=N-M; i<N; ++i) for (UInt32 i=N-M; i<N; ++i)
{ {
skipping to change at line 204 skipping to change at line 205
: current_(0) : current_(0)
{ {
seed(19650218U, *this); seed(19650218U, *this);
} }
protected: protected:
UInt32 get() const UInt32 get() const
{ {
if(current_ == N) if(current_ == N)
generateNumbers(); generateNumbers<void>();
UInt32 x = state_[current_++]; UInt32 x = state_[current_++];
x ^= (x >> 11); x ^= (x >> 11);
x ^= (x << 7) & 0x9D2C5680U; x ^= (x << 7) & 0x9D2C5680U;
x ^= (x << 15) & 0xEFC60000U; x ^= (x << 15) & 0xEFC60000U;
return x ^ (x >> 18); return x ^ (x >> 18);
} }
template <class DUMMY>
void generateNumbers() const; void generateNumbers() const;
static UInt32 twiddle(UInt32 u, UInt32 v) static UInt32 twiddle(UInt32 u, UInt32 v)
{ {
return (((u & 0x80000000U) | (v & 0x7FFFFFFFU)) >> 1) return (((u & 0x80000000U) | (v & 0x7FFFFFFFU)) >> 1)
^ ((v & 1U) ? 0x9908B0DFU : 0x0U); ^ ((v & 1U) ? 0x9908B0DFU : 0x0U);
} }
void seedImpl(RandomSeedTag) void seedImpl(RandomSeedTag)
{ {
seed(RandomSeed, *this); seed(RandomSeed, *this);
generateNumbers(); generateNumbers<void>();
} }
void seedImpl(UInt32 theSeed) void seedImpl(UInt32 theSeed)
{ {
seed(theSeed, *this); seed(theSeed, *this);
generateNumbers(); generateNumbers<void>();
} }
template<class Iterator> template<class Iterator>
void seedImpl(Iterator init, UInt32 length) void seedImpl(Iterator init, UInt32 length)
{ {
seed(19650218U, *this); seed(19650218U, *this);
seed(init, length, *this); seed(init, length, *this);
generateNumbers(); generateNumbers<void>();
} }
}; };
template <class DUMMY>
void RandomState<MT19937>::generateNumbers() const void RandomState<MT19937>::generateNumbers() const
{ {
for (int i = 0; i < (N - M); ++i) for (unsigned int i = 0; i < (N - M); ++i)
{ {
state_[i] = state_[i + M] ^ twiddle(state_[i], state_[i + 1]); state_[i] = state_[i + M] ^ twiddle(state_[i], state_[i + 1]);
} }
for (int i = N - M; i < (N - 1); ++i) for (unsigned int i = N - M; i < (N - 1); ++i)
{ {
state_[i] = state_[i + M - N] ^ twiddle(state_[i], state_[i + 1]); state_[i] = state_[i + M - N] ^ twiddle(state_[i], state_[i + 1]);
} }
state_[N - 1] = state_[M - 1] ^ twiddle(state_[N - 1], state_[0]); state_[N - 1] = state_[M - 1] ^ twiddle(state_[N - 1], state_[0]);
current_ = 0; current_ = 0;
} }
} // namespace detail } // namespace detail
/** \addtogroup RandomNumberGeneration Random Number Generation /** \addtogroup RandomNumberGeneration Random Number Generation
skipping to change at line 583 skipping to change at line 586
<b>Traits defined:</b> <b>Traits defined:</b>
<tt>FunctorTraits<UniformIntRandomFunctor<Engine> >::isInitializer</tt> and <tt>FunctorTraits<UniformIntRandomFunctor<Engine> >::isInitializer</tt> and
<tt>FunctorTraits<UniformIntRandomFunctor<Engine> >::isUnaryFunctor</tt > are true (<tt>VigraTrueType</tt>). <tt>FunctorTraits<UniformIntRandomFunctor<Engine> >::isUnaryFunctor</tt > are true (<tt>VigraTrueType</tt>).
*/ */
template <class Engine = RandomTT800> template <class Engine = RandomTT800>
class UniformIntRandomFunctor class UniformIntRandomFunctor
{ {
UInt32 lower_, difference_, factor_; UInt32 lower_, difference_, factor_;
Engine & generator_; Engine const & generator_;
bool useLowBits_; bool useLowBits_;
public: public:
typedef UInt32 argument_type; ///< STL required functor argument type typedef UInt32 argument_type; ///< STL required functor argument type
typedef UInt32 result_type; ///< STL required functor result type typedef UInt32 result_type; ///< STL required functor result type
/** Create functor for uniform random integers in the range [0, 2<s up>32</sup>) /** Create functor for uniform random integers in the range [0, 2<s up>32</sup>)
using the given engine. using the given engine.
That is, the generated numbers satisfy 0 &lt;= i &lt; 2<sup>32< /sup>. That is, the generated numbers satisfy 0 &lt;= i &lt; 2<sup>32< /sup>.
*/ */
explicit UniformIntRandomFunctor(Engine & generator = Engine::global() ) explicit UniformIntRandomFunctor(Engine const & generator = Engine::glo bal() )
: lower_(0), difference_(0xffffffff), factor_(1), : lower_(0), difference_(0xffffffff), factor_(1),
generator_(generator), generator_(generator),
useLowBits_(true) useLowBits_(true)
{} {}
/** Create functor for uniform random integers in the range [<tt>lo wer</tt>, <tt>upper</tt>] /** Create functor for uniform random integers in the range [<tt>lo wer</tt>, <tt>upper</tt>]
using the given engine. using the given engine.
That is, the generated numbers satisfy <tt>lower</tt> &lt;= i & lt;= <tt>upper</tt>. That is, the generated numbers satisfy <tt>lower</tt> &lt;= i & lt;= <tt>upper</tt>.
\a useLowBits should be set to <tt>false</tt> when the engine g enerates \a useLowBits should be set to <tt>false</tt> when the engine g enerates
random numbers whose low bits are significantly less random tha n the high random numbers whose low bits are significantly less random tha n the high
bits. This does not apply to <tt>RandomTT800</tt> and <tt>Rando mMT19937</tt>, bits. This does not apply to <tt>RandomTT800</tt> and <tt>Rando mMT19937</tt>,
but is necessary for simpler linear congruential generators. but is necessary for simpler linear congruential generators.
*/ */
UniformIntRandomFunctor(UInt32 lower, UInt32 upper, UniformIntRandomFunctor(UInt32 lower, UInt32 upper,
Engine & generator = Engine::global(), Engine const & generator = Engine::global(),
bool useLowBits = true) bool useLowBits = true)
: lower_(lower), difference_(upper-lower), : lower_(lower), difference_(upper-lower),
factor_(Engine::factorForUniformInt(difference_ + 1)), factor_(Engine::factorForUniformInt(difference_ + 1)),
generator_(generator), generator_(generator),
useLowBits_(useLowBits) useLowBits_(useLowBits)
{ {
vigra_precondition(lower < upper, vigra_precondition(lower < upper,
"UniformIntRandomFunctor(): lower bound must be smaller than uppe r bound."); "UniformIntRandomFunctor(): lower bound must be smaller than uppe r bound.");
} }
skipping to change at line 689 skipping to change at line 692
in an STL-compatible interface. in an STL-compatible interface.
<b>Traits defined:</b> <b>Traits defined:</b>
<tt>FunctorTraits<UniformIntRandomFunctor<Engine> >::isInitializer</tt> is true (<tt>VigraTrueType</tt>). <tt>FunctorTraits<UniformIntRandomFunctor<Engine> >::isInitializer</tt> is true (<tt>VigraTrueType</tt>).
*/ */
template <class Engine = RandomTT800> template <class Engine = RandomTT800>
class UniformRandomFunctor class UniformRandomFunctor
{ {
double offset_, scale_; double offset_, scale_;
Engine & generator_; Engine const & generator_;
public: public:
typedef double result_type; ///< STL required functor result type typedef double result_type; ///< STL required functor result type
/** Create functor for uniform random double-precision numbers in t he range [0.0, 1.0] /** Create functor for uniform random double-precision numbers in t he range [0.0, 1.0]
using the given engine. using the given engine.
That is, the generated numbers satisfy 0.0 &lt;= i &lt;= 1.0. That is, the generated numbers satisfy 0.0 &lt;= i &lt;= 1.0.
*/ */
UniformRandomFunctor(Engine & generator = Engine::global()) UniformRandomFunctor(Engine const & generator = Engine::global())
: offset_(0.0), : offset_(0.0),
scale_(1.0), scale_(1.0),
generator_(generator) generator_(generator)
{} {}
/** Create functor for uniform random double-precision numbers in t he range [<tt>lower</tt>, <tt>upper</tt>] /** Create functor for uniform random double-precision numbers in t he range [<tt>lower</tt>, <tt>upper</tt>]
using the given engine. using the given engine.
That is, the generated numbers satisfy <tt>lower</tt> &lt;= i & lt;= <tt>upper</tt>. That is, the generated numbers satisfy <tt>lower</tt> &lt;= i & lt;= <tt>upper</tt>.
*/ */
skipping to change at line 757 skipping to change at line 760
This functor encapsulates the function <tt>normal()</tt> of the given r andom number This functor encapsulates the function <tt>normal()</tt> of the given r andom number
<tt>Engine</tt> (usually <tt>RandomTT800</tt> or <tt>RandomMT19937</tt> ) <tt>Engine</tt> (usually <tt>RandomTT800</tt> or <tt>RandomMT19937</tt> )
in an STL-compatible interface. in an STL-compatible interface.
<b>Traits defined:</b> <b>Traits defined:</b>
<tt>FunctorTraits<UniformIntRandomFunctor<Engine> >::isInitializer</tt> is true (<tt>VigraTrueType</tt>). <tt>FunctorTraits<UniformIntRandomFunctor<Engine> >::isInitializer</tt> is true (<tt>VigraTrueType</tt>).
*/ */
template <class Engine = RandomTT800> template <class Engine = RandomTT800>
struct NormalRandomFunctor class NormalRandomFunctor
{ {
double mean_, stddev_; double mean_, stddev_;
Engine & generator_; Engine const & generator_;
public: public:
typedef double result_type; ///< STL required functor result type typedef double result_type; ///< STL required functor result type
/** Create functor for standard normal random numbers /** Create functor for standard normal random numbers
using the given engine. using the given engine.
That is, mean is 0.0 and standard deviation is 1.0. That is, mean is 0.0 and standard deviation is 1.0.
*/ */
NormalRandomFunctor(Engine & generator = Engine::global()) NormalRandomFunctor(Engine const & generator = Engine::global())
: mean_(0.0), : mean_(0.0),
stddev_(1.0), stddev_(1.0),
generator_(generator) generator_(generator)
{} {}
/** Create functor for normal random numbers with goven mean and st andard deviation /** Create functor for normal random numbers with goven mean and st andard deviation
using the given engine. using the given engine.
*/ */
NormalRandomFunctor(double mean, double stddev, NormalRandomFunctor(double mean, double stddev,
Engine & generator = Engine::global()) Engine & generator = Engine::global())
 End of changes. 21 change blocks. 
17 lines changed or deleted 20 lines changed or added


 rational.hxx   rational.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2004 by Ullrich Koethe */ /* Copyright 1998-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* It was adapted from the file boost/rational.hpp of the */ /* It was adapted from the file boost/rational.hpp of the */
/* boost library. */ /* boost library. */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 1014 skipping to change at line 1012
bool bool
operator< (const Rational<IntType1> & l, const Rational<IntType2>& r) operator< (const Rational<IntType1> & l, const Rational<IntType2>& r)
{ {
// Avoid repeated construction // Avoid repeated construction
typedef typename PromoteTraits<IntType1, IntType2>::Promote IntType; typedef typename PromoteTraits<IntType1, IntType2>::Promote IntType;
IntType zero(0); IntType zero(0);
// Handle the easy cases. Take advantage of the fact // Handle the easy cases. Take advantage of the fact
// that the denominator is never negative. // that the denominator is never negative.
if(l.denominator() == zero) if(l.denominator() == zero)
{
if(r.denominator() == zero) if(r.denominator() == zero)
// -inf < inf, !(-inf < -inf), !(inf < -inf), !(inf < inf) // -inf < inf, !(-inf < -inf), !(inf < -inf), !(inf < inf)
return l.numerator() < r.numerator(); return l.numerator() < r.numerator();
else else
// -inf < -1, -inf < 0, -inf < 1 // -inf < -1, -inf < 0, -inf < 1
// !(inf < -1), !(inf < 0), !(inf < 1) // !(inf < -1), !(inf < 0), !(inf < 1)
return l.numerator() < zero; return l.numerator() < zero;
}
if(r.denominator() == zero) if(r.denominator() == zero)
// -1 < inf, 0 < inf, 1 < inf // -1 < inf, 0 < inf, 1 < inf
// !(-1 < -inf), !(0 < -inf), !(1 < -inf) // !(-1 < -inf), !(0 < -inf), !(1 < -inf)
return r.numerator() > zero; return r.numerator() > zero;
// !(1 < -1), !(1 < 0), !(0 < -1), !(0 < 0) // !(1 < -1), !(1 < 0), !(0 < -1), !(0 < 0)
if(l.numerator() >= zero && r.numerator() <= zero) if(l.numerator() >= zero && r.numerator() <= zero)
return false; return false;
// -1 < 0, -1 < 1, 0 < 1 (note: !(0 < 0) was already handled!) // -1 < 0, -1 < 1, 0 < 1 (note: !(0 < 0) was already handled!)
if(l.numerator() <= zero && r.numerator() >= zero) if(l.numerator() <= zero && r.numerator() >= zero)
return true; return true;
 End of changes. 5 change blocks. 
3 lines changed or deleted 3 lines changed or added


 recursiveconvolution.hxx   recursiveconvolution.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 190 skipping to change at line 188
} }
return; return;
} }
double eps = 0.00001; double eps = 0.00001;
int kernelw = std::min(w-1, (int)(VIGRA_CSTD::log(eps)/VIGRA_CSTD::log( VIGRA_CSTD::fabs(b)))); int kernelw = std::min(w-1, (int)(VIGRA_CSTD::log(eps)/VIGRA_CSTD::log( VIGRA_CSTD::fabs(b))));
typedef typename typedef typename
NumericTraits<typename SrcAccessor::value_type>::RealPromote TempTy pe; NumericTraits<typename SrcAccessor::value_type>::RealPromote TempTy pe;
typedef NumericTraits<typename DestAccessor::value_type> DestTraits; typedef NumericTraits<typename DestAccessor::value_type> DestTraits;
typedef typename DestTraits::RealPromote RealPromote;
// store result of causal filtering // store result of causal filtering
std::vector<TempType> vline(w); std::vector<TempType> vline(w);
typename std::vector<TempType>::iterator line = vline.begin(); typename std::vector<TempType>::iterator line = vline.begin();
double norm = (1.0 - b) / (1.0 + b); double norm = (1.0 - b) / (1.0 + b);
TempType old; TempType old;
if(border == BORDER_TREATMENT_REPEAT || if(border == BORDER_TREATMENT_REPEAT ||
border == BORDER_TREATMENT_AVOID) border == BORDER_TREATMENT_AVOID)
{ {
old = (1.0 / (1.0 - b)) * as(is); old = TempType((1.0 / (1.0 - b)) * as(is));
} }
else if(border == BORDER_TREATMENT_REFLECT) else if(border == BORDER_TREATMENT_REFLECT)
{ {
is += kernelw; is += kernelw;
old = (1.0 / (1.0 - b)) * as(is); old = TempType((1.0 / (1.0 - b)) * as(is));
for(x = 0; x < kernelw; ++x, --is) for(x = 0; x < kernelw; ++x, --is)
old = as(is) + b * old; old = TempType(as(is) + b * old);
} }
else if(border == BORDER_TREATMENT_WRAP) else if(border == BORDER_TREATMENT_WRAP)
{ {
is = isend - kernelw; is = isend - kernelw;
old = (1.0 / (1.0 - b)) * as(is); old = TempType((1.0 / (1.0 - b)) * as(is));
for(x = 0; x < kernelw; ++x, ++is) for(x = 0; x < kernelw; ++x, ++is)
old = as(is) + b * old; old = TempType(as(is) + b * old);
} }
else if(border == BORDER_TREATMENT_CLIP) else if(border == BORDER_TREATMENT_CLIP)
{ {
old = NumericTraits<TempType>::zero(); old = NumericTraits<TempType>::zero();
} }
else else
vigra_fail("recursiveFilterLine(): Unknown border treatment mode.\n "); vigra_fail("recursiveFilterLine(): Unknown border treatment mode.\n ");
// left side of filter // left side of filter
for(x=0, is = istart; x < w; ++x, ++is) for(x=0, is = istart; x < w; ++x, ++is)
{ {
old = as(is) + b * old; old = TempType(as(is) + b * old);
line[x] = old; line[x] = old;
} }
// right side of the filter // right side of the filter
if(border == BORDER_TREATMENT_REPEAT || if(border == BORDER_TREATMENT_REPEAT ||
border == BORDER_TREATMENT_AVOID) border == BORDER_TREATMENT_AVOID)
{ {
is = isend - 1; is = isend - 1;
old = (1.0 / (1.0 - b)) * as(is); old = TempType((1.0 / (1.0 - b)) * as(is));
} }
else if(border == BORDER_TREATMENT_REFLECT) else if(border == BORDER_TREATMENT_REFLECT)
{ {
old = line[w-2]; old = line[w-2];
} }
else if(border == BORDER_TREATMENT_WRAP) else if(border == BORDER_TREATMENT_WRAP)
{ {
is = istart + kernelw - 1; is = istart + kernelw - 1;
old = (1.0 / (1.0 - b)) * as(is); old = TempType((1.0 / (1.0 - b)) * as(is));
for(x = 0; x < kernelw; ++x, --is) for(x = 0; x < kernelw; ++x, --is)
old = as(is) + b * old; old = TempType(as(is) + b * old);
} }
else if(border == BORDER_TREATMENT_CLIP) else if(border == BORDER_TREATMENT_CLIP)
{ {
old = NumericTraits<TempType>::zero(); old = NumericTraits<TempType>::zero();
} }
is = isend - 1; is = isend - 1;
id += w - 1; id += w - 1;
if(border == BORDER_TREATMENT_CLIP) if(border == BORDER_TREATMENT_CLIP)
{ {
// correction factors for b // correction factors for b
double bright = b; double bright = b;
double bleft = VIGRA_CSTD::pow(b, w); double bleft = VIGRA_CSTD::pow(b, w);
for(x=w-1; x>=0; --x, --is, --id) for(x=w-1; x>=0; --x, --is, --id)
{ {
TempType f = b * old; TempType f = TempType(b * old);
old = as(is) + f; old = as(is) + f;
double norm = (1.0 - b) / (1.0 + b - bleft - bright); double norm = (1.0 - b) / (1.0 + b - bleft - bright);
bleft /= b; bleft /= b;
bright *= b; bright *= b;
ad.set(norm * (line[x] + f), id); ad.set(norm * (line[x] + f), id);
} }
} }
else if(border == BORDER_TREATMENT_AVOID) else if(border == BORDER_TREATMENT_AVOID)
{ {
for(x=w-1; x >= kernelw; --x, --is, --id) for(x=w-1; x >= kernelw; --x, --is, --id)
{ {
TempType f = b * old; TempType f = TempType(b * old);
old = as(is) + f; old = as(is) + f;
if(x < w - kernelw) if(x < w - kernelw)
ad.set(DestTraits::fromRealPromote(norm * (line[x] + f)), i d); ad.set(DestTraits::fromRealPromote(RealPromote(norm * (line [x] + f))), id);
} }
} }
else else
{ {
for(x=w-1; x>=0; --x, --is, --id) for(x=w-1; x>=0; --x, --is, --id)
{ {
TempType f = b * old; TempType f = TempType(b * old);
old = as(is) + f; old = as(is) + f;
ad.set(DestTraits::fromRealPromote(norm * (line[x] + f)), id); ad.set(DestTraits::fromRealPromote(RealPromote(norm * (line[x] + f))), id);
} }
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* recursiveFilterLine (2nd order) */ /* recursiveFilterLine (2nd order) */
/* */ /* */
/********************************************************/ /********************************************************/
skipping to change at line 329 skipping to change at line 328
double norm1 = (1.0 - b1 - b2) / (1.0 + b1 + b2); double norm1 = (1.0 - b1 - b2) / (1.0 + b1 + b2);
double norm2 = norm * norm; double norm2 = norm * norm;
// init left side of filter // init left side of filter
int kernelw = std::min(w-1, std::max(8, (int)(1.0 / norm + 0.5))); int kernelw = std::min(w-1, std::max(8, (int)(1.0 / norm + 0.5)));
is += (kernelw - 2); is += (kernelw - 2);
line[kernelw] = as(is); line[kernelw] = as(is);
line[kernelw-1] = as(is); line[kernelw-1] = as(is);
for(x = kernelw - 2; x > 0; --x, --is) for(x = kernelw - 2; x > 0; --x, --is)
{ {
line[x] = as(is) + b1 * line[x+1] + b2 * line[x+2]; line[x] = detail::RequiresExplicitCast<TempType>::cast(as(is) + b1 * line[x+1] + b2 * line[x+2]);
} }
line[0] = as(is) + b1 * line[1] + b2 * line[2]; line[0] = detail::RequiresExplicitCast<TempType>::cast(as(is) + b1 * li ne[1] + b2 * line[2]);
++is; ++is;
line[1] = as(is) + b1 * line[0] + b2 * line[1]; line[1] = detail::RequiresExplicitCast<TempType>::cast(as(is) + b1 * li ne[0] + b2 * line[1]);
++is; ++is;
for(x=2; x < w; ++x, ++is) for(x=2; x < w; ++x, ++is)
{ {
line[x] = as(is) + b1 * line[x-1] + b2 * line[x-2]; line[x] = detail::RequiresExplicitCast<TempType>::cast(as(is) + b1 * line[x-1] + b2 * line[x-2]);
} }
line[w] = line[w-1]; line[w] = line[w-1];
line[w-1] = norm1 * (line[w-1] + b1 * line[w-2] + b2 * line[w-3]); line[w-1] = detail::RequiresExplicitCast<TempType>::cast(norm1 * (line[
line[w-2] = norm1 * (line[w-2] + b1 * line[w] + b2 * line[w-2]); w-1] + b1 * line[w-2] + b2 * line[w-3]));
line[w-2] = detail::RequiresExplicitCast<TempType>::cast(norm1 * (line[
w-2] + b1 * line[w] + b2 * line[w-2]));
id += w-1; id += w-1;
ad.set(line[w-1], id); ad.set(line[w-1], id);
--id; --id;
ad.set(line[w-2], id); ad.set(line[w-2], id);
--id; --id;
for(x=w-3; x>=0; --x, --id, --is) for(x=w-3; x>=0; --x, --id, --is)
{ {
line[x] = norm2 * line[x] + b1 * line[x+1] + b2 * line[x+2]; line[x] = detail::RequiresExplicitCast<TempType>::cast(norm2 * line [x] + b1 * line[x+1] + b2 * line[x+2]);
ad.set(line[x], id); ad.set(line[x], id);
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* recursiveSmoothLine */ /* recursiveSmoothLine */
/* */ /* */
/********************************************************/ /********************************************************/
skipping to change at line 651 skipping to change at line 650
NumericTraits<typename SrcAccessor::value_type>::RealPromote NumericTraits<typename SrcAccessor::value_type>::RealPromote
TempType; TempType;
typedef NumericTraits<typename DestAccessor::value_type> DestTraits; typedef NumericTraits<typename DestAccessor::value_type> DestTraits;
std::vector<TempType> vline(w); std::vector<TempType> vline(w);
typename std::vector<TempType>::iterator line = vline.begin(); typename std::vector<TempType>::iterator line = vline.begin();
double b = VIGRA_CSTD::exp(-1.0/scale); double b = VIGRA_CSTD::exp(-1.0/scale);
double a = -2.0 / (1.0 - b); double a = -2.0 / (1.0 - b);
double norm = (1.0 - b) * (1.0 - b) * (1.0 - b) / (1.0 + b); double norm = (1.0 - b) * (1.0 - b) * (1.0 - b) / (1.0 + b);
TempType old = (1.0 / (1.0 - b)) * as(is); TempType old = detail::RequiresExplicitCast<TempType>::cast((1.0 / (1.0 - b)) * as(is));
// left side of filter // left side of filter
for(x=0; x<w; ++x, ++is) for(x=0; x<w; ++x, ++is)
{ {
line[x] = old; line[x] = old;
old = as(is) + b * old; old = detail::RequiresExplicitCast<TempType>::cast(as(is) + b * old );
} }
// right side of the filter // right side of the filter
--is; --is;
old = (1.0 / (1.0 - b)) * as(is); old = detail::RequiresExplicitCast<TempType>::cast((1.0 / (1.0 - b)) * as(is));
id += w; id += w;
++is; ++is;
for(x=w-1; x>=0; --x) for(x=w-1; x>=0; --x)
{ {
--is; --is;
--id; --id;
TempType f = old + a * as(is); TempType f = detail::RequiresExplicitCast<TempType>::cast(old + a *
old = as(is) + b * old; as(is));
ad.set(DestTraits::fromRealPromote(norm * (line[x] + f)), id); old = detail::RequiresExplicitCast<TempType>::cast(as(is) + b * old
);
ad.set(DestTraits::fromRealPromote(detail::RequiresExplicitCast<Tem
pType>::cast(norm * (line[x] + f))), id);
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* recursiveFilterX */ /* recursiveFilterX */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Performs 1 dimensional recursive filtering (1st and 2nd order) i n x direction. /** \brief Performs 1 dimensional recursive filtering (1st and 2nd order) i n x direction.
 End of changes. 28 change blocks. 
30 lines changed or deleted 34 lines changed or added


 regression.hxx   regression.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2008 by Ullrich Koethe */ /* Copyright 2008 by Ullrich Koethe */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 52 skipping to change at line 51
#include "singular_value_decomposition.hxx" #include "singular_value_decomposition.hxx"
#include "numerictraits.hxx" #include "numerictraits.hxx"
#include "functorexpression.hxx" #include "functorexpression.hxx"
namespace vigra namespace vigra
{ {
namespace linalg namespace linalg
{ {
/** \addtogroup MatrixAlgebra /** \addtogroup Optimization Optimization and Regression
*/ */
//@{ //@{
/** Ordinary Least Squares Regression. /** Ordinary Least Squares Regression.
Given a matrix \a A with <tt>m</tt> rows and <tt>n</tt> columns (wit h <tt>m \>= n</tt>), Given a matrix \a A with <tt>m</tt> rows and <tt>n</tt> columns (wit h <tt>m \>= n</tt>),
and a column vector \a b of length <tt>m</tt> rows, this function co mputes and a column vector \a b of length <tt>m</tt> rows, this function co mputes
a column vector \a x of length <tt>n</tt> rows such that the residua l the column vector \a x of length <tt>n</tt> rows that solves the opt imization problem
\f[ \left|\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\right|^2 \f[ \tilde \textrm{\bf x} = \textrm{argmin}
\left|\left|\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\righ
t|\right|_2^2
\f] \f]
is minimized. When \a b is a matrix with <tt>k</tt> columns, \a x mu st also have When \a b is a matrix with <tt>k</tt> columns, \a x must also have
<tt>k</tt> columns, which will contain the solutions for the corresp onding columns of <tt>k</tt> columns, which will contain the solutions for the corresp onding columns of
\a b. Note that all matrices must already have the correct shape. \a b. Note that all matrices must already have the correct shape.
This function is just another name for \ref linearSolve(), perhaps This function is just another name for \ref linearSolve(), perhaps
leading to more readable code when \a A is a rectangular matrix. It returns leading to more readable code when \a A is a rectangular matrix. It returns
<tt>false</tt> when the rank of \a A is less than <tt>n</tt>. <tt>false</tt> when the rank of \a A is less than <tt>n</tt>.
See \ref linearSolve() for more documentation. See \ref linearSolve() for more documentation.
<b>\#include</b> \<<a href="regression_8hxx-source.html">vigra/regressi <b>\#include</b> \<<a href="regression_8hxx-source.html">vigra/regressi
on_8hxx.hxx</a>\> or<br> on.hxx</a>\>
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin
ear_algebra.hxx</a>\><br>
Namespaces: vigra and vigra::linalg Namespaces: vigra and vigra::linalg
*/ */
template <class T, class C1, class C2, class C3> template <class T, class C1, class C2, class C3>
inline bool inline bool
leastSquares(MultiArrayView<2, T, C1> const & A, leastSquares(MultiArrayView<2, T, C1> const & A,
MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> &x , MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> &x ,
std::string method = "QR") std::string method = "QR")
{ {
return linearSolve(A, b, x, method); return linearSolve(A, b, x, method);
} }
/** Weighted Least Squares Regression. /** Weighted Least Squares Regression.
Given a matrix \a A with <tt>m</tt> rows and <tt>n</tt> columns (wit h <tt>m \>= n</tt>), Given a matrix \a A with <tt>m</tt> rows and <tt>n</tt> columns (wit h <tt>m \>= n</tt>),
a vector \a b of length <tt>m</tt>, and a weight vector \a weights o f length <tt>m</tt> a vector \a b of length <tt>m</tt>, and a weight vector \a weights o f length <tt>m</tt>
with non-negative entries, this function computes a vector \a x of l with non-negative entries, this function computes the vector \a x of
ength <tt>n</tt> length <tt>n</tt>
such that the weighted residual that solves the optimization problem
\f[ \left(\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\right)^T \f[ \tilde \textrm{\bf x} = \textrm{argmin}
\left(\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\right)^T
\textrm{diag}(\textrm{\bf weights}) \textrm{diag}(\textrm{\bf weights})
\left(\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\right) \left(\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\right)
\f] \f]
is minimized, where <tt>diag(weights)</tt> creates a diagonal matrix from \a weights. where <tt>diag(weights)</tt> creates a diagonal matrix from \a weigh ts.
The algorithm calls \ref leastSquares() on the equivalent problem The algorithm calls \ref leastSquares() on the equivalent problem
\f[ \left|\textrm{diag}(\textrm{\bf weights})^{1/2}\textrm{\bf A} \ \f[ \tilde \textrm{\bf x} = \textrm{argmin}
textrm{\bf x} - \left|\left|\textrm{diag}(\textrm{\bf weights})^{1/2}\textrm{\
\textrm{diag}(\textrm{\bf weights})^{1/2} \textrm{\bf b}\ bf A} \textrm{\bf x} -
right|^2 \textrm{diag}(\textrm{\bf weights})^{1/2} \textrm{\bf b}\
right|\right|_2^2
\f] \f]
where the square root of \a weights is just taken element-wise. where the square root of \a weights is just taken element-wise.
When \a b is a matrix with <tt>k</tt> columns, \a x must also have When \a b is a matrix with <tt>k</tt> columns, \a x must also have
<tt>k</tt> columns, which will contain the solutions for the corresp onding columns of <tt>k</tt> columns, which will contain the solutions for the corresp onding columns of
\a b. Note that all matrices must already have the correct shape. \a b. Note that all matrices must already have the correct shape.
The function returns The function returns
<tt>false</tt> when the rank of the weighted matrix \a A is less tha n <tt>n</tt>. <tt>false</tt> when the rank of the weighted matrix \a A is less tha n <tt>n</tt>.
<b>\#include</b> \<<a href="regression_8hxx-source.html">vigra/regressi <b>\#include</b> \<<a href="regression_8hxx-source.html">vigra/regressi
on.hxx</a>\> or<br> on.hxx</a>\>
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin
ear_algebra.hxx</a>\><br>
Namespaces: vigra and vigra::linalg Namespaces: vigra and vigra::linalg
*/ */
template <class T, class C1, class C2, class C3, class C4> template <class T, class C1, class C2, class C3, class C4>
bool bool
weightedLeastSquares(MultiArrayView<2, T, C1> const & A, weightedLeastSquares(MultiArrayView<2, T, C1> const & A,
MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> co nst &weights, MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> co nst &weights,
MultiArrayView<2, T, C4> &x, std::string method = "QR") MultiArrayView<2, T, C4> &x, std::string method = "QR")
{ {
typedef T Real; typedef T Real;
skipping to change at line 158 skipping to change at line 158
wb(k,l) = w * b(k,l); wb(k,l) = w * b(k,l);
} }
return leastSquares(wa, wb, x, method); return leastSquares(wa, wb, x, method);
} }
/** Ridge Regression. /** Ridge Regression.
Given a matrix \a A with <tt>m</tt> rows and <tt>n</tt> columns (wit h <tt>m \>= n</tt>), Given a matrix \a A with <tt>m</tt> rows and <tt>n</tt> columns (wit h <tt>m \>= n</tt>),
a vector \a b of length <tt>m</tt>, and a regularization parameter < tt>lambda \>= 0.0</tt>, a vector \a b of length <tt>m</tt>, and a regularization parameter < tt>lambda \>= 0.0</tt>,
this function computes a vector \a x of length <tt>n</tt> such that this function computes the vector \a x of length <tt>n</tt>
the residual that solves the optimization problem
\f[ \left|\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\right|^2 + \f[ \tilde \textrm{\bf x} = \textrm{argmin}
\left|\left|\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\righ
t|\right|_2^2 +
\lambda \textrm{\bf x}^T\textrm{\bf x} \lambda \textrm{\bf x}^T\textrm{\bf x}
\f] \f]
is minimized. This is implemented by means of \ref singularValueDeco mposition(). This is implemented by means of \ref singularValueDecomposition().
When \a b is a matrix with <tt>k</tt> columns, \a x must also have When \a b is a matrix with <tt>k</tt> columns, \a x must also have
<tt>k</tt> columns, which will contain the solutions for the corresp onding columns of <tt>k</tt> columns, which will contain the solutions for the corresp onding columns of
\a b. Note that all matrices must already have the correct shape. \a b. Note that all matrices must already have the correct shape.
The function returns <tt>false</tt> if the rank of \a A is less than <tt>n</tt> The function returns <tt>false</tt> if the rank of \a A is less than <tt>n</tt>
and <tt>lambda == 0.0</tt>. and <tt>lambda == 0.0</tt>.
<b>\#include</b> \<<a href="regression_8hxx-source.html">vigra/regressi <b>\#include</b> \<<a href="regression_8hxx-source.html">vigra/regressi
on.hxx</a>\> or<br> on.hxx</a>\>
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin
ear_algebra.hxx</a>\><br>
Namespaces: vigra and vigra::linalg Namespaces: vigra and vigra::linalg
*/ */
template <class T, class C1, class C2, class C3> template <class T, class C1, class C2, class C3>
bool bool
ridgeRegression(MultiArrayView<2, T, C1> const & A, ridgeRegression(MultiArrayView<2, T, C1> const & A,
MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> &x, double lambda) MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> &x, double lambda)
{ {
typedef T Real; typedef T Real;
const unsigned int rows = rowCount(A); const unsigned int rows = rowCount(A);
skipping to change at line 218 skipping to change at line 219
t(k,l) *= s(k,0) / (sq(s(k,0)) + lambda); t(k,l) *= s(k,0) / (sq(s(k,0)) + lambda);
x = v*t; x = v*t;
return true; return true;
} }
/** Weighted ridge Regression. /** Weighted ridge Regression.
Given a matrix \a A with <tt>m</tt> rows and <tt>n</tt> columns (wit h <tt>m \>= n</tt>), Given a matrix \a A with <tt>m</tt> rows and <tt>n</tt> columns (wit h <tt>m \>= n</tt>),
a vector \a b of length <tt>m</tt>, a weight vector \a weights of le ngth <tt>m</tt> a vector \a b of length <tt>m</tt>, a weight vector \a weights of le ngth <tt>m</tt>
with non-negative entries, and a regularization parameter <tt>lambda >= 0.0</tt> with non-negative entries, and a regularization parameter <tt>lambda >= 0.0</tt>
this function computes a vector \a x of length <tt>n</tt> such that this function computes the vector \a x of length <tt>n</tt>
the weighted residual that solves the optimization problem
\f[ \left(\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\right)^T \f[ \tilde \textrm{\bf x} = \textrm{argmin}
\left(\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\right)^T
\textrm{diag}(\textrm{\bf weights}) \textrm{diag}(\textrm{\bf weights})
\left(\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\right) + \left(\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\right) +
\lambda \textrm{\bf x}^T\textrm{\bf x} \lambda \textrm{\bf x}^T\textrm{\bf x}
\f] \f]
is minimized, where <tt>diag(weights)</tt> creates a diagonal matrix from \a weights. where <tt>diag(weights)</tt> creates a diagonal matrix from \a weigh ts.
The algorithm calls \ref ridgeRegression() on the equivalent problem The algorithm calls \ref ridgeRegression() on the equivalent problem
\f[ \left|\textrm{diag}(\textrm{\bf weights})^{1/2}\textrm{\bf A} \ \f[ \tilde \textrm{\bf x} = \textrm{argmin}
textrm{\bf x} - \left|\left|\textrm{diag}(\textrm{\bf weights})^{1/2}\textrm{\b
\textrm{diag}(\textrm{\bf weights})^{1/2} \textrm{\bf b}\ f A} \textrm{\bf x} -
right|^2 + \textrm{diag}(\textrm{\bf weights})^{1/2} \textrm{\bf b}\
right|\right|_2^2 +
\lambda \textrm{\bf x}^T\textrm{\bf x} \lambda \textrm{\bf x}^T\textrm{\bf x}
\f] \f]
where the square root of \a weights is just taken element-wise. Thi s solution is where the square root of \a weights is just taken element-wise. Thi s solution is
computed by means of \ref singularValueDecomposition(). computed by means of \ref singularValueDecomposition().
When \a b is a matrix with <tt>k</tt> columns, \a x must also have When \a b is a matrix with <tt>k</tt> columns, \a x must also have
<tt>k</tt> columns, which will contain the solutions for the corresp onding columns of <tt>k</tt> columns, which will contain the solutions for the corresp onding columns of
\a b. Note that all matrices must already have the correct shape. \a b. Note that all matrices must already have the correct shape.
The function returns <tt>false</tt> if the rank of \a A is less than <tt>n</tt> The function returns <tt>false</tt> if the rank of \a A is less than <tt>n</tt>
and <tt>lambda == 0.0</tt>. and <tt>lambda == 0.0</tt>.
<b>\#include</b> \<<a href="regression_8hxx-source.html">vigra/regressi <b>\#include</b> \<<a href="regression_8hxx-source.html">vigra/regressi
on.hxx</a>\> or<br> on.hxx</a>\>
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin
ear_algebra.hxx</a>\><br>
Namespaces: vigra and vigra::linalg Namespaces: vigra and vigra::linalg
*/ */
template <class T, class C1, class C2, class C3, class C4> template <class T, class C1, class C2, class C3, class C4>
bool bool
weightedRidgeRegression(MultiArrayView<2, T, C1> const & A, weightedRidgeRegression(MultiArrayView<2, T, C1> const & A,
MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> co nst &weights, MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> co nst &weights,
MultiArrayView<2, T, C4> &x, double lambda) MultiArrayView<2, T, C4> &x, double lambda)
{ {
typedef T Real; typedef T Real;
skipping to change at line 299 skipping to change at line 302
is implemented so that the \ref singularValueDecomposition() has to be executed only once. is implemented so that the \ref singularValueDecomposition() has to be executed only once.
\a lambda must be an array conforming to the <tt>std::vector</tt> in terface, i.e. must \a lambda must be an array conforming to the <tt>std::vector</tt> in terface, i.e. must
support <tt>lambda.size()</tt> and <tt>lambda[k]</tt>. The columns o f the matrix \a x support <tt>lambda.size()</tt> and <tt>lambda[k]</tt>. The columns o f the matrix \a x
will contain the solutions for the corresponding lambda, so the num ber of columns of will contain the solutions for the corresponding lambda, so the num ber of columns of
the matrix \a x must be equal to <tt>lambda.size()</tt>, and \a b mu st be a columns vector, the matrix \a x must be equal to <tt>lambda.size()</tt>, and \a b mu st be a columns vector,
i.e. cannot contain several right hand sides at once. i.e. cannot contain several right hand sides at once.
The function returns <tt>false</tt> when the matrix \a A is rank def icient. If this The function returns <tt>false</tt> when the matrix \a A is rank def icient. If this
happens, and one of the lambdas is zero, the corresponding column of \a x will be skipped. happens, and one of the lambdas is zero, the corresponding column of \a x will be skipped.
<b>\#include</b> \<<a href="regression_8hxx-source.html">vigra/regressi <b>\#include</b> \<<a href="regression_8hxx-source.html">vigra/regressi
on.hxx</a>\> or<br> on.hxx</a>\>
<b>\#include</b> \<<a href="linear__algebra_8hxx-source.html">vigra/lin
ear_algebra.hxx</a>\><br>
Namespaces: vigra and vigra::linalg Namespaces: vigra and vigra::linalg
*/ */
template <class T, class C1, class C2, class C3, class Array> template <class T, class C1, class C2, class C3, class Array>
bool bool
ridgeRegressionSeries(MultiArrayView<2, T, C1> const & A, ridgeRegressionSeries(MultiArrayView<2, T, C1> const & A,
MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> &x, A rray const & lambda) MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> &x, A rray const & lambda)
{ {
typedef T Real; typedef T Real;
const unsigned int rows = rowCount(A); const unsigned int rows = rowCount(A);
skipping to change at line 333 skipping to change at line 335
Matrix<T> u(m, n), s(n, 1), v(n, n); Matrix<T> u(m, n), s(n, 1), v(n, n);
unsigned int rank = singularValueDecomposition(A, u, s, v); unsigned int rank = singularValueDecomposition(A, u, s, v);
Matrix<T> xl = transpose(u)*b; Matrix<T> xl = transpose(u)*b;
Matrix<T> xt(cols,1); Matrix<T> xt(cols,1);
for(unsigned int i=0; i<lambdaCount; ++i) for(unsigned int i=0; i<lambdaCount; ++i)
{ {
vigra_precondition(lambda[i] >= 0.0, vigra_precondition(lambda[i] >= 0.0,
"ridgeRegressionSeries(): lambda >= 0.0 required."); "ridgeRegressionSeries(): lambda >= 0.0 required.");
if(lambda == 0.0 && rank < rows) if(lambda[i] == 0.0 && rank < rows)
continue; continue;
for(unsigned int k=0; k<cols; ++k) for(unsigned int k=0; k<cols; ++k)
xt(k,0) = xl(k,0) * s(k,0) / (sq(s(k,0)) + lambda[i]); xt(k,0) = xl(k,0) * s(k,0) / (sq(s(k,0)) + lambda[i]);
columnVector(x, i) = v*xt; columnVector(x, i) = v*xt;
} }
return (rank < n); return (rank == n);
} }
/** \brief Pass options to leastAngleRegression().
<b>\#include</b> \<<a href="regression_8hxx-source.html">vigra/regressi
on.hxx</a>\>
Namespaces: vigra and vigra::linalg
*/
class LeastAngleRegressionOptions
{
public:
enum Mode { LARS, LASSO, NNLASSO };
/** Initialize all options with default values.
*/
LeastAngleRegressionOptions()
: max_solution_count(0),
unconstrained_dimension_count(0),
mode(LASSO),
least_squares_solutions(true)
{}
/** Maximum number of solutions to be computed.
If \a n is 0 (the default), the number of solutions is determin
ed by the length
of the solution array. Otherwise, the minimum of maxSolutionCou
nt() and that
length is taken.<br>
Default: 0 (use length of solution array)
*/
LeastAngleRegressionOptions & maxSolutionCount(unsigned int n)
{
max_solution_count = (int)n;
return *this;
}
/** Set the mode of the algorithm.
Mode must be one of "lars", "lasso", "nnlasso". The function ju
st calls
the member function of the corresponding name to set the mode.
Default: "lasso"
*/
LeastAngleRegressionOptions & setMode(std::string mode)
{
for(unsigned int k=0; k<mode.size(); ++k)
mode[k] = (std::string::value_type)tolower(mode[k]);
if(mode == "lars")
this->lars();
else if(mode == "lasso")
this->lasso();
else if(mode == "nnlasso")
this->nnlasso();
else
vigra_fail("LeastAngleRegressionOptions.setMode(): Invalid mode
.");
return *this;
}
/** Use the plain LARS algorithm.
Default: inactive
*/
LeastAngleRegressionOptions & lars()
{
mode = LARS;
return *this;
}
/** Use the LASSO modification of the LARS algorithm.
This allows features to be removed from the active set under ce
rtain conditions.<br>
Default: active
*/
LeastAngleRegressionOptions & lasso()
{
mode = LASSO;
return *this;
}
/** Use the non-negative LASSO modification of the LARS algorithm.
This enforces all non-zero entries in the solution to be positi
ve.<br>
Default: inactive
*/
LeastAngleRegressionOptions & nnlasso()
{
mode = NNLASSO;
return *this;
}
/** Compute least squares solutions.
Use least angle regression to determine active sets, but
return least squares solutions for the features in each active
set,
instead of constrained solutions.<br>
Default: <tt>true</tt>
*/
LeastAngleRegressionOptions & leastSquaresSolutions(bool select = true)
{
least_squares_solutions = select;
return *this;
}
int max_solution_count, unconstrained_dimension_count;
Mode mode;
bool least_squares_solutions;
};
namespace detail {
template <class T, class C1, class C2>
struct LarsData
{
typedef typename MultiArrayShape<2>::type Shape;
int activeSetSize;
MultiArrayView<2, T, C1> A;
MultiArrayView<2, T, C2> b;
Matrix<T> R, qtb, lars_solution, lars_prediction, next_lsq_solution, ne
xt_lsq_prediction, searchVector;
ArrayVector<MultiArrayIndex> columnPermutation;
// init data for a new run
LarsData(MultiArrayView<2, T, C1> const & Ai, MultiArrayView<2, T, C2>
const & bi)
: activeSetSize(1),
A(Ai), b(bi), R(A), qtb(b),
lars_solution(A.shape(1), 1), lars_prediction(A.shape(0), 1),
next_lsq_solution(A.shape(1), 1), next_lsq_prediction(A.shape(0), 1),
searchVector(A.shape(0), 1),
columnPermutation(A.shape(1))
{
for(unsigned int k=0; k<columnPermutation.size(); ++k)
columnPermutation[k] = k;
}
// copy data for the recursive call in nnlassolsq
LarsData(LarsData const & d, int asetSize)
: activeSetSize(asetSize),
A(d.R.subarray(Shape(0,0), Shape(d.A.shape(0), activeSetSize))), b(d.
qtb), R(A), qtb(b),
lars_solution(d.lars_solution.subarray(Shape(0,0), Shape(activeSetSiz
e, 1))), lars_prediction(d.lars_prediction),
next_lsq_solution(d.next_lsq_solution.subarray(Shape(0,0), Shape(acti
veSetSize, 1))),
next_lsq_prediction(d.next_lsq_prediction), searchVector(d.searchVect
or),
columnPermutation(A.shape(1))
{
for(unsigned int k=0; k<columnPermutation.size(); ++k)
columnPermutation[k] = k;
}
};
template <class T, class C1, class C2, class Array1, class Array2>
unsigned int leastAngleRegressionMainLoop(LarsData<T, C1, C2> & d,
Array1 & activeSets, Array2 * lars_solutions, Array2 * ls
q_solutions,
LeastAngleRegressionOptions const & options)
{
using namespace vigra::functor;
typedef typename MultiArrayShape<2>::type Shape;
typedef typename Matrix<T>::view_type Subarray;
typedef ArrayVector<MultiArrayIndex> Permutation;
typedef typename Permutation::view_type ColumnSet;
vigra_precondition(d.activeSetSize > 0,
"leastAngleRegressionMainLoop() must not be called with empty active
set.");
bool enforce_positive = (options.mode == LeastAngleRegressionOptions::N
NLASSO);
bool lasso_modification = (options.mode != LeastAngleRegressionOptions:
:LARS);
const MultiArrayIndex rows = rowCount(d.R);
const MultiArrayIndex cols = columnCount(d.R);
const MultiArrayIndex maxRank = std::min(rows, cols);
MultiArrayIndex maxSolutionCount = options.max_solution_count;
if(maxSolutionCount == 0)
maxSolutionCount = lasso_modification
? 10*maxRank
: maxRank;
bool needToRemoveColumn = false;
MultiArrayIndex columnToBeAdded, columnToBeRemoved;
MultiArrayIndex currentSolutionCount = 0;
while(currentSolutionCount < maxSolutionCount)
{
ColumnSet activeSet = d.columnPermutation.subarray(0, (unsigned int
)d.activeSetSize);
ColumnSet inactiveSet = d.columnPermutation.subarray((unsigned int)
d.activeSetSize, (unsigned int)cols);
// find next dimension to be activated
Matrix<T> cLARS = transpose(d.A) * (d.b - d.lars_prediction),
// correlation with LARS residual
cLSQ = transpose(d.A) * (d.b - d.next_lsq_prediction);
// correlation with LSQ residual
// In theory, all vectors in the active set should have the same co
rrelation C, and
// the correlation of all others should not exceed this. In practic
e, we may find the
// maximum correlation in any variable due to tiny numerical inaccu
racies. Therefore, we
// determine C from the entire set of variables.
MultiArrayIndex cmaxIndex = enforce_positive
? argMax(cLARS)
: argMax(abs(cLARS));
T C = abs(cLARS(cmaxIndex, 0));
Matrix<T> ac(cols - d.activeSetSize, 1);
for(MultiArrayIndex k = 0; k<cols-d.activeSetSize; ++k)
{
T rho = cLSQ(inactiveSet[k], 0),
cc = C - sign(rho)*cLARS(inactiveSet[k], 0);
if(rho == 0.0) // make sure that 0/0 cannot happen in the othe
r cases
ac(k,0) = 1.0; // variable k is linearly dependent on the a
ctive set
else if(rho > 0.0)
ac(k,0) = cc / (cc + rho); // variable k would enter the ac
tive set with positive sign
else if(enforce_positive)
ac(k,0) = 1.0; // variable k cannot enter the active set be
cause it would be negative
else
ac(k,0) = cc / (cc - rho); // variable k would enter the ac
tive set with negative sign
}
// in the non-negative case: make sure that a column just removed c
annot re-enter right away
// (in standard LASSO, this is allowed, because the variable may re
-enter with opposite sign)
if(enforce_positive && needToRemoveColumn)
ac(columnToBeRemoved-d.activeSetSize,0) = 1.0;
// find candidate
// Note: R uses Arg1() > epsilon, but this is only possible because
it allows several variables to
// join the active set simultaneously, so that gamma = 0 cann
ot occur.
columnToBeAdded = argMin(ac);
// if no new column can be added, we do a full step gamma = 1.0 and
then stop, unless a column is removed below
T gamma = (d.activeSetSize == maxRank)
? 1.0
: ac(columnToBeAdded, 0);
// adjust columnToBeAdded: we skipped the active set
if(columnToBeAdded >= 0)
columnToBeAdded += d.activeSetSize;
// check whether we have to remove a column from the active set
needToRemoveColumn = false;
if(lasso_modification)
{
// find dimensions whose weight changes sign below gamma*search
Direction
Matrix<T> s(Shape(d.activeSetSize, 1), NumericTraits<T>::max())
;
for(MultiArrayIndex k=0; k<d.activeSetSize; ++k)
{
if(( enforce_positive && d.next_lsq_solution(k,0) < 0.0) ||
(!enforce_positive && sign(d.lars_solution(k,0))*sign(d.
next_lsq_solution(k,0)) == -1.0))
s(k,0) = d.lars_solution(k,0) / (d.lars_solution(k,
0) - d.next_lsq_solution(k,0));
}
columnToBeRemoved = argMinIf(s, Arg1() <= Param(gamma));
if(columnToBeRemoved >= 0)
{
needToRemoveColumn = true; // remove takes precedence over
add
gamma = s(columnToBeRemoved, 0);
}
}
// compute the current solutions
d.lars_prediction = gamma * d.next_lsq_prediction + (1.0 - gamma)
* d.lars_prediction;
d.lars_solution = gamma * d.next_lsq_solution + (1.0 - gamma)
* d.lars_solution;
if(needToRemoveColumn)
d.lars_solution(columnToBeRemoved, 0) = 0.0; // turn possible
epsilon into an exact zero
// write the current solution
++currentSolutionCount;
activeSets.push_back(typename Array1::value_type(d.columnPermutatio
n.begin(), d.columnPermutation.begin()+d.activeSetSize));
if(lsq_solutions != 0)
{
if(enforce_positive)
{
ArrayVector<Matrix<T> > nnresults;
ArrayVector<ArrayVector<MultiArrayIndex> > nnactiveSets;
LarsData<T, C1, C2> nnd(d, d.activeSetSize);
leastAngleRegressionMainLoop(nnd, nnactiveSets, &nnresults,
(Array2*)0,
LeastAngleRegressionOptions().
leastSquaresSolutions(false).nnlasso());
Matrix<T> nnlsq_solution(d.activeSetSize, 1);
for(unsigned int k=0; k<nnactiveSets.back().size(); ++k)
{
nnlsq_solution(nnactiveSets.back()[k],0) = nnresults.ba
ck()[k];
}
lsq_solutions->push_back(nnlsq_solution);
}
else
{
lsq_solutions->push_back(d.next_lsq_solution.subarray(Shape
(0,0), Shape(d.activeSetSize, 1)));
}
}
if(lars_solutions != 0)
{
lars_solutions->push_back(d.lars_solution.subarray(Shape(0,0),
Shape(d.activeSetSize, 1)));
}
// no further solutions possible
if(gamma == 1.0)
break;
if(needToRemoveColumn)
{
--d.activeSetSize;
if(columnToBeRemoved != d.activeSetSize)
{
// remove column 'columnToBeRemoved' and restore triangular
form of R
// note: columnPermutation is automatically swapped here
detail::upperTriangularSwapColumns(columnToBeRemoved, d.act
iveSetSize, d.R, d.qtb, d.columnPermutation);
// swap solution entries
std::swap(d.lars_solution(columnToBeRemoved, 0), d.lars_sol
ution(d.activeSetSize,0));
std::swap(d.next_lsq_solution(columnToBeRemoved, 0), d.next
_lsq_solution(d.activeSetSize,0));
columnToBeRemoved = d.activeSetSize; // keep track of remov
ed column
}
d.lars_solution(d.activeSetSize,0) = 0.0;
d.next_lsq_solution(d.activeSetSize,0) = 0.0;
}
else
{
vigra_invariant(columnToBeAdded >= 0,
"leastAngleRegression(): internal error (columnToBeAdded <
0)");
// add column 'columnToBeAdded'
if(d.activeSetSize != columnToBeAdded)
{
std::swap(d.columnPermutation[d.activeSetSize], d.columnPer
mutation[columnToBeAdded]);
columnVector(d.R, d.activeSetSize).swapData(columnVector(d.
R, columnToBeAdded));
columnToBeAdded = d.activeSetSize; // keep track of added c
olumn
}
// zero the corresponding entries of the solutions
d.next_lsq_solution(d.activeSetSize,0) = 0.0;
d.lars_solution(d.activeSetSize,0) = 0.0;
// reduce R (i.e. its newly added column) to triangular form
detail::qrColumnHouseholderStep(d.activeSetSize, d.R, d.qtb);
++d.activeSetSize;
}
// compute the LSQ solution of the new active set
Subarray Ractive = d.R.subarray(Shape(0,0), Shape(d.activeSetSize,
d.activeSetSize));
Subarray qtbactive = d.qtb.subarray(Shape(0,0), Shape(d.activeSetSi
ze, 1));
Subarray next_lsq_solution_view = d.next_lsq_solution.subarray(Shap
e(0,0), Shape(d.activeSetSize, 1));
linearSolveUpperTriangular(Ractive, qtbactive, next_lsq_solution_vi
ew);
// compute the LSQ prediction of the new active set
d.next_lsq_prediction.init(0.0);
for(MultiArrayIndex k=0; k<d.activeSetSize; ++k)
d.next_lsq_prediction += next_lsq_solution_view(k,0)*columnVect
or(d.A, d.columnPermutation[k]);
}
return (unsigned int)currentSolutionCount;
}
#if 0
// old version, keep it until we are sure that the new version works
template <class T, class C1, class C2, class Array1, class Array2>
unsigned int leastAngleRegressionMainLoop(LarsData<T, C1, C2> & d,
Array1 & activeSets, Array2 * lars_solutions, Array2 * ls
q_solutions,
LeastAngleRegressionOptions const & options)
{
using namespace vigra::functor;
typedef typename MultiArrayShape<2>::type Shape;
typedef typename Matrix<T>::view_type Subarray;
typedef ArrayVector<MultiArrayIndex> Permutation;
typedef typename Permutation::view_type ColumnSet;
vigra_precondition(d.activeSetSize > 0,
"leastAngleRegressionMainLoop() must not be called with empty active
set.");
bool enforce_positive = (options.mode == LeastAngleRegressionOptions::N
NLASSO);
bool lasso_modification = (options.mode != LeastAngleRegressionOptions:
:LARS);
const MultiArrayIndex rows = rowCount(d.R);
const MultiArrayIndex cols = columnCount(d.R);
const MultiArrayIndex maxRank = std::min(rows, cols);
MultiArrayIndex maxSolutionCount = options.max_solution_count;
if(maxSolutionCount == 0)
maxSolutionCount = lasso_modification
? 10*maxRank
: maxRank;
bool needToRemoveColumn = false;
MultiArrayIndex columnToBeAdded, columnToBeRemoved;
MultiArrayIndex currentSolutionCount = 0;
while(currentSolutionCount < maxSolutionCount)
{
ColumnSet activeSet = d.columnPermutation.subarray(0, (unsigned int
)d.activeSetSize);
ColumnSet inactiveSet = d.columnPermutation.subarray((unsigned int)
d.activeSetSize, (unsigned int)cols);
// find next dimension to be activated
Matrix<T> lars_residual = d.b - d.lars_prediction;
Matrix<T> lsq_residual = lars_residual - d.searchVector;
Matrix<T> c = transpose(d.A) * lars_residual;
// In theory, all vecors in the active set should have the same cor
relation C, and
// the correlation of all others should not exceed this. In practic
e, we may find the
// maximum correlation in any variable due to tiny numerical inaccu
racies. Therefore, we
// determine C from the entire set of variables.
MultiArrayIndex cmaxIndex = enforce_positive
? argMax(c)
: argMax(abs(c));
T C = abs(c(cmaxIndex, 0));
Matrix<T> ac(cols - d.activeSetSize, 1);
for(MultiArrayIndex k = 0; k<cols-d.activeSetSize; ++k)
{
T a = dot(columnVector(d.A, inactiveSet[k]), d.searchVector),
a1 = (C - c(inactiveSet[k], 0)) / (C - a),
a2 = (C + c(inactiveSet[k], 0)) / (C + a);
if(enforce_positive)
ac(k, 0) = a1;
else if(std::min(a1, a2) < 0.0)
ac(k, 0) = std::max(a1, a2);
else
ac(k, 0) = std::min(a1, a2);
}
// in the non-negative case: make sure that a column just removed c
annot re-enter right away
// (in standard LASSO, this is allowed, because the variable may re
-enter with opposite sign)
if(enforce_positive && needToRemoveColumn)
ac(columnToBeRemoved-d.activeSetSize,0) = -1.0;
// find candidate
// Note: R uses Arg1() > epsilon, but this is only possible because
it allows several variables to
// join the active set simultaneously, so that gamma = 0 cann
ot occur.
columnToBeAdded = argMinIf(ac, Arg1() < Param(1.0) && Arg1() >= Par
am(NumericTraits<T>::zero()));
// if no new column can be added, we do a full step gamma = 1.0 and
then stop, unless a column is removed below
T gamma = (columnToBeAdded == -1 || d.activeSetSize == maxRank)
? 1.0
: ac(columnToBeAdded, 0);
// adjust columnToBeAdded: we skipped the active set
if(columnToBeAdded >= 0)
columnToBeAdded += d.activeSetSize;
// check whether we have to remove a column from the active set
needToRemoveColumn = false;
if(lasso_modification)
{
// find dimensions whose weight changes sign below gamma*search
Direction
Matrix<T> s(Shape(d.activeSetSize, 1), NumericTraits<T>::max())
;
for(MultiArrayIndex k=0; k<d.activeSetSize; ++k)
{
if(( enforce_positive && d.next_lsq_solution(k,0) < 0.0) ||
(!enforce_positive && sign(d.lars_solution(k,0))*sign(d.
next_lsq_solution(k,0)) == -1.0))
s(k,0) = d.lars_solution(k,0) / (d.lars_solution(k,
0) - d.next_lsq_solution(k,0));
}
columnToBeRemoved = argMinIf(s, Arg1() < Param(gamma) && Arg1()
>= Param(NumericTraits<T>::zero()));
if(columnToBeRemoved >= 0)
{
needToRemoveColumn = true; // remove takes precedence over
add
gamma = s(columnToBeRemoved, 0);
}
}
// compute the current solutions
d.lars_prediction += gamma * d.searchVector;
d.lars_solution = gamma * d.next_lsq_solution + (1.0 - gamma) *
d.lars_solution;
if(needToRemoveColumn)
d.lars_solution(columnToBeRemoved, 0) = 0.0; // turn possible
epsilon into an exact zero
// write the current solution
++currentSolutionCount;
activeSets.push_back(typename Array1::value_type(d.columnPermutatio
n.begin(), d.columnPermutation.begin()+d.activeSetSize));
if(lsq_solutions != 0)
{
if(enforce_positive)
{
ArrayVector<Matrix<T> > nnresults;
ArrayVector<ArrayVector<MultiArrayIndex> > nnactiveSets;
LarsData<T, C1, C2> nnd(d, d.activeSetSize);
leastAngleRegressionMainLoop(nnd, nnactiveSets, &nnresults,
(Array2*)0,
LeastAngleRegressionOptions().
leastSquaresSolutions(false).nnlasso());
Matrix<T> nnlsq_solution(d.activeSetSize, 1);
for(unsigned int k=0; k<nnactiveSets.back().size(); ++k)
{
nnlsq_solution(nnactiveSets.back()[k],0) = nnresults.ba
ck()[k];
}
lsq_solutions->push_back(nnlsq_solution);
}
else
{
lsq_solutions->push_back(d.next_lsq_solution.subarray(Shape
(0,0), Shape(d.activeSetSize, 1)));
}
}
if(lars_solutions != 0)
{
lars_solutions->push_back(d.lars_solution.subarray(Shape(0,0),
Shape(d.activeSetSize, 1)));
}
// no further solutions possible
if(gamma == 1.0)
break;
if(needToRemoveColumn)
{
--d.activeSetSize;
if(columnToBeRemoved != d.activeSetSize)
{
// remove column 'columnToBeRemoved' and restore triangular
form of R
// note: columnPermutation is automatically swapped here
detail::upperTriangularSwapColumns(columnToBeRemoved, d.act
iveSetSize, d.R, d.qtb, d.columnPermutation);
// swap solution entries
std::swap(d.lars_solution(columnToBeRemoved, 0), d.lars_sol
ution(d.activeSetSize,0));
std::swap(d.next_lsq_solution(columnToBeRemoved, 0), d.next
_lsq_solution(d.activeSetSize,0));
columnToBeRemoved = d.activeSetSize; // keep track of remov
ed column
}
d.lars_solution(d.activeSetSize,0) = 0.0;
d.next_lsq_solution(d.activeSetSize,0) = 0.0;
}
else
{
vigra_invariant(columnToBeAdded >= 0,
"leastAngleRegression(): internal error (columnToBeAdded <
0)");
// add column 'columnToBeAdded'
if(d.activeSetSize != columnToBeAdded)
{
std::swap(d.columnPermutation[d.activeSetSize], d.columnPer
mutation[columnToBeAdded]);
columnVector(d.R, d.activeSetSize).swapData(columnVector(d.
R, columnToBeAdded));
columnToBeAdded = d.activeSetSize; // keep track of added c
olumn
}
// zero the corresponding entries of the solutions
d.next_lsq_solution(d.activeSetSize,0) = 0.0;
d.lars_solution(d.activeSetSize,0) = 0.0;
// reduce R (i.e. its newly added column) to triangular form
detail::qrColumnHouseholderStep(d.activeSetSize, d.R, d.qtb);
++d.activeSetSize;
}
// compute the LSQ solution of the new active set
Subarray Ractive = d.R.subarray(Shape(0,0), Shape(d.activeSetSize,
d.activeSetSize));
Subarray qtbactive = d.qtb.subarray(Shape(0,0), Shape(d.activeSetSi
ze, 1));
Subarray next_lsq_solution_view = d.next_lsq_solution.subarray(Shap
e(0,0), Shape(d.activeSetSize, 1));
linearSolveUpperTriangular(Ractive, qtbactive, next_lsq_solution_vi
ew);
// compute the LSQ prediction of the new active set
Matrix<T> lsq_prediction(rows, 1);
for(MultiArrayIndex k=0; k<d.activeSetSize; ++k)
lsq_prediction += next_lsq_solution_view(k,0)*columnVector(d.A,
d.columnPermutation[k]);
// finally, the new search direction
d.searchVector = lsq_prediction - d.lars_prediction;
}
return (unsigned int)currentSolutionCount;
}
#endif
template <class T, class C1, class C2, class Array1, class Array2>
unsigned int
leastAngleRegressionImpl(MultiArrayView<2, T, C1> const & A, MultiArrayView
<2, T, C2> const &b,
Array1 & activeSets, Array2 * lasso_solutions, Arr
ay2 * lsq_solutions,
LeastAngleRegressionOptions const & options)
{
using namespace vigra::functor;
const MultiArrayIndex rows = rowCount(A);
vigra_precondition(rowCount(b) == rows && columnCount(b) == 1,
"leastAngleRegression(): Shape mismatch between matrices A and b.");
bool enforce_positive = (options.mode == LeastAngleRegressionOptions::N
NLASSO);
detail::LarsData<T, C1, C2> d(A, b);
// find dimension with largest correlation
Matrix<T> c = transpose(A)*b;
MultiArrayIndex initialColumn = enforce_positive
? argMaxIf(c, Arg1() > Param(0.0))
: argMax(abs(c));
if(initialColumn == -1)
return 0; // no solution found
// prepare initial active set and search direction etc.
std::swap(d.columnPermutation[0], d.columnPermutation[initialColumn]);
columnVector(d.R, 0).swapData(columnVector(d.R, initialColumn));
detail::qrColumnHouseholderStep(0, d.R, d.qtb);
d.next_lsq_solution(0,0) = d.qtb(0,0) / d.R(0,0);
d.next_lsq_prediction = d.next_lsq_solution(0,0) * columnVector(A, d.co
lumnPermutation[0]);
d.searchVector = d.next_lsq_solution(0,0) * columnVector(A, d.columnPer
mutation[0]);
return leastAngleRegressionMainLoop(d, activeSets, lasso_solutions, lsq
_solutions, options);
}
} // namespace detail
/** Least Angle Regression.
<b>\#include</b> \<<a href="regression_8hxx-source.html">vigra/regressi
on.hxx</a>\>
Namespaces: vigra and vigra::linalg
<b> Declarations:</b>
\code
namespace vigra {
namespace linalg {
// compute either LASSO or least sqaures solutions
template <class T, class C1, class C2, class Array1, class Array2>
unsigned int
leastAngleRegression(MultiArrayView<2, T, C1> const & A, MultiArray
View<2, T, C2> const &b,
Array1 & activeSets, Array2 & solutions,
LeastAngleRegressionOptions const & options =
LeastAngleRegressionOptions());
// compute LASSO and least sqaures solutions
template <class T, class C1, class C2, class Array1, class Array2>
unsigned int
leastAngleRegression(MultiArrayView<2, T, C1> const & A, MultiArray
View<2, T, C2> const &b,
Array1 & activeSets, Array2 & lasso_solutions,
Array2 & lsq_solutions,
LeastAngleRegressionOptions const & options =
LeastAngleRegressionOptions());
}
using linalg::leastAngleRegression;
}
\endcode
This function implements Least Angle Regression (LARS) as described
in
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
B.Efron, T.Hastie, I.Johnstone, and R.Tibshirani: <em>"Least Angle R
egression"</em>,
Annals of Statistics 32(2):407-499, 2004.
It is an efficient algorithm to solve the L1-regularized least squar
es (LASSO) problem
\f[ \tilde \textrm{\bf x} = \textrm{argmin}
\left|\left|\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\rig
ht|\right|_2^2
\textrm{ subject to } \left|\left|\textrm{\bf x}\right|\right|_1
\le s
\f]
and the L1-regularized non-negative least squares (NN-LASSO) problem
\f[ \tilde \textrm{\bf x} = \textrm{argmin} \left|\left|\textrm{\bf
A} \textrm{\bf x} - \textrm{\bf b}\right|\right|_2^2
\textrm{ subject to } \left|\left|\textrm{\bf x}\right|\right|_1
\le s \textrm{ and } \textrm{\bf x}\ge \textrm{\bf 0}
\f]
where \a A is a matrix with <tt>m</tt> rows and <tt>n</tt> columns (
often with <tt>m \< n</tt>),
\a b a vector of length <tt>m</tt>, and a regularization parameter s
\>= 0.0.
L1-regularization has the desirable effect that it causes the soluti
on \a x to be sparse, i.e. only
the most important variables (called the <em>active set</em>) have n
on-zero values. The
key insight of the LARS algorithm is the following: When the solutio
n vector is considered
as a function of the regularization parameter s, then <b>x</b>(s) is
a piecewise
linear function, i.e. a polyline in n-dimensional space. The knots o
f the polyline
occur precisely at those values of s where one variable enters or le
aves the active set,
and can be efficiently computed.
Therefore, leastAngleRegression() returns the entire solution path a
s a sequence of knot points, starting
at \f$\textrm{\bf x}(s=0)\f$ (where the only feasible solution is ob
viously <b>x</b> = 0) and ending at
\f$\textrm{\bf x}(s=\infty)\f$ (where the solution becomes the ordin
ary least squares solution). Actually,
the initial null solution is not explicitly returned, i.e. the seque
nce starts at the first non-zero
solution with one variable in the active set. The function leastAngl
eRegression() returns the number
of solutions( i.e. knot points) computed.
The sequences of active sets and corresponding variable weights are
returned in \a activeSets and
\a solutions respectively. That is, <tt>activeSets[i]</tt> is an \re
f vigra::ArrayVector "ArrayVector\<int\>"
containing the indices of the variables that are active at the i-th
knot, and <tt>solutions</tt> is a
\ref vigra::linalg::Matrix "Matrix\<T\>" containing the weights of t
hose variables, in the same order (see
example below). Variables not contained in <tt>activeSets[i]</tt> ar
e zero at this solution.
The behavior of the algorithm can be adapted by \ref vigra::linalg::
LeastAngleRegressionOptions
"LeastAngleRegressionOptions":
<DL>
<DT><b>options.lasso()</b> (active by default)
<DD> Compute the LASSO solution as described abov
e.
<DT><b>options.nnlasso()</b> (inactive by default)
<DD> Compute non-negative LASSO solutions, i.e. u
se the additional constraint that
<b>x</b> \>= 0 in all solutions.
<DT><b>options.lars()</b> (inactive by default)
<DD> Compute a solution path according to the pla
in LARS rule, i.e. never remove
a variable from the active set once it enter
ed.
<DT><b>options.leastSquaresSolutions(bool)</b> (default: true)
<DD> Use the algorithm mode selected above
to determine the sequence of active sets, bu
t then compute and return an
ordinary (unconstrained) least squares solut
ion for every active set.<br>
<b>Note:</b> The second form of leastAngleRe
gression() ignores this option and
does always compute both constrained and unc
onstrained solutions (returned in
\a lasso_solutions and \a lsq_solutions resp
ectively).
<DT><b>maxSolutionCount(unsigned int n)</b> (default: n = 0, i.e. c
ompute all solutions)
<DD> Compute at most <tt>n</tt> solutions.
</DL>
<b>Usage:</b>
\code
int m = ..., n = ...;
Matrix<double> A(m, n), b(m, 1);
... // fill A and b
// normalize the input
Matrix<double> offset(1,n), scaling(1,n);
prepareColumns(A, A, offset, scaling, DataPreparationGoals(ZeroM
ean|UnitVariance));
prepareColumns(b, b, DataPreparationGoals(ZeroMean));
// arrays to hold the output
ArrayVector<ArrayVector<int> > activeSets;
ArrayVector<Matrix<double> > solutions;
// run leastAngleRegression() in non-negative LASSO mode
int numSolutions = leastAngleRegression(A, b, activeSets, soluti
ons,
LeastAngleRegressionOptions().nnlass
o());
// print results
Matrix<double> denseSolution(1, n);
for (MultiArrayIndex k = 0; k < numSolutions; ++k)
{
// transform the sparse solution into a dense vector
denseSolution.init(0.0); // ensure that inactive variabl
es are zero
for (unsigned int i = 0; i < activeSets[k].size(); ++i)
{
// set the values of the active variables;
// activeSets[k][i] is the true index of the i-t
h variable in the active set
denseSolution(0, activeSets[k][i]) = solutions[k
](i,0);
}
// invert the input normalization
denseSolution = denseSolution * pointWise(scaling);
// output the solution
std::cout << "solution " << k << ":\n" << denseSolution << std:
:endl;
}
\endcode
<b>Required Interface:</b>
<ul>
<li> <tt>T</tt> must be numeric type (compatible to double)
<li> <tt>Array1 a1;</tt><br>
<tt>a1.push_back(ArrayVector\<int\>());</tt>
<li> <tt>Array2 a2;</tt><br>
<tt>a2.push_back(Matrix\<T\>());</tt>
</ul>
*/
doxygen_overloaded_function(template <...> unsigned int leastAngleRegressio
n)
template <class T, class C1, class C2, class Array1, class Array2>
inline unsigned int
leastAngleRegression(MultiArrayView<2, T, C1> const & A, MultiArrayView<2,
T, C2> const &b,
Array1 & activeSets, Array2 & solutions,
LeastAngleRegressionOptions const & options = LeastAng
leRegressionOptions())
{
if(options.least_squares_solutions)
return detail::leastAngleRegressionImpl(A, b, activeSets, (Array2*)
0, &solutions, options);
else
return detail::leastAngleRegressionImpl(A, b, activeSets, &solution
s, (Array2*)0, options);
}
template <class T, class C1, class C2, class Array1, class Array2>
inline unsigned int
leastAngleRegression(MultiArrayView<2, T, C1> const & A, MultiArrayView<2,
T, C2> const &b,
Array1 & activeSets, Array2 & lasso_solutions, Array2
& lsq_solutions,
LeastAngleRegressionOptions const & options = LeastAng
leRegressionOptions())
{
return detail::leastAngleRegressionImpl(A, b, activeSets, &lasso_soluti
ons, &lsq_solutions, options);
}
/** Non-negative Least Squares Regression.
Given a matrix \a A with <tt>m</tt> rows and <tt>n</tt> columns (wit
h <tt>m \>= n</tt>),
and a column vector \a b of length <tt>m</tt> rows, this function co
mputes
a column vector \a x of length <tt>n</tt> with <b>non-negative entri
es</b> that solves the optimization problem
\f[ \tilde \textrm{\bf x} = \textrm{argmin}
\left|\left|\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\righ
t|\right|_2^2
\textrm{ subject to } \textrm{\bf x} \ge \textrm{\bf 0}
\f]
Both \a b and \a x must be column vectors (i.e. matrices with <tt>1<
/tt> column).
Note that all matrices must already have the correct shape. The solu
tion is computed by means
of \ref leastAngleRegression() with non-negativity constraint.
<b>\#include</b> \<<a href="regression_8hxx-source.html">vigra/regressi
on.hxx</a>\>
Namespaces: vigra and vigra::linalg
*/
template <class T, class C1, class C2, class C3>
inline void
nonnegativeLeastSquares(MultiArrayView<2, T, C1> const & A,
MultiArrayView<2, T, C2> const &b, MultiArrayView<2
, T, C3> &x)
{
vigra_precondition(columnCount(A) == rowCount(x) && rowCount(A) == r
owCount(b),
"nonnegativeLeastSquares(): Matrix shape mismatch.");
vigra_precondition(columnCount(b) == 1 && columnCount(x) == 1,
"nonnegativeLeastSquares(): RHS and solution must be vectors (i.
e. columnCount == 1).");
ArrayVector<ArrayVector<MultiArrayIndex> > activeSets;
ArrayVector<Matrix<T> > results;
leastAngleRegression(A, b, activeSets, results,
LeastAngleRegressionOptions().leastSquaresSolution
s(false).nnlasso());
x.init(NumericTraits<T>::zero());
if(activeSets.size() > 0)
for(unsigned int k=0; k<activeSets.back().size(); ++k)
x(activeSets.back()[k],0) = results.back()[k];
}
//@}
} // namespace linalg } // namespace linalg
using linalg::leastSquares; using linalg::leastSquares;
using linalg::weightedLeastSquares; using linalg::weightedLeastSquares;
using linalg::ridgeRegression; using linalg::ridgeRegression;
using linalg::weightedRidgeRegression; using linalg::weightedRidgeRegression;
using linalg::ridgeRegressionSeries; using linalg::ridgeRegressionSeries;
using linalg::nonnegativeLeastSquares;
using linalg::leastAngleRegression;
using linalg::LeastAngleRegressionOptions;
} // namespace vigra } // namespace vigra
#endif // VIGRA_REGRESSION_HXX #endif // VIGRA_REGRESSION_HXX
 End of changes. 26 change blocks. 
49 lines changed or deleted 1023 lines changed or added


 resampling_convolution.hxx   resampling_convolution.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2004 by Ullrich Koethe */ /* Copyright 1998-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 330 skipping to change at line 328
{ {
vigra_precondition(-lbound < wo && wo2 - hbound >= 0, vigra_precondition(-lbound < wo && wo2 - hbound >= 0,
"resamplingConvolveLine(): kernel or offset larger than ima ge."); "resamplingConvolveLine(): kernel or offset larger than ima ge.");
for(int m=lbound; m <= hbound; ++m, --k) for(int m=lbound; m <= hbound; ++m, --k)
{ {
int mm = (m < 0) ? int mm = (m < 0) ?
-m : -m :
(m >= wo) ? (m >= wo) ?
wo2 - m : wo2 - m :
m; m;
sum += *k * src(s, mm); sum = TmpType(sum + *k * src(s, mm));
} }
} }
else else
{ {
SrcIter ss = s + lbound; SrcIter ss = s + lbound;
SrcIter ssend = s + hbound; SrcIter ssend = s + hbound;
for(; ss <= ssend; ++ss, --k) for(; ss <= ssend; ++ss, --k)
{ {
sum += *k * src(ss); sum = TmpType(sum + *k * src(ss));
} }
} }
dest.set(sum, d); dest.set(sum, d);
} }
} }
template <class Kernel, class MapCoordinate, class KernelArray> template <class Kernel, class MapCoordinate, class KernelArray>
void void
createResamplingKernels(Kernel const & kernel, createResamplingKernels(Kernel const & kernel,
skipping to change at line 806 skipping to change at line 804
double centerValue = 0.4) double centerValue = 0.4)
{ {
vigra_precondition(0.25 <= centerValue && centerValue <= 0.5, vigra_precondition(0.25 <= centerValue && centerValue <= 0.5,
"pyramidReduceBurtFilter(): centerValue must be between 0.25 a nd 0.5."); "pyramidReduceBurtFilter(): centerValue must be between 0.25 a nd 0.5.");
int wold = slr.x - sul.x; int wold = slr.x - sul.x;
int wnew = dlr.x - dul.x; int wnew = dlr.x - dul.x;
int hold = slr.y - sul.y; int hold = slr.y - sul.y;
int hnew = dlr.y - dul.y; int hnew = dlr.y - dul.y;
vigra_precondition(wnew == (wold + 1) / 2 && hnew == (hold + 1) / 2,
"pyramidReduceBurtFilter(): oldSize = ceil(newSize / 2) required.");
vigra_precondition(wnew == (wold + 1) / 2 && hnew == (hold + 1) / 2,
"pyramidReduceBurtFilter(): oldSize = ceil(newSize / 2) required.");
Rational<int> samplingRatio(1,2), offset(0); Rational<int> samplingRatio(1,2), offset(0);
resampling_detail::MapTargetToSourceCoordinate mapCoordinate(samplingRa tio, offset); resampling_detail::MapTargetToSourceCoordinate mapCoordinate(samplingRa tio, offset);
ArrayVector<Kernel1D<double> > kernels(1); ArrayVector<Kernel1D<double> > kernels(1);
kernels[0].initExplicitly(-2, 2) = 0.25 - centerValue / 2.0, 0.25, cent erValue, 0.25, 0.25 - centerValue / 2.0; kernels[0].initExplicitly(-2, 2) = 0.25 - centerValue / 2.0, 0.25, cent erValue, 0.25, 0.25 - centerValue / 2.0;
typedef typename typedef typename
NumericTraits<typename SrcAccessor::value_type>::RealPromote NumericTraits<typename SrcAccessor::value_type>::RealPromote
TmpType; TmpType;
typedef BasicImage<TmpType> TmpImage; typedef BasicImage<TmpType> TmpImage;
skipping to change at line 923 skipping to change at line 927
double centerValue = 0.4) double centerValue = 0.4)
{ {
vigra_precondition(0.25 <= centerValue && centerValue <= 0.5, vigra_precondition(0.25 <= centerValue && centerValue <= 0.5,
"pyramidExpandBurtFilter(): centerValue must be between 0.25 a nd 0.5."); "pyramidExpandBurtFilter(): centerValue must be between 0.25 a nd 0.5.");
int wold = slr.x - sul.x; int wold = slr.x - sul.x;
int wnew = dlr.x - dul.x; int wnew = dlr.x - dul.x;
int hold = slr.y - sul.y; int hold = slr.y - sul.y;
int hnew = dlr.y - dul.y; int hnew = dlr.y - dul.y;
vigra_precondition(wold == (wnew + 1) / 2 && hold == (hnew + 1) / 2,
"pyramidExpandBurtFilter(): oldSize = ceil(newSize / 2) required.");
vigra_precondition(wold == (wnew + 1) / 2 && hold == (hnew + 1) / 2,
"pyramidExpandBurtFilter(): oldSize = ceil(newSize / 2) required.");
Rational<int> samplingRatio(2), offset(0); Rational<int> samplingRatio(2), offset(0);
resampling_detail::MapTargetToSourceCoordinate mapCoordinate(samplingRa tio, offset); resampling_detail::MapTargetToSourceCoordinate mapCoordinate(samplingRa tio, offset);
ArrayVector<Kernel1D<double> > kernels(2); ArrayVector<Kernel1D<double> > kernels(2);
kernels[0].initExplicitly(-1, 1) = 0.5 - centerValue, 2.0*centerValue, 0.5 - centerValue; kernels[0].initExplicitly(-1, 1) = 0.5 - centerValue, 2.0*centerValue, 0.5 - centerValue;
kernels[1].initExplicitly(-1, 0) = 0.5, 0.5; kernels[1].initExplicitly(-1, 0) = 0.5, 0.5;
typedef typename typedef typename
NumericTraits<typename SrcAccessor::value_type>::RealPromote NumericTraits<typename SrcAccessor::value_type>::RealPromote
TmpType; TmpType;
 End of changes. 7 change blocks. 
5 lines changed or deleted 15 lines changed or added


 resizeimage.hxx   resizeimage.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2004 by Ullrich Koethe */ /* Copyright 1998-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 170 skipping to change at line 168
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void void
resizeLineNoInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as, resizeLineNoInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
DestIterator id, DestIterator idend, DestAccesso r ad) DestIterator id, DestIterator idend, DestAccesso r ad)
{ {
int wold = iend - i1; int wold = iend - i1;
int wnew = idend - id; int wnew = idend - id;
if((wold <= 1) || (wnew <= 1)) return; // oder error ? if(wnew == 1)
{
ad.set(as(i1), id); ad.set(as(i1), id);
++id; return;
}
--iend, --idend;
ad.set(as(iend), idend);
double dx = (double)(wold - 1) / (wnew - 1); double dx = (double)(wold - 1) / (wnew - 1);
double x = dx; double x = 0.5;
for(; id != idend; ++id, x += dx) for(; id != idend; ++id, x += dx)
{ {
if(x >= 1.0) int ix = (int)x;
{ ad.set(as(i1, ix), id);
int xx = (int)x;
i1 += xx;
x -= (double)xx;
}
ad.set(as(i1), id);
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* resizeImageNoInterpolation */ /* resizeImageNoInterpolation */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Resize image by repeating the nearest pixel values. /** \brief Resize image by repeating the nearest pixel values.
skipping to change at line 350 skipping to change at line 339
resizeLineLinearInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as, resizeLineLinearInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
DestIterator id, DestIterator idend, DestAccesso r ad) DestIterator id, DestIterator idend, DestAccesso r ad)
{ {
int wold = iend - i1; int wold = iend - i1;
int wnew = idend - id; int wnew = idend - id;
if((wold <= 1) || (wnew <= 1)) return; // oder error ? if((wold <= 1) || (wnew <= 1)) return; // oder error ?
typedef typedef
NumericTraits<typename DestAccessor::value_type> DestTraits; NumericTraits<typename DestAccessor::value_type> DestTraits;
typedef typename DestTraits::RealPromote RealPromote;
ad.set(DestTraits::fromRealPromote(as(i1)), id); ad.set(DestTraits::fromRealPromote(as(i1)), id);
++id; ++id;
--iend, --idend; --iend, --idend;
ad.set(DestTraits::fromRealPromote(as(iend)), idend); ad.set(DestTraits::fromRealPromote(as(iend)), idend);
double dx = (double)(wold - 1) / (wnew - 1); double dx = (double)(wold - 1) / (wnew - 1);
double x = dx; double x = dx;
for(; id != idend; ++id, x += dx) for(; id != idend; ++id, x += dx)
{ {
if(x >= 1.0) if(x >= 1.0)
{ {
int xx = (int)x; int xx = (int)x;
i1 += xx; i1 += xx;
x -= (double)xx; x -= (double)xx;
} }
double x1 = 1.0 - x; double x1 = 1.0 - x;
ad.set(DestTraits::fromRealPromote(x1 * as(i1) + x * as(i1, 1)), id ); ad.set(DestTraits::fromRealPromote(RealPromote(x1 * as(i1) + x * as (i1, 1))), id);
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* resizeImageLinearInterpolation */ /* resizeImageLinearInterpolation */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Resize image using linear interpolation. /** \brief Resize image using linear interpolation.
 End of changes. 8 change blocks. 
21 lines changed or deleted 11 lines changed or added


 rfftw.hxx   rfftw.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 rgbvalue.hxx   rgbvalue.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 155 skipping to change at line 153
/** STL-compatible definition of const iterator /** STL-compatible definition of const iterator
*/ */
typedef typename Base::const_iterator const_iterator; typedef typename Base::const_iterator const_iterator;
/** squared norm type (result of squaredManitude()) /** squared norm type (result of squaredManitude())
*/ */
typedef typename Base::SquaredNormType SquaredNormType; typedef typename Base::SquaredNormType SquaredNormType;
/** norm type (result of magnitude()) /** norm type (result of magnitude())
*/ */
typedef typename Base::NormType NormType; typedef typename Base::NormType NormType;
typedef typename Base::reference reference;
typedef typename Base::const_reference const_reference;
typedef typename Base::pointer pointer;
typedef typename Base::const_pointer const_pointer;
typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type;
typedef typename Base::scalar_multiplier scalar_multiplier;
typedef typename Base::ReverseCopyTag ReverseCopyTag;
/** Color index positions /** Color index positions
*/ */
enum enum
{ {
RedIdx = RED_IDX, RedIdx = RED_IDX,
GreenIdx = GREEN_IDX, GreenIdx = GREEN_IDX,
BlueIdx = BLUE_IDX BlueIdx = BLUE_IDX
}; };
/** Construct from explicit color values. /** Construct from explicit color values.
\a first, \a second, \a third are written in this order, \a first, \a second, \a third are written in this order,
irrespective of how the color indices are specified. irrespective of how the color indices are specified.
*/ */
RGBValue(value_type first, value_type second, value_type third) RGBValue(value_type first, value_type second, value_type third)
: Base(first, second, third) : Base(first, second, third)
{ {
VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>)); VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
} }
/** Construct gray value /** Construct gray value.
*/ */
RGBValue(value_type gray) RGBValue(value_type gray)
: Base(gray, gray, gray) : Base(gray, gray, gray)
{ {
VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>)); VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
} }
/** Construct from another sequence (must have length 3!) /** Copy from raw memory. The order is preserved,
irrespective of how the color indices are specified.
*/ */
template <class Iterator> explicit RGBValue(const_pointer i)
RGBValue(Iterator i, Iterator end) : Base(i)
: Base(i[0], i[1], i[2]) {
VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX,
BLUE_IDX>));
}
/** Construct by reverse copying from raw memory.
*/
RGBValue(const_pointer i, ReverseCopyTag reverse)
: Base(i, reverse)
{ {
VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>)); VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
} }
/** Default constructor (sets all components to 0) /** Default constructor (sets all components to 0)
*/ */
RGBValue() RGBValue()
: Base(0, 0, 0) : Base(0, 0, 0)
{ {
VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>)); VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
} }
#if !defined(TEMPLATE_COPY_CONSTRUCTOR_BUG) #if !defined(TEMPLATE_COPY_CONSTRUCTOR_BUG)
RGBValue(RGBValue const & r) RGBValue(RGBValue const & r)
: Base(r) : Base((Base const &)r)
{ {
VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>)); VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
} }
RGBValue & operator=(RGBValue const & r) RGBValue & operator=(RGBValue const & r)
{ {
Base::operator=(r); Base::operator=(r);
return *this; return *this;
} }
skipping to change at line 257 skipping to change at line 272
RGBValue & operator=(TinyVector<value_type, 3> const & r) RGBValue & operator=(TinyVector<value_type, 3> const & r)
{ {
Base::operator=(r); Base::operator=(r);
return *this; return *this;
} }
/** Unary negation (construct RGBValue with negative values) /** Unary negation (construct RGBValue with negative values)
*/ */
RGBValue operator-() const RGBValue operator-() const
{ {
return RGBValue(-red(), -green(), -blue()); return RGBValue(-(*this)[0], -(*this)[1], -(*this)[2]);
} }
/** Access red component. /** Access red component.
*/ */
value_type & red() { return (*this)[RED_IDX]; } value_type & red() { return (*this)[RED_IDX]; }
/** Access green component. /** Access green component.
*/ */
value_type & green() { return (*this)[GREEN_IDX]; } value_type & green() { return (*this)[GREEN_IDX]; }
skipping to change at line 509 skipping to change at line 524
{ {
typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promo te; typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promo te;
}; };
template <class T, unsigned int R, unsigned int G, unsigned int B> template <class T, unsigned int R, unsigned int G, unsigned int B>
struct PromoteTraits<double, RGBValue<T, R, G, B> > struct PromoteTraits<double, RGBValue<T, R, G, B> >
{ {
typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promo te; typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promo te;
}; };
template<class T, unsigned int R, unsigned int G, unsigned int B>
struct CanSkipInitialization<RGBValue<T, R, G, B> >
{
typedef typename CanSkipInitialization<T>::type type;
static const bool value = type::asBool;
};
#else // NO_PARTIAL_TEMPLATE_SPECIALIZATION #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
#define RGBVALUE_NUMTRAITS(T) \ #define RGBVALUE_NUMTRAITS(T) \
template<>\ template<>\
struct NumericTraits<RGBValue<T, 0, 1, 2> >\ struct NumericTraits<RGBValue<T, 0, 1, 2> >\
{\ {\
typedef RGBValue<T> Type; \ typedef RGBValue<T> Type; \
typedef RGBValue<NumericTraits<T>::Promote> Promote; \ typedef RGBValue<NumericTraits<T>::Promote> Promote; \
typedef RGBValue<NumericTraits<T>::RealPromote> RealPromote; \ typedef RGBValue<NumericTraits<T>::RealPromote> RealPromote; \
typedef RGBValue<NumericTraits<T>::ComplexPromote> ComplexPromote; \ typedef RGBValue<NumericTraits<T>::ComplexPromote> ComplexPromote; \
skipping to change at line 670 skipping to change at line 692
} }
/// componentwise multiply-assignment /// componentwise multiply-assignment
template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BI DX1, template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BI DX1,
class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BI DX2> class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BI DX2>
inline inline
RGBValue<V1, RIDX1, GIDX1, BIDX1> & RGBValue<V1, RIDX1, GIDX1, BIDX1> &
operator*=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l, operator*=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r) RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
{ {
l.red() *= r.red(); l.red() = V1(l.red() * r.red());
l.green() *= r.green(); l.green() = V1(l.green() * r.green());
l.blue() *= r.blue(); l.blue() = V1(l.blue() * r.blue());
return l; return l;
} }
/// componentwise scalar multiply-assignment /// componentwise scalar multiply-assignment
template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX> template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
inline inline
RGBValue<V, RIDX, GIDX, BIDX> & RGBValue<V, RIDX, GIDX, BIDX> &
operator*=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r) operator*=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r)
{ {
l.red() *= r; l.red() = V(l.red() * r);
l.green() *= r; l.green() = V(l.green() * r);
l.blue() *= r; l.blue() = V(l.blue() * r);
return l;
}
/// componentwise divide-assignment
template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BI
DX1,
class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BI
DX2>
inline
RGBValue<V1, RIDX1, GIDX1, BIDX1> &
operator/=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
{
l.red() = V1(l.red() / r.red());
l.green() = V1(l.green() / r.green());
l.blue() = V1(l.blue() / r.blue());
return l; return l;
} }
/// componentwise scalar divide-assignment /// componentwise scalar divide-assignment
template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX> template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
inline inline
RGBValue<V, RIDX, GIDX, BIDX> & RGBValue<V, RIDX, GIDX, BIDX> &
operator/=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r) operator/=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r)
{ {
l.red() /= r; l.red() = V(l.red() / r);
l.green() /= r; l.green() = V(l.green() / r);
l.blue() /= r; l.blue() = V(l.blue() / r);
return l; return l;
} }
using VIGRA_CSTD::abs; using VIGRA_CSTD::abs;
/// component-wise absolute value /// component-wise absolute value
template <class T, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX> template <class T, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
inline inline
RGBValue<T, RIDX, GIDX, BIDX> RGBValue<T, RIDX, GIDX, BIDX>
abs(RGBValue<T, RIDX, GIDX, BIDX> const & v) abs(RGBValue<T, RIDX, GIDX, BIDX> const & v)
skipping to change at line 785 skipping to change at line 821
typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
operator*(RGBValue<V, R, G, B> const & r, double v) operator*(RGBValue<V, R, G, B> const & r, double v)
{ {
typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r); typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
res *= v; res *= v;
return res; return res;
} }
/// component-wise division
template <class V1, unsigned int R, unsigned int G, unsigned int B, class V
2>
inline
typename PromoteTraits<RGBValue<V1, R, G, B>,
RGBValue<V2, R, G, B> >::Promote
operator/(RGBValue<V1, R, G, B> const & r1,
RGBValue<V2, R, G, B> const & r2)
{
typename PromoteTraits<RGBValue<V1, R, G, B>,
RGBValue<V2, R, G, B> >::Promote res(r1);
res /= r2;
return res;
}
/// component-wise scalar division /// component-wise scalar division
template <class V, unsigned int R, unsigned int G, unsigned int B> template <class V, unsigned int R, unsigned int G, unsigned int B>
inline inline
typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
operator/(RGBValue<V, R, G, B> const & r, double v) operator/(RGBValue<V, R, G, B> const & r, double v)
{ {
typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r); typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
res /= v; res /= v;
 End of changes. 14 change blocks. 
19 lines changed or deleted 75 lines changed or added


 seededregiongrowing.hxx   seededregiongrowing.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2003 by Ullrich Koethe, Hans Meine */ /* Copyright 1998-2010 by Ullrich Koethe, Hans Meine */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 47 skipping to change at line 45
#ifndef VIGRA_SEEDEDREGIONGROWING_HXX #ifndef VIGRA_SEEDEDREGIONGROWING_HXX
#define VIGRA_SEEDEDREGIONGROWING_HXX #define VIGRA_SEEDEDREGIONGROWING_HXX
#include <vector> #include <vector>
#include <stack> #include <stack>
#include <queue> #include <queue>
#include "utilities.hxx" #include "utilities.hxx"
#include "stdimage.hxx" #include "stdimage.hxx"
#include "stdimagefunctions.hxx" #include "stdimagefunctions.hxx"
#include "pixelneighborhood.hxx"
namespace vigra { namespace vigra {
namespace detail { namespace detail {
template <class COST> template <class COST>
class SeedRgPixel class SeedRgPixel
{ {
public: public:
Point2D location_, nearest_; Point2D location_, nearest_;
skipping to change at line 164 skipping to change at line 163
struct UnlabelWatersheds struct UnlabelWatersheds
{ {
int operator()(int label) const int operator()(int label) const
{ {
return label < 0 ? 0 : label; return label < 0 ? 0 : label;
} }
}; };
} // namespace detail } // namespace detail
enum SRGType { KeepContours, CompleteGrow, SRGWatershedLabel = -1 }; enum SRGType { CompleteGrow = 0, KeepContours = 1, StopAtThreshold = 2, SRG WatershedLabel = -1 };
/** \addtogroup SeededRegionGrowing Region Segmentation Algorithms /** \addtogroup SeededRegionGrowing Region Segmentation Algorithms
Region growing, watersheds, and voronoi tesselation Region growing, watersheds, and voronoi tesselation
*/ */
//@{ //@{
/********************************************************/ /********************************************************/
/* */ /* */
/* seededRegionGrowing */ /* seededRegionGrowing */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Region Segmentation by means of Seeded Region Growing. /** \brief Region Segmentation by means of Seeded Region Growing.
This algorithm implements seeded region growing as described in This algorithm implements seeded region growing as described in
R. Adams, L. Bischof: "<em> Seeded Region Growing</em>", IEEE Trans. on Pattern R. Adams, L. Bischof: "<em> Seeded Region Growing</em>", IEEE Trans. on Pattern
Analysis and Maschine Intelligence, vol 16, no 6, 1994, and Analysis and Maschine Intelligence, vol 16, no 6, 1994, and
Ullrich K&ouml;the: Ullrich K&ouml;the:
<em><a href="http://kogs-www.informatik.uni-hamburg.de/~koethe/papers/# primary">Primary Image Segmentation</a></em>, <em><a href="http://hci.iwr.uni-heidelberg.de/people/ukoethe/papers/ind ex.php#cite_primary_segmentation">Primary Image Segmentation</a></em>,
in: G. Sagerer, S. in: G. Sagerer, S.
Posch, F. Kummert (eds.): Mustererkennung 1995, Proc. 17. DAGM-Symposiu m, Posch, F. Kummert (eds.): Mustererkennung 1995, Proc. 17. DAGM-Symposiu m,
Springer 1995 Springer 1995
The seed image is a partly segmented image which contains uniquely The seed image is a partly segmented image which contains uniquely
labeled regions (the seeds) and unlabeled pixels (the candidates, label 0). labeled regions (the seeds) and unlabeled pixels (the candidates, label 0).
Seed regions can be as large as you wish and as small as one pixel. If Seed regions can be as large as you wish and as small as one pixel. If
there are no candidates, the algorithm will simply copy the seed image there are no candidates, the algorithm will simply copy the seed image
into the output image. Otherwise it will aggregate the candidates into into the output image. Otherwise it will aggregate the candidates into
the existing regions so that a cost function is minimized. This the existing regions so that a cost function is minimized.
works as follows: Candidates are taken from the neighborhood of the already assigned pixe
ls,
where the type of neighborhood is determined by parameter <tt>neighborh
ood</tt>
which can take the values <tt>FourNeighborCode()</tt> (the default)
or <tt>EightNeighborCode()</tt>. The algorithm basically works as follo
ws
(illustrated for 4-neighborhood, but 8-neighborhood works in the same w
ay):
<ol> <ol>
<li> Find all candidate pixels that are 4-adjacent to a seed region. <li> Find all candidate pixels that are 4-adjacent to a seed region.
Calculate the cost for aggregating each candidate into its adajacent re gion Calculate the cost for aggregating each candidate into its adajacent re gion
and put the candidates into a priority queue. and put the candidates into a priority queue.
<li> While( priority queue is not empty) <li> While( priority queue is not empty and termination criterion is no t fulfilled)
<ol> <ol>
<li> Take the candidate with least cost from the queue. If it has n ot <li> Take the candidate with least cost from the queue. If it has n ot
already been merged, merge it with it's adjacent region. already been merged, merge it with it's adjacent region.
<li> Put all candidates that are 4-adjacent to the pixel just proce ssed <li> Put all candidates that are 4-adjacent to the pixel just proce ssed
into the priority queue. into the priority queue.
</ol> </ol>
</ol> </ol>
If <tt>SRGType == CompleteGrow</tt> (the default), this algorithm <tt>SRGType</tt> can take the following values:
will produce a complete 4-connected tesselation of the image.
If <tt>SRGType == KeepContours</tt>, a one-pixel-wide border will be le <DL>
ft <DT><tt>CompleteGrow</tt> <DD> produce a complete tesselation of the vo
between the regions. The border pixels get label 0 (zero). lume (default).
<DT><tt>KeepContours</tt> <DD> keep a 1-voxel wide unlabeled contour be
tween all regions.
<DT><tt>StopAtThreshold</tt> <DD> stop when the boundary indicator valu
es exceed the
threshold given by parameter <tt>max_cost</tt>
.
<DT><tt>KeepContours | StopAtThreshold</tt> <DD> keep 1-voxel wide cont
our and stop at given <tt>max_cost</tt>.
</DL>
The cost is determined jointly by the source image and the The cost is determined jointly by the source image and the
region statistics functor. The source image contains feature values for each region statistics functor. The source image contains feature values for each
pixel which will be used by the region statistics functor to calculate and pixel which will be used by the region statistics functor to calculate and
update statistics for each region and to calculate the cost for each update statistics for each region and to calculate the cost for each
candidate. The <TT>RegionStatisticsArray</TT> must be compatible to the candidate. The <TT>RegionStatisticsArray</TT> must be compatible to the
\ref ArrayOfRegionStatistics functor and contains an <em> array</em> of \ref ArrayOfRegionStatistics functor and contains an <em> array</em> of
statistics objects for each region. The indices must correspond to the statistics objects for each region. The indices must correspond to the
labels of the seed regions. The statistics for the initial regions must have labels of the seed regions. The statistics for the initial regions must have
been calculated prior to calling <TT>seededRegionGrowing()</TT> (for ex ample by been calculated prior to calling <TT>seededRegionGrowing()</TT> (for ex ample by
skipping to change at line 244 skipping to change at line 252
For each candidate For each candidate
<TT>x</TT> that is adjacent to region <TT>i</TT>, the algorithm will ca ll <TT>x</TT> that is adjacent to region <TT>i</TT>, the algorithm will ca ll
<TT>stats[i].cost(as(x))</TT> to get the cost (where <TT>x</TT> is a <T T>SrcImageIterator</TT> <TT>stats[i].cost(as(x))</TT> to get the cost (where <TT>x</TT> is a <T T>SrcImageIterator</TT>
and <TT>as</TT> is and <TT>as</TT> is
the SrcAccessor). When a candidate has been merged with a region, the the SrcAccessor). When a candidate has been merged with a region, the
statistics are updated by calling <TT>stats[i].operator()(as(x))</TT>. Since statistics are updated by calling <TT>stats[i].operator()(as(x))</TT>. Since
the <TT>RegionStatisticsArray</TT> is passed by reference, this will ov erwrite the <TT>RegionStatisticsArray</TT> is passed by reference, this will ov erwrite
the original statistics. the original statistics.
If a candidate could be merged into more than one regions with identica l If a candidate could be merged into more than one regions with identica l
cost, the algorithm will favour the nearest region. cost, the algorithm will favour the nearest region. If <tt>StopAtThresh
old</tt> is active,
and the cost of the current candidate at any point in the algorithm exc
eeds the optional
<tt>max_cost</tt> value (which defaults to <tt>NumericTraits<double>::m
ax()</tt>),
region growing is aborted, and all voxels not yet assigned to a region
remain unlabeled.
In some cases, the cost only depends on the feature value of the curren t In some cases, the cost only depends on the feature value of the curren t
pixel. Then the update operation will simply be a no-op, and the <TT>co st()</TT> pixel. Then the update operation will simply be a no-op, and the <TT>co st()</TT>
function returns its argument. This behavior is implemented by the function returns its argument. This behavior is implemented by the
\ref SeedRgDirectValueFunctor. With <tt>SRGType == KeepContours</tt>, \ref SeedRgDirectValueFunctor. With <tt>SRGType == KeepContours</tt>,
this is equivalent to the watershed algorithm. this is equivalent to the watershed algorithm.
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray> class RegionStatisticsArray, class Neighborhood>
void seededRegionGrowing(SrcImageIterator srcul, void
SrcImageIterator srclr, SrcAccessor as, seededRegionGrowing(SrcImageIterator srcul, SrcImageIterator srclr,
SeedImageIterator seedsul, SeedAccessor as SrcAccessor as,
eeds, SeedImageIterator seedsul, SeedAccessor aseeds,
DestImageIterator destul, DestAccessor ad, DestImageIterator destul, DestAccessor ad,
RegionStatisticsArray & stats, RegionStatisticsArray & stats,
SRGType srgType = CompleteGrow); SRGType srgType = CompleteGrow,
Neighborhood neighborhood = FourNeighborCode(),
double max_cost = NumericTraits<double>::max())
;
} }
\endcode \endcode
use argument objects in conjunction with \ref ArgumentObjectFactories : use argument objects in conjunction with \ref ArgumentObjectFactories :
\code \code
namespace vigra { namespace vigra {
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray> class RegionStatisticsArray, class Neighborhood>
void void
seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcA seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcA
ccessor> img1, ccessor> src,
pair<SeedImageIterator, SeedAccessor> img3, pair<SeedImageIterator, SeedAccessor> seeds,
pair<DestImageIterator, DestAccessor> img4, pair<DestImageIterator, DestAccessor> dest,
RegionStatisticsArray & stats, RegionStatisticsArray & stats,
SRGType srgType = CompleteGrow); SRGType srgType = CompleteGrow,
Neighborhood neighborhood = FourNeighborCode(),
double max_cost = NumericTraits<double>::max())
;
} }
\endcode \endcode
<b> Usage:</b> <b> Usage:</b>
<b>\#include</b> \<<a href="seededregiongrowing_8hxx-source.html">vigra /seededregiongrowing.hxx</a>\><br> <b>\#include</b> \<<a href="seededregiongrowing_8hxx-source.html">vigra /seededregiongrowing.hxx</a>\><br>
Namespace: vigra Namespace: vigra
Example: implementation of the voronoi tesselation Example: implementation of the voronoi tesselation
skipping to change at line 353 skipping to change at line 368
dest_accessor.set(seed_accessor(seed_upperleft), dest_upperleft); dest_accessor.set(seed_accessor(seed_upperleft), dest_upperleft);
\endcode \endcode
Further requirements are determined by the <TT>RegionStatisticsArray</T T>. Further requirements are determined by the <TT>RegionStatisticsArray</T T>.
*/ */
doxygen_overloaded_function(template <...> void seededRegionGrowing) doxygen_overloaded_function(template <...> void seededRegionGrowing)
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray> class RegionStatisticsArray, class Neighborhood>
void seededRegionGrowing(SrcImageIterator srcul, void seededRegionGrowing(SrcImageIterator srcul,
SrcImageIterator srclr, SrcAccessor as, SrcImageIterator srclr, SrcAccessor as,
SeedImageIterator seedsul, SeedAccessor aseeds, SeedImageIterator seedsul, SeedAccessor aseeds,
DestImageIterator destul, DestAccessor ad, DestImageIterator destul, DestAccessor ad,
RegionStatisticsArray & stats, RegionStatisticsArray & stats,
const SRGType srgType) SRGType srgType,
Neighborhood,
double max_cost)
{ {
int w = srclr.x - srcul.x; int w = srclr.x - srcul.x;
int h = srclr.y - srcul.y; int h = srclr.y - srcul.y;
int count = 0; int count = 0;
SrcImageIterator isy = srcul, isx = srcul; // iterators for the src im age SrcImageIterator isy = srcul, isx = srcul; // iterators for the src im age
typedef typename RegionStatisticsArray::value_type RegionStatistics; typedef typename RegionStatisticsArray::value_type RegionStatistics;
typedef typename RegionStatistics::cost_type CostType; typedef typename RegionStatistics::cost_type CostType;
typedef detail::SeedRgPixel<CostType> Pixel; typedef detail::SeedRgPixel<CostType> Pixel;
skipping to change at line 389 skipping to change at line 406
IImage::Iterator iry, irx; IImage::Iterator iry, irx;
initImageBorder(destImageRange(regions), 1, SRGWatershedLabel); initImageBorder(destImageRange(regions), 1, SRGWatershedLabel);
copyImage(seedsul, seedsul+Diff2D(w,h), aseeds, ir, regions.accessor()) ; copyImage(seedsul, seedsul+Diff2D(w,h), aseeds, ir, regions.accessor()) ;
// allocate and init memory for the results // allocate and init memory for the results
SeedRgPixelHeap pheap; SeedRgPixelHeap pheap;
int cneighbor; int cneighbor;
static const Diff2D dist[] = { Diff2D(-1,0), Diff2D(0,-1), typedef typename Neighborhood::Direction Direction;
Diff2D(1,0), Diff2D(0,1) }; int directionCount = Neighborhood::DirectionCount;
Point2D pos(0,0); Point2D pos(0,0);
for(isy=srcul, iry=ir, pos.y=0; pos.y<h; for(isy=srcul, iry=ir, pos.y=0; pos.y<h;
++pos.y, ++isy.y, ++iry.y) ++pos.y, ++isy.y, ++iry.y)
{ {
for(isx=isy, irx=iry, pos.x=0; pos.x<w; for(isx=isy, irx=iry, pos.x=0; pos.x<w;
++pos.x, ++isx.x, ++irx.x) ++pos.x, ++isx.x, ++irx.x)
{ {
if(*irx == 0) if(*irx == 0)
{ {
// find candidate pixels for growing and fill heap // find candidate pixels for growing and fill heap
for(int i=0; i<4; i++) for(int i=0; i<directionCount; i++)
{ {
cneighbor = irx[dist[i]]; // cneighbor = irx[dist[i]];
cneighbor = irx[Neighborhood::diff((Direction)i)];
if(cneighbor > 0) if(cneighbor > 0)
{ {
CostType cost = stats[cneighbor].cost(as(isx)); CostType cost = stats[cneighbor].cost(as(isx));
Pixel * pixel = Pixel * pixel =
allocator.create(pos, pos+dist[i], cost, count+ +, cneighbor); allocator.create(pos, pos+Neighborhood::diff((D irection)i), cost, count++, cneighbor);
pheap.push(pixel); pheap.push(pixel);
} }
} }
} }
} }
} }
// perform region growing // perform region growing
while(pheap.size() != 0) while(pheap.size() != 0)
{ {
Pixel * pixel = pheap.top(); Pixel * pixel = pheap.top();
pheap.pop(); pheap.pop();
if((srgType & StopAtThreshold) != 0 && pixel->cost_ > max_cost)
break;
Point2D pos = pixel->location_; Point2D pos = pixel->location_;
Point2D nearest = pixel->nearest_; Point2D nearest = pixel->nearest_;
int lab = pixel->label_; int lab = pixel->label_;
allocator.dismiss(pixel); allocator.dismiss(pixel);
irx = ir + pos; irx = ir + pos;
isx = srcul + pos; isx = srcul + pos;
if(*irx) // already labelled region / watershed? if(*irx) // already labelled region / watershed?
continue; continue;
if(srgType == KeepContours) if((srgType & KeepContours) != 0)
{ {
for(int i=0; i<4; i++) for(int i=0; i<directionCount; i++)
{ {
cneighbor = irx[dist[i]]; cneighbor = irx[Neighborhood::diff((Direction)i)];
if((cneighbor>0) && (cneighbor != lab)) if((cneighbor>0) && (cneighbor != lab))
{ {
lab = SRGWatershedLabel; lab = SRGWatershedLabel;
break; break;
} }
} }
} }
*irx = lab; *irx = lab;
if((srgType != KeepContours) || (lab > 0)) if((srgType & KeepContours) == 0 || lab > 0)
{ {
// update statistics // update statistics
stats[*irx](as(isx)); stats[*irx](as(isx));
// search neighborhood // search neighborhood
// second pass: find new candidate pixels // second pass: find new candidate pixels
for(int i=0; i<4; i++) for(int i=0; i<directionCount; i++)
{ {
if(irx[dist[i]] == 0) if(irx[Neighborhood::diff((Direction)i)] == 0)
{ {
CostType cost = stats[lab].cost(as(isx, dist[i])); CostType cost = stats[lab].cost(as(isx, Neighborhood::d iff((Direction)i)));
Pixel * new_pixel = Pixel * new_pixel =
allocator.create(pos+dist[i], nearest, cost, count+ +, lab); allocator.create(pos+Neighborhood::diff((Direction) i), nearest, cost, count++, lab);
pheap.push(new_pixel); pheap.push(new_pixel);
} }
} }
} }
} }
// write result // write result
transformImage(ir, ir+Point2D(w,h), regions.accessor(), destul, ad, transformImage(ir, ir+Point2D(w,h), regions.accessor(), destul, ad,
detail::UnlabelWatersheds()); detail::UnlabelWatersheds());
} }
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray, class Neighborhood>
inline void
seededRegionGrowing(SrcImageIterator srcul,
SrcImageIterator srclr, SrcAccessor as,
SeedImageIterator seedsul, SeedAccessor aseeds,
DestImageIterator destul, DestAccessor ad,
RegionStatisticsArray & stats,
SRGType srgType,
Neighborhood n)
{
seededRegionGrowing(srcul, srclr, as,
seedsul, aseeds,
destul, ad,
stats, srgType, n, NumericTraits<double>::max());
}
template <class SrcImageIterator, class SrcAccessor,
class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor,
class RegionStatisticsArray>
inline void
seededRegionGrowing(SrcImageIterator srcul,
SrcImageIterator srclr, SrcAccessor as,
SeedImageIterator seedsul, SeedAccessor aseeds,
DestImageIterator destul, DestAccessor ad,
RegionStatisticsArray & stats,
SRGType srgType)
{
seededRegionGrowing(srcul, srclr, as,
seedsul, aseeds,
destul, ad,
stats, srgType, FourNeighborCode());
}
template <class SrcImageIterator, class SrcAccessor,
class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor,
class RegionStatisticsArray> class RegionStatisticsArray>
inline void inline void
seededRegionGrowing(SrcImageIterator srcul, seededRegionGrowing(SrcImageIterator srcul,
SrcImageIterator srclr, SrcAccessor as, SrcImageIterator srclr, SrcAccessor as,
SeedImageIterator seedsul, SeedAccessor aseeds, SeedImageIterator seedsul, SeedAccessor aseeds,
DestImageIterator destul, DestAccessor ad, DestImageIterator destul, DestAccessor ad,
RegionStatisticsArray & stats) RegionStatisticsArray & stats)
{ {
seededRegionGrowing(srcul, srclr, as, seededRegionGrowing(srcul, srclr, as,
seedsul, aseeds, seedsul, aseeds,
destul, ad, destul, ad,
stats, CompleteGrow); stats, CompleteGrow);
} }
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray, class Neighborhood>
inline void
seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor>
img1,
pair<SeedImageIterator, SeedAccessor> img3,
pair<DestImageIterator, DestAccessor> img4,
RegionStatisticsArray & stats,
SRGType srgType,
Neighborhood n,
double max_cost)
{
seededRegionGrowing(img1.first, img1.second, img1.third,
img3.first, img3.second,
img4.first, img4.second,
stats, srgType, n, max_cost);
}
template <class SrcImageIterator, class SrcAccessor,
class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor,
class RegionStatisticsArray, class Neighborhood>
inline void
seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor>
img1,
pair<SeedImageIterator, SeedAccessor> img3,
pair<DestImageIterator, DestAccessor> img4,
RegionStatisticsArray & stats,
SRGType srgType,
Neighborhood n)
{
seededRegionGrowing(img1.first, img1.second, img1.third,
img3.first, img3.second,
img4.first, img4.second,
stats, srgType, n, NumericTraits<double>::max());
}
template <class SrcImageIterator, class SrcAccessor,
class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor,
class RegionStatisticsArray> class RegionStatisticsArray>
inline void inline void
seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img1, seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img1,
pair<SeedImageIterator, SeedAccessor> img3, pair<SeedImageIterator, SeedAccessor> img3,
pair<DestImageIterator, DestAccessor> img4, pair<DestImageIterator, DestAccessor> img4,
RegionStatisticsArray & stats, RegionStatisticsArray & stats,
SRGType srgType) SRGType srgType)
{ {
seededRegionGrowing(img1.first, img1.second, img1.third, seededRegionGrowing(img1.first, img1.second, img1.third,
img3.first, img3.second, img3.first, img3.second,
img4.first, img4.second, img4.first, img4.second,
stats, srgType); stats, srgType, FourNeighborCode());
} }
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray> class RegionStatisticsArray>
inline void inline void
seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img1, seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img1,
pair<SeedImageIterator, SeedAccessor> img3, pair<SeedImageIterator, SeedAccessor> img3,
pair<DestImageIterator, DestAccessor> img4, pair<DestImageIterator, DestAccessor> img4,
 End of changes. 32 change blocks. 
45 lines changed or deleted 156 lines changed or added


 seededregiongrowing3d.hxx   seededregiongrowing3d.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2003-2007 by Kasim Terzic, Christian-Dennis Rahn */ /* Copyright 2003-2007 by Kasim Terzic, Christian-Dennis Rahn */
/* and Ullrich Koethe */ /* and Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 50 skipping to change at line 48
#define VIGRA_SEEDEDREGIONGROWING_3D_HXX #define VIGRA_SEEDEDREGIONGROWING_3D_HXX
#include <vector> #include <vector>
#include <stack> #include <stack>
#include <queue> #include <queue>
#include "utilities.hxx" #include "utilities.hxx"
#include "stdimage.hxx" #include "stdimage.hxx"
#include "stdimagefunctions.hxx" #include "stdimagefunctions.hxx"
#include "seededregiongrowing.hxx" #include "seededregiongrowing.hxx"
#include "multi_pointoperators.hxx" #include "multi_pointoperators.hxx"
#include "voxelneighborhood.hxx"
namespace vigra { namespace vigra {
namespace detail { namespace detail {
template <class COST, class Diff_type> template <class COST, class Diff_type>
class SeedRgVoxel class SeedRgVoxel
{ {
public: public:
Diff_type location_, nearest_; Diff_type location_, nearest_;
skipping to change at line 186 skipping to change at line 185
/** \brief Three-dimensional Region Segmentation by means of Seeded Region Growing. /** \brief Three-dimensional Region Segmentation by means of Seeded Region Growing.
This algorithm implements seeded region growing as described in This algorithm implements seeded region growing as described in
The seed image is a partly segmented multi-dimensional array which cont ains uniquely The seed image is a partly segmented multi-dimensional array which cont ains uniquely
labeled regions (the seeds) and unlabeled voxels (the candidates, label 0). labeled regions (the seeds) and unlabeled voxels (the candidates, label 0).
Seed regions can be as large as you wish and as small as one voxel. If Seed regions can be as large as you wish and as small as one voxel. If
there are no candidates, the algorithm will simply copy the seed array there are no candidates, the algorithm will simply copy the seed array
into the output array. Otherwise it will aggregate the candidates into into the output array. Otherwise it will aggregate the candidates into
the existing regions so that a cost function is minimized. This the existing regions so that a cost function is minimized.
works as follows: Candidates are taken from the neighborhood of the already assigned pixe
ls,
where the type of neighborhood is determined by parameter <tt>neighborh
ood</tt>
which can take the values <tt>NeighborCode3DSix()</tt> (the default)
or <tt>NeighborCode3DTwentySix()</tt>. The algorithm basically works as
follows
(illustrated for 6-neighborhood, but 26-neighborhood works in the same
way):
<ol> <ol>
<li> Find all candidate pixels that are 6-adjacent to a seed region. <li> Find all candidate pixels that are 6-adjacent to a seed region.
Calculate the cost for aggregating each candidate into its adajacent re gion Calculate the cost for aggregating each candidate into its adajacent re gion
and put the candidates into a priority queue. and put the candidates into a priority queue.
<li> While( priority queue is not empty) <li> While( priority queue is not empty)
<ol> <ol>
skipping to change at line 209 skipping to change at line 212
<li> Take the candidate with least cost from the queue. If it has n ot <li> Take the candidate with least cost from the queue. If it has n ot
already been merged, merge it with it's adjacent region. already been merged, merge it with it's adjacent region.
<li> Put all candidates that are 4-adjacent to the pixel just proce ssed <li> Put all candidates that are 4-adjacent to the pixel just proce ssed
into the priority queue. into the priority queue.
</ol> </ol>
</ol> </ol>
If <tt>SRGType == CompleteGrow</tt> (the default), this algorithm will <tt>SRGType</tt> can take the following values:
produce a complete 6-connected tesselation of the array.
Other grow types (such as keeping contours for watersheds) are currentl <DL>
y not <DT><tt>CompleteGrow</tt> <DD> produce a complete tesselation of the vo
supported lume (default).
<DT><tt>KeepContours</tt> <DD> keep a 1-voxel wide unlabeled contour be
tween all regions.
<DT><tt>StopAtThreshold</tt> <DD> stop when the boundary indicator valu
es exceed the
threshold given by parameter <tt>max_cost</tt>
.
<DT><tt>KeepContours | StopAtThreshold</tt> <DD> keep 1-voxel wide cont
our and stop at given <tt>max_cost</tt>.
</DL>
The cost is determined jointly by the source array and the The cost is determined jointly by the source array and the
region statistics functor. The source array contains feature values for each region statistics functor. The source array contains feature values for each
pixel which will be used by the region statistics functor to calculate and pixel which will be used by the region statistics functor to calculate and
update statistics for each region and to calculate the cost for each update statistics for each region and to calculate the cost for each
candidate. The <TT>RegionStatisticsArray</TT> must be compatible to the candidate. The <TT>RegionStatisticsArray</TT> must be compatible to the
\ref ArrayOfRegionStatistics functor and contains an <em> array</em> of \ref ArrayOfRegionStatistics functor and contains an <em> array</em> of
statistics objects for each region. The indices must correspond to the statistics objects for each region. The indices must correspond to the
labels of the seed regions. The statistics for the initial regions must have labels of the seed regions. The statistics for the initial regions must have
been calculated prior to calling <TT>seededRegionGrowing3D()</TT> been calculated prior to calling <TT>seededRegionGrowing3D()</TT>
skipping to change at line 234 skipping to change at line 242
For each candidate For each candidate
<TT>x</TT> that is adjacent to region <TT>i</TT>, the algorithm will ca ll <TT>x</TT> that is adjacent to region <TT>i</TT>, the algorithm will ca ll
<TT>stats[i].cost(as(x))</TT> to get the cost (where <TT>x</TT> is a <T T>SrcImageIterator</TT> <TT>stats[i].cost(as(x))</TT> to get the cost (where <TT>x</TT> is a <T T>SrcImageIterator</TT>
and <TT>as</TT> is and <TT>as</TT> is
the SrcAccessor). When a candidate has been merged with a region, the the SrcAccessor). When a candidate has been merged with a region, the
statistics are updated by calling <TT>stats[i].operator()(as(x))</TT>. Since statistics are updated by calling <TT>stats[i].operator()(as(x))</TT>. Since
the <TT>RegionStatisticsArray</TT> is passed by reference, this will ov erwrite the <TT>RegionStatisticsArray</TT> is passed by reference, this will ov erwrite
the original statistics. the original statistics.
If a candidate could be merged into more than one regions with identica l If a candidate could be merged into more than one regions with identica l
cost, the algorithm will favour the nearest region. If, at any point in cost, the algorithm will favour the nearest region. If <tt>StopAtThresh
the algorithm, old</tt> is active,
the cost of the current candidate exceeds the optional <tt>max_cost</tt and the cost of the current candidate at any point in the algorithm exc
> value (which defaults to eeds the optional
<tt>-1</tt>), region growing is aborted, and all voxels not yet assigne <tt>max_cost</tt> value (which defaults to <tt>NumericTraits<double>::m
d to a region ax()</tt>),
remain unlabeled. region growing is aborted, and all voxels not yet assigned to a region
remain unlabeled.
In some cases, the cost only depends on the feature value of the curren t In some cases, the cost only depends on the feature value of the curren t
voxel. Then the update operation will simply be a no-op, and the <TT>co st()</TT> voxel. Then the update operation will simply be a no-op, and the <TT>co st()</TT>
function returns its argument. This behavior is implemented by the function returns its argument. This behavior is implemented by the
\ref SeedRgDirectValueFunctor. \ref SeedRgDirectValueFunctor.
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
template <class SrcImageIterator, class Diff_type, class SrcAccesso template <class SrcImageIterator, class Shape, class SrcAccessor,
r,
class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor,
class RegionStatisticsArray, class CostThresholdType >
void seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape,
SrcAccessor as,
SeedImageIterator seedsul, SeedAccessor as
eeds,
DestImageIterator destul, DestAccessor ad,
RegionStatisticsArray & stats,
CostThresholdType max_cost = -1.0,
const SRGType srgType == CompleteGrow);
template <class SrcImageIterator, class Diff_type, class SrcAccesso
r,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray> class RegionStatisticsArray, class Neighborhood>
void seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, void
SrcAccessor as, seededRegionGrowing3D(SrcImageIterator srcul, Shape shape, SrcAcces
SeedImageIterator seedsul, SeedAccessor as sor as,
eeds, SeedImageIterator seedsul, SeedAccessor aseed
DestImageIterator destul, DestAccessor ad, s,
RegionStatisticsArray & stats, DestImageIterator destul, DestAccessor ad,
const SRGType srgType == CompleteGrow); RegionStatisticsArray & stats,
SRGType srgType = CompleteGrow,
} Neighborhood neighborhood = NeighborCode3DSix
(),
double max_cost = NumericTraits<double>::max(
));
}
\endcode \endcode
use argument objects in conjunction with \ref ArgumentObjectFactories : use argument objects in conjunction with \ref ArgumentObjectFactories :
\code \code
namespace vigra { namespace vigra {
template <class SrcImageIterator, class Shape, class SrcAccesso template <class SrcImageIterator, class Shape, class SrcAccessor,
r,
class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor,
class RegionStatisticsArray, class CostThresholdType>
void
seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccess
or> img1,
pair<SeedImageIterator, SeedAccessor> img3,
pair<DestImageIterator, DestAccessor> img4,
RegionStatisticsArray & stats,
CostThresholdType max_cost = -1.0,
const SRGType srgType == CompleteGrow);
template <class SrcImageIterator, class Shape, class SrcAccesso
r,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray> class RegionStatisticsArray, class Neighborhood>
void void
seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccess seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor>
or> img1, src,
pair<SeedImageIterator, SeedAccessor> img3, pair<SeedImageIterator, SeedAccessor> seeds,
pair<DestImageIterator, DestAccessor> img4, pair<DestImageIterator, DestAccessor> dest,
RegionStatisticsArray & stats, RegionStatisticsArray & stats,
const SRGType srgType == CompleteGrow); SRGType srgType = CompleteGrow,
Neighborhood neighborhood = NeighborCode3DSix
(),
double max_cost = NumericTraits<double>::max(
));
} }
\endcode \endcode
*/ */
doxygen_overloaded_function(template <...> void seededRegionGrowing3D) doxygen_overloaded_function(template <...> void seededRegionGrowing3D)
template <class SrcImageIterator, class Diff_type, class SrcAccessor, template <class SrcImageIterator, class Diff_type, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray, class CostThresholdType> class RegionStatisticsArray, class Neighborhood>
void seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, void
SrcAccessor as, seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, SrcAccessor
SeedImageIterator seedsul, SeedAccessor aseeds, as,
DestImageIterator destul, DestAccessor ad, SeedImageIterator seedsul, SeedAccessor aseeds,
RegionStatisticsArray & stats, CostThresholdType m DestImageIterator destul, DestAccessor ad,
ax_cost, RegionStatisticsArray & stats,
const SRGType srgType) SRGType srgType,
Neighborhood,
double max_cost)
{ {
SrcImageIterator srclr = srcul + shape; SrcImageIterator srclr = srcul + shape;
//int w = srclr.x - srcul.x; //int w = srclr.x - srcul.x;
int w = shape[0]; int w = shape[0];
//int h = srclr.y - srcul.y; //int h = srclr.y - srcul.y;
int h = shape[1]; int h = shape[1];
//int d = srclr.z - srcul.z; //int d = srclr.z - srcul.z;
int d = shape[2]; int d = shape[2];
int count = 0; int count = 0;
SrcImageIterator isy = srcul, isx = srcul, isz = srcul; // iterators f or the src image SrcImageIterator isy = srcul, isx = srcul, isz = srcul; // iterators f or the src image
typedef typename RegionStatisticsArray::value_type RegionStatistics; typedef typename RegionStatisticsArray::value_type RegionStatistics;
typedef typename PromoteTraits<typename RegionStatistics::cost_type, Co stThresholdType>::Promote CostType; typedef typename PromoteTraits<typename RegionStatistics::cost_type, do uble>::Promote CostType;
typedef detail::SeedRgVoxel<CostType, Diff_type> Voxel; typedef detail::SeedRgVoxel<CostType, Diff_type> Voxel;
typename Voxel::Allocator allocator; typename Voxel::Allocator allocator;
typedef std::priority_queue< Voxel *, typedef std::priority_queue< Voxel *,
std::vector<Voxel *>, std::vector<Voxel *>,
typename Voxel::Compare > SeedRgVoxelHeap ; typename Voxel::Compare > SeedRgVoxelHeap ;
typedef MultiArray<3, int> IVolume; typedef MultiArray<3, int> IVolume;
// copy seed image in an image with border // copy seed image in an image with border
skipping to change at line 351 skipping to change at line 340
IVolume regions(regionshape); IVolume regions(regionshape);
MultiIterator<3,int> ir = regions.traverser_begin(); MultiIterator<3,int> ir = regions.traverser_begin();
ir = ir + Diff_type(1,1,1); ir = ir + Diff_type(1,1,1);
//IVolume::Iterator iry, irx, irz; //IVolume::Iterator iry, irx, irz;
MultiIterator<3,int> iry, irx, irz; MultiIterator<3,int> iry, irx, irz;
//initImageBorder(destImageRange(regions), 1, SRGWatershedLabel); //initImageBorder(destImageRange(regions), 1, SRGWatershedLabel);
initMultiArrayBorder(destMultiArrayRange(regions), 1, SRGWatershedLabel ); initMultiArrayBorder(destMultiArrayRange(regions), 1, SRGWatershedLabel );
copyMultiArray(seedsul, Diff_type(w,h,d), aseeds, ir, AccessorTraits<in t>::default_accessor()/* vigra::StandardValueAccessor<int>*/); copyMultiArray(seedsul, Diff_type(w,h,d), aseeds, ir, AccessorTraits<in t>::default_accessor());
// allocate and init memory for the results // allocate and init memory for the results
SeedRgVoxelHeap pheap; SeedRgVoxelHeap pheap;
int cneighbor; int cneighbor;
#if 0
static const Diff_type dist[] = { Diff_type(-1, 0, 0), Diff_type( 0,-1, 0), static const Diff_type dist[] = { Diff_type(-1, 0, 0), Diff_type( 0,-1, 0),
Diff_type( 1, 0, 0), Diff_type( 0, 1, 0), Diff_type( 1, 0, 0), Diff_type( 0, 1, 0),
Diff_type( 0, 0,-1), Diff_type( 0, 0, 1) }; Diff_type( 0, 0,-1), Diff_type( 0, 0, 1) };
#endif
typedef typename Neighborhood::Direction Direction;
int directionCount = Neighborhood::DirectionCount;
Diff_type pos(0,0,0); Diff_type pos(0,0,0);
for(isz=srcul, irz=ir, pos[2]=0; pos[2]<d; for(isz=srcul, irz=ir, pos[2]=0; pos[2]<d;
pos[2]++, isz.dim2()++, irz.dim2()++) pos[2]++, isz.dim2()++, irz.dim2()++)
{ {
//std::cerr << "Z = " << pos[2] << std::endl; //std::cerr << "Z = " << pos[2] << std::endl;
for(isy=isz, iry=irz, pos[1]=0; pos[1]<h; for(isy=isz, iry=irz, pos[1]=0; pos[1]<h;
pos[1]++, isy.dim1()++, iry.dim1()++) pos[1]++, isy.dim1()++, iry.dim1()++)
skipping to change at line 382 skipping to change at line 376
//std::cerr << "Y = " << pos[1] << std::endl; //std::cerr << "Y = " << pos[1] << std::endl;
for(isx=isy, irx=iry, pos[0]=0; pos[0]<w; for(isx=isy, irx=iry, pos[0]=0; pos[0]<w;
pos[0]++, isx.dim0()++, irx.dim0()++) pos[0]++, isx.dim0()++, irx.dim0()++)
{ {
//std::cerr << "X = " << pos[0] << std::endl; //std::cerr << "X = " << pos[0] << std::endl;
if(*irx == 0) if(*irx == 0)
{ {
// find candidate pixels for growing and fill heap // find candidate pixels for growing and fill heap
for(int i=0; i<6; i++) for(int i=0; i<directionCount; i++)
{ {
cneighbor = *(irx + dist[i]); cneighbor = *(irx + Neighborhood::diff((Direction)i ));
if(cneighbor > 0) if(cneighbor > 0)
{ {
CostType cost = stats[cneighbor].cost(as(isx)); CostType cost = stats[cneighbor].cost(as(isx));
Voxel * voxel = Voxel * voxel =
allocator.create(pos, pos+dist[i], cost, co unt++, cneighbor); allocator.create(pos, pos+Neighborhood::dif f((Direction)i), cost, count++, cneighbor);
pheap.push(voxel); pheap.push(voxel);
} }
} }
} }
} }
} }
} }
// perform region growing // perform region growing
while(pheap.size() != 0) while(pheap.size() != 0)
{ {
Voxel * voxel = pheap.top(); Voxel * voxel = pheap.top();
pheap.pop(); pheap.pop();
if(max_cost > NumericTraits<CostThresholdType>::zero() && voxel->co if((srgType & StopAtThreshold) != 0 && voxel->cost_ > max_cost)
st_ > max_cost) break; break;
Diff_type pos = voxel->location_; Diff_type pos = voxel->location_;
Diff_type nearest = voxel->nearest_; Diff_type nearest = voxel->nearest_;
int lab = voxel->label_; int lab = voxel->label_;
allocator.dismiss(voxel); allocator.dismiss(voxel);
irx = ir + pos; irx = ir + pos;
isx = srcul + pos; isx = srcul + pos;
if(*irx) // already labelled region / watershed? if(*irx) // already labelled region / watershed?
continue; continue;
if(srgType == KeepContours) if((srgType & KeepContours) != 0)
{ {
for(int i=0; i<6; i++) for(int i=0; i<directionCount; i++)
{ {
cneighbor = * (irx + dist[i]); cneighbor = * (irx + Neighborhood::diff((Direction)i));
if((cneighbor>0) && (cneighbor != lab)) if((cneighbor>0) && (cneighbor != lab))
{ {
lab = SRGWatershedLabel; lab = SRGWatershedLabel;
break; break;
} }
} }
} }
*irx = lab; *irx = lab;
if((srgType != KeepContours) || (lab > 0)) if((srgType & KeepContours) == 0 || lab > 0)
{ {
// update statistics // update statistics
stats[*irx](as(isx)); stats[*irx](as(isx));
// search neighborhood // search neighborhood
// second pass: find new candidate pixels // second pass: find new candidate pixels
for(int i=0; i<6; i++) for(int i=0; i<directionCount; i++)
{ {
if(*(irx + dist[i]) == 0) if(*(irx + Neighborhood::diff((Direction)i)) == 0)
{ {
CostType cost = stats[lab].cost(as(isx, dist[i])); CostType cost = stats[lab].cost(as(isx, Neighborhood::d iff((Direction)i)));
Voxel * new_voxel = Voxel * new_voxel =
allocator.create(pos+dist[i], nearest, cost, count+ +, lab); allocator.create(pos+Neighborhood::diff((Direction) i), nearest, cost, count++, lab);
pheap.push(new_voxel); pheap.push(new_voxel);
} }
} }
} }
} }
// write result // write result
transformMultiArray(ir, Diff_type(w,h,d), AccessorTraits<int>::default_ transformMultiArray(ir, Diff_type(w,h,d), AccessorTraits<int>::default_
accessor()/* regions.accessor()*/, destul, ad, accessor(),
detail::UnlabelWatersheds()); destul, ad, detail::UnlabelWatersheds());
}
/*
template <class SrcImageIterator, class SrcAccessor,
class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor,
class RegionStatisticsArray>
inline void
seededRegionGrowing3D(SrcImageIterator srcul,
SrcImageIterator srclr, SrcAccessor as,
SeedImageIterator seedsul, SeedAccessor aseeds,
DestImageIterator destul, DestAccessor ad,
RegionStatisticsArray & stats)
{
seededRegionGrowing3D(srcul, srclr, as,
seedsul, aseeds,
destul, ad,
stats, CompleteGrow);
}*/
/*
template <class SrcImageIterator, class SrcAccessor,
class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor,
class RegionStatisticsArray>
inline void
seededRegionGrowing3D(triple<SrcImageIterator, SrcImageIterator, SrcAccesso
r> img1,
pair<SeedImageIterator, SeedAccessor> img3,
pair<DestImageIterator, DestAccessor> img4,
RegionStatisticsArray & stats,
SRGType srgType)
{
seededRegionGrowing3D(img1.first, img1.second, img1.third,
img3.first, img3.second,
img4.first, img4.second,
stats, srgType);
}
template <class SrcImageIterator, class SrcAccessor,
class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor,
class RegionStatisticsArray>
inline void
seededRegionGrowing3D(triple<SrcImageIterator, SrcImageIterator, SrcAccesso
r> img1,
pair<SeedImageIterator, SeedAccessor> img3,
pair<DestImageIterator, DestAccessor> img4,
RegionStatisticsArray & stats)
{
seededRegionGrowing3D(img1.first, img1.second, img1.third,
img3.first, img3.second,
img4.first, img4.second,
stats, CompleteGrow);
} }
*/
template <class SrcImageIterator, class Diff_type, class SrcAccessor, template <class SrcImageIterator, class Diff_type, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray, class CostThresholdType> class RegionStatisticsArray, class Neighborhood >
void seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, inline void
SrcAccessor as, seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, SrcAccessor
SeedImageIterator seedsul, SeedAccessor aseeds, as,
DestImageIterator destul, DestAccessor ad, SeedImageIterator seedsul, SeedAccessor aseeds,
RegionStatisticsArray & stats, CostThresholdType m DestImageIterator destul, DestAccessor ad,
ax_cost) RegionStatisticsArray & stats, SRGType srgType, Neigh
borhood n)
{ {
seededRegionGrowing3D( srcul, shape, as, seedsul, aseeds, destul, ad, s seededRegionGrowing3D( srcul, shape, as, seedsul, aseeds,
tats, max_cost, CompleteGrow); destul, ad, stats, srgType, n, NumericTraits<dou
ble>::max());
} }
template <class SrcImageIterator, class Diff_type, class SrcAccessor, template <class SrcImageIterator, class Diff_type, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray > class RegionStatisticsArray >
void seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, inline void
SrcAccessor as, seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, SrcAccessor
SeedImageIterator seedsul, SeedAccessor aseeds, as,
DestImageIterator destul, DestAccessor ad, SeedImageIterator seedsul, SeedAccessor aseeds,
RegionStatisticsArray & stats) DestImageIterator destul, DestAccessor ad,
RegionStatisticsArray & stats, SRGType srgType)
{ {
seededRegionGrowing3D( srcul, shape, as, seedsul, aseeds, destul, ad, s seededRegionGrowing3D( srcul, shape, as, seedsul, aseeds,
tats, -1.0, CompleteGrow); destul, ad, stats, srgType, NeighborCode3DSix())
;
} }
template <class SrcImageIterator, class Diff_type, class SrcAccessor, template <class SrcImageIterator, class Diff_type, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray > class RegionStatisticsArray >
void seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, inline void
SrcAccessor as, seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, SrcAccessor
SeedImageIterator seedsul, SeedAccessor aseeds, as,
DestImageIterator destul, DestAccessor ad, SeedImageIterator seedsul, SeedAccessor aseeds,
RegionStatisticsArray & stats, SRGType srgType) DestImageIterator destul, DestAccessor ad,
RegionStatisticsArray & stats)
{ {
seededRegionGrowing3D( srcul, shape, as, seedsul, aseeds, destul, ad, s seededRegionGrowing3D( srcul, shape, as, seedsul, aseeds, destul, ad,
tats, -1.0, srgType); stats, CompleteGrow);
} }
template <class SrcImageIterator, class Shape, class SrcAccessor, template <class SrcImageIterator, class Shape, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray> class RegionStatisticsArray, class Neighborhood>
inline void inline void
seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1, seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1,
pair<SeedImageIterator, SeedAccessor> img3, pair<SeedImageIterator, SeedAccessor> img3,
pair<DestImageIterator, DestAccessor> img4, pair<DestImageIterator, DestAccessor> img4,
RegionStatisticsArray & stats, int max_cost) RegionStatisticsArray & stats,
SRGType srgType, Neighborhood n, double max_cost)
{ {
seededRegionGrowing3D(img1.first, img1.second, img1.third, seededRegionGrowing3D(img1.first, img1.second, img1.third,
img3.first, img3.second, img3.first, img3.second,
img4.first, img4.second, img4.first, img4.second,
stats, max_cost, CompleteGrow); stats, srgType, n, max_cost);
} }
template <class SrcImageIterator, class Shape, class SrcAccessor, template <class SrcImageIterator, class Shape, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray, class CostThresholdType> class RegionStatisticsArray, class Neighborhood>
inline void inline void
seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1, seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1,
pair<SeedImageIterator, SeedAccessor> img3, pair<SeedImageIterator, SeedAccessor> img3,
pair<DestImageIterator, DestAccessor> img4, pair<DestImageIterator, DestAccessor> img4,
RegionStatisticsArray & stats, CostThresholdType max_co RegionStatisticsArray & stats,
st, const SRGType srgType) SRGType srgType, Neighborhood n)
{ {
seededRegionGrowing3D(img1.first, img1.second, img1.third, seededRegionGrowing3D(img1.first, img1.second, img1.third,
img3.first, img3.second, img3.first, img3.second,
img4.first, img4.second, img4.first, img4.second,
stats, max_cost, srgType); stats, srgType, n, NumericTraits<double>::max());
} }
template <class SrcImageIterator, class Shape, class SrcAccessor, template <class SrcImageIterator, class Shape, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray> class RegionStatisticsArray>
inline void inline void
seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1, seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1,
pair<SeedImageIterator, SeedAccessor> img3, pair<SeedImageIterator, SeedAccessor> img3,
pair<DestImageIterator, DestAccessor> img4, pair<DestImageIterator, DestAccessor> img4,
RegionStatisticsArray & stats, const SRGType srgType) RegionStatisticsArray & stats, SRGType srgType)
{ {
seededRegionGrowing3D(img1.first, img1.second, img1.third, seededRegionGrowing3D(img1.first, img1.second, img1.third,
img3.first, img3.second, img3.first, img3.second,
img4.first, img4.second, img4.first, img4.second,
stats, -1.0, srgType); stats, srgType, NeighborCode3DSix());
} }
template <class SrcImageIterator, class Shape, class SrcAccessor, template <class SrcImageIterator, class Shape, class SrcAccessor,
class SeedImageIterator, class SeedAccessor, class SeedImageIterator, class SeedAccessor,
class DestImageIterator, class DestAccessor, class DestImageIterator, class DestAccessor,
class RegionStatisticsArray> class RegionStatisticsArray>
inline void inline void
seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1, seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1,
pair<SeedImageIterator, SeedAccessor> img3, pair<SeedImageIterator, SeedAccessor> img3,
pair<DestImageIterator, DestAccessor> img4, pair<DestImageIterator, DestAccessor> img4,
RegionStatisticsArray & stats) RegionStatisticsArray & stats)
{ {
seededRegionGrowing3D(img1.first, img1.second, img1.third, seededRegionGrowing3D(img1.first, img1.second, img1.third,
img3.first, img3.second, img3.first, img3.second,
img4.first, img4.second, img4.first, img4.second,
stats, -1.0, CompleteGrow); stats);
} }
} // namespace vigra } // namespace vigra
#endif // VIGRA_SEEDEDREGIONGROWING_HXX #endif // VIGRA_SEEDEDREGIONGROWING_HXX
 End of changes. 46 change blocks. 
196 lines changed or deleted 151 lines changed or added


 separableconvolution.hxx   separableconvolution.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 68 skipping to change at line 66
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class KernelIterator, class KernelAccessor> class KernelIterator, class KernelAccessor>
void internalConvolveLineWrap(SrcIterator is, SrcIterator iend, SrcAccessor sa, void internalConvolveLineWrap(SrcIterator is, SrcIterator iend, SrcAccessor sa,
DestIterator id, DestAccessor da, DestIterator id, DestAccessor da,
KernelIterator kernel, KernelAccessor ka, KernelIterator kernel, KernelAccessor ka,
int kleft, int kright) int kleft, int kright)
{ {
// int w = iend - is; // int w = iend - is;
int w = std::distance( is, iend ); int w = std::distance( is, iend );
typedef typename NumericTraits<typename typedef typename PromoteTraits<
SrcAccessor::value_type>::RealPromote SumType; typename SrcAccessor::value_type,
typename KernelAccessor::value_type>::Promote SumType;
SrcIterator ibegin = is; SrcIterator ibegin = is;
for(int x=0; x<w; ++x, ++is, ++id) for(int x=0; x<w; ++x, ++is, ++id)
{ {
KernelIterator ik = kernel + kright; KernelIterator ik = kernel + kright;
SumType sum = NumericTraits<SumType>::zero(); SumType sum = NumericTraits<SumType>::zero();
if(x < kright) if(x < kright)
{ {
skipping to change at line 122 skipping to change at line 121
else else
{ {
SrcIterator iss = is - kright; SrcIterator iss = is - kright;
SrcIterator isend = is + (1 - kleft); SrcIterator isend = is + (1 - kleft);
for(; iss != isend ; --ik, ++iss) for(; iss != isend ; --ik, ++iss)
{ {
sum += ka(ik) * sa(iss); sum += ka(ik) * sa(iss);
} }
} }
da.set(NumericTraits<typename da.set(detail::RequiresExplicitCast<typename
DestAccessor::value_type>::fromRealPromote(sum), id); DestAccessor::value_type>::cast(sum), id);
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* internalConvolveLineClip */ /* internalConvolveLineClip */
/* */ /* */
/********************************************************/ /********************************************************/
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
skipping to change at line 145 skipping to change at line 144
class KernelIterator, class KernelAccessor, class KernelIterator, class KernelAccessor,
class Norm> class Norm>
void internalConvolveLineClip(SrcIterator is, SrcIterator iend, SrcAccessor sa, void internalConvolveLineClip(SrcIterator is, SrcIterator iend, SrcAccessor sa,
DestIterator id, DestAccessor da, DestIterator id, DestAccessor da,
KernelIterator kernel, KernelAccessor ka, KernelIterator kernel, KernelAccessor ka,
int kleft, int kright, Norm norm) int kleft, int kright, Norm norm)
{ {
// int w = iend - is; // int w = iend - is;
int w = std::distance( is, iend ); int w = std::distance( is, iend );
typedef typename NumericTraits<typename typedef typename PromoteTraits<
SrcAccessor::value_type>::RealPromote SumType; typename SrcAccessor::value_type,
typename KernelAccessor::value_type>::Promote SumType;
SrcIterator ibegin = is; SrcIterator ibegin = is;
for(int x=0; x<w; ++x, ++is, ++id) for(int x=0; x<w; ++x, ++is, ++id)
{ {
KernelIterator ik = kernel + kright; KernelIterator ik = kernel + kright;
SumType sum = NumericTraits<SumType>::zero(); SumType sum = NumericTraits<SumType>::zero();
if(x < kright) if(x < kright)
{ {
skipping to change at line 204 skipping to change at line 204
else else
{ {
SrcIterator iss = is + (-kright); SrcIterator iss = is + (-kright);
SrcIterator isend = is + (1 - kleft); SrcIterator isend = is + (1 - kleft);
for(; iss != isend ; --ik, ++iss) for(; iss != isend ; --ik, ++iss)
{ {
sum += ka(ik) * sa(iss); sum += ka(ik) * sa(iss);
} }
} }
da.set(NumericTraits<typename da.set(detail::RequiresExplicitCast<typename
DestAccessor::value_type>::fromRealPromote(sum), id); DestAccessor::value_type>::cast(sum), id);
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* internalConvolveLineReflect */ /* internalConvolveLineReflect */
/* */ /* */
/********************************************************/ /********************************************************/
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class KernelIterator, class KernelAccessor> class KernelIterator, class KernelAccessor>
void internalConvolveLineReflect(SrcIterator is, SrcIterator iend, SrcAcces sor sa, void internalConvolveLineReflect(SrcIterator is, SrcIterator iend, SrcAcces sor sa,
DestIterator id, DestAccessor da, DestIterator id, DestAccessor da,
KernelIterator kernel, KernelAccessor ka, KernelIterator kernel, KernelAccessor ka,
int kleft, int kright) int kleft, int kright)
{ {
// int w = iend - is; // int w = iend - is;
int w = std::distance( is, iend ); int w = std::distance( is, iend );
typedef typename NumericTraits<typename typedef typename PromoteTraits<
SrcAccessor::value_type>::RealPromote SumType; typename SrcAccessor::value_type,
typename KernelAccessor::value_type>::Promote SumType;
SrcIterator ibegin = is; SrcIterator ibegin = is;
for(int x=0; x<w; ++x, ++is, ++id) for(int x=0; x<w; ++x, ++is, ++id)
{ {
KernelIterator ik = kernel + kright; KernelIterator ik = kernel + kright;
SumType sum = NumericTraits<SumType>::zero(); SumType sum = NumericTraits<SumType>::zero();
if(x < kright) if(x < kright)
{ {
skipping to change at line 279 skipping to change at line 280
else else
{ {
SrcIterator iss = is + (-kright); SrcIterator iss = is + (-kright);
SrcIterator isend = is + (1 - kleft); SrcIterator isend = is + (1 - kleft);
for(; iss != isend ; --ik, ++iss) for(; iss != isend ; --ik, ++iss)
{ {
sum += ka(ik) * sa(iss); sum += ka(ik) * sa(iss);
} }
} }
da.set(NumericTraits<typename da.set(detail::RequiresExplicitCast<typename
DestAccessor::value_type>::fromRealPromote(sum), id); DestAccessor::value_type>::cast(sum), id);
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* internalConvolveLineRepeat */ /* internalConvolveLineRepeat */
/* */ /* */
/********************************************************/ /********************************************************/
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class KernelIterator, class KernelAccessor> class KernelIterator, class KernelAccessor>
void internalConvolveLineRepeat(SrcIterator is, SrcIterator iend, SrcAccess or sa, void internalConvolveLineRepeat(SrcIterator is, SrcIterator iend, SrcAccess or sa,
DestIterator id, DestAccessor da, DestIterator id, DestAccessor da,
KernelIterator kernel, KernelAccessor ka, KernelIterator kernel, KernelAccessor ka,
int kleft, int kright) int kleft, int kright)
{ {
// int w = iend - is; // int w = iend - is;
int w = std::distance( is, iend ); int w = std::distance( is, iend );
typedef typename NumericTraits<typename typedef typename PromoteTraits<
SrcAccessor::value_type>::RealPromote SumType; typename SrcAccessor::value_type,
typename KernelAccessor::value_type>::Promote SumType;
SrcIterator ibegin = is; SrcIterator ibegin = is;
for(int x=0; x<w; ++x, ++is, ++id) for(int x=0; x<w; ++x, ++is, ++id)
{ {
KernelIterator ik = kernel + kright; KernelIterator ik = kernel + kright;
SumType sum = NumericTraits<SumType>::zero(); SumType sum = NumericTraits<SumType>::zero();
if(x < kright) if(x < kright)
{ {
skipping to change at line 354 skipping to change at line 356
else else
{ {
SrcIterator iss = is + (-kright); SrcIterator iss = is + (-kright);
SrcIterator isend = is + (1 - kleft); SrcIterator isend = is + (1 - kleft);
for(; iss != isend ; --ik, ++iss) for(; iss != isend ; --ik, ++iss)
{ {
sum += ka(ik) * sa(iss); sum += ka(ik) * sa(iss);
} }
} }
da.set(NumericTraits<typename da.set(detail::RequiresExplicitCast<typename
DestAccessor::value_type>::fromRealPromote(sum), id); DestAccessor::value_type>::cast(sum), id);
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* internalConvolveLineAvoid */ /* internalConvolveLineAvoid */
/* */ /* */
/********************************************************/ /********************************************************/
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class KernelIterator, class KernelAccessor> class KernelIterator, class KernelAccessor>
void internalConvolveLineAvoid(SrcIterator is, SrcIterator iend, SrcAccesso r sa, void internalConvolveLineAvoid(SrcIterator is, SrcIterator iend, SrcAccesso r sa,
DestIterator id, DestAccessor da, DestIterator id, DestAccessor da,
KernelIterator kernel, KernelAccessor ka, KernelIterator kernel, KernelAccessor ka,
int kleft, int kright) int kleft, int kright)
{ {
// int w = iend - is; // int w = iend - is;
int w = std::distance( is, iend ); int w = std::distance( is, iend );
typedef typename NumericTraits<typename typedef typename PromoteTraits<
SrcAccessor::value_type>::RealPromote SumType; typename SrcAccessor::value_type,
typename KernelAccessor::value_type>::Promote SumType;
is += kright; is += kright;
id += kright; id += kright;
for(int x=kright; x<w+kleft; ++x, ++is, ++id) for(int x=kright; x<w+kleft; ++x, ++is, ++id)
{ {
KernelIterator ik = kernel + kright; KernelIterator ik = kernel + kright;
SumType sum = NumericTraits<SumType>::zero(); SumType sum = NumericTraits<SumType>::zero();
SrcIterator iss = is + (-kright); SrcIterator iss = is + (-kright);
SrcIterator isend = is + (1 - kleft); SrcIterator isend = is + (1 - kleft);
for(; iss != isend ; --ik, ++iss) for(; iss != isend ; --ik, ++iss)
{ {
sum += ka(ik) * sa(iss); sum += ka(ik) * sa(iss);
} }
da.set(NumericTraits<typename da.set(detail::RequiresExplicitCast<typename
DestAccessor::value_type>::fromRealPromote(sum), id); DestAccessor::value_type>::cast(sum), id);
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* Separable convolution functions */ /* Separable convolution functions */
/* */ /* */
/********************************************************/ /********************************************************/
/** \addtogroup SeparableConvolution One-dimensional and separable convolut ion functions /** \addtogroup SeparableConvolution One-dimensional and separable convolut ion functions
skipping to change at line 981 skipping to change at line 984
/** Copy constructor. /** Copy constructor.
*/ */
Kernel1D(Kernel1D const & k) Kernel1D(Kernel1D const & k)
: kernel_(k.kernel_), : kernel_(k.kernel_),
left_(k.left_), left_(k.left_),
right_(k.right_), right_(k.right_),
border_treatment_(k.border_treatment_), border_treatment_(k.border_treatment_),
norm_(k.norm_) norm_(k.norm_)
{} {}
/** Construct from kernel with different element type, e.g. double
=> FixedPoint16.
*/
template <class U>
Kernel1D(Kernel1D<U> const & k)
: kernel_(k.center()+k.left(), k.center()+k.right()+1),
left_(k.left()),
right_(k.right()),
border_treatment_(k.borderTreatment()),
norm_(k.norm())
{}
/** Copy assignment. /** Copy assignment.
*/ */
Kernel1D & operator=(Kernel1D const & k) Kernel1D & operator=(Kernel1D const & k)
{ {
if(this != &k) if(this != &k)
{ {
left_ = k.left_; left_ = k.left_;
right_ = k.right_; right_ = k.right_;
border_treatment_ = k.border_treatment_; border_treatment_ = k.border_treatment_;
norm_ = k.norm_; norm_ = k.norm_;
skipping to change at line 1678 skipping to change at line 1692
sum += *k; sum += *k;
} }
} }
else else
{ {
unsigned int faculty = 1; unsigned int faculty = 1;
for(unsigned int i = 2; i <= derivativeOrder; ++i) for(unsigned int i = 2; i <= derivativeOrder; ++i)
faculty *= i; faculty *= i;
for(double x = left() + offset; k < kernel_.end(); ++x, ++k) for(double x = left() + offset; k < kernel_.end(); ++x, ++k)
{ {
sum += *k * VIGRA_CSTD::pow(-x, int(derivativeOrder)) / faculty ; sum = TmpType(sum + *k * VIGRA_CSTD::pow(-x, int(derivativeOrde r)) / faculty);
} }
} }
vigra_precondition(sum != NumericTraits<value_type>::zero(), vigra_precondition(sum != NumericTraits<value_type>::zero(),
"Kernel1D<ARITHTYPE>::normalize(): " "Kernel1D<ARITHTYPE>::normalize(): "
"Cannot normalize a kernel with sum = 0"); "Cannot normalize a kernel with sum = 0");
// normalize // normalize
sum = norm / sum; sum = norm / sum;
k = kernel_.begin(); k = kernel_.begin();
for(; k != kernel_.end(); ++k) for(; k != kernel_.end(); ++k)
skipping to change at line 1707 skipping to change at line 1721
template <class ARITHTYPE> template <class ARITHTYPE>
void Kernel1D<ARITHTYPE>::initGaussian(double std_dev, void Kernel1D<ARITHTYPE>::initGaussian(double std_dev,
value_type norm) value_type norm)
{ {
vigra_precondition(std_dev >= 0.0, vigra_precondition(std_dev >= 0.0,
"Kernel1D::initGaussian(): Standard deviation must be >= 0.") ; "Kernel1D::initGaussian(): Standard deviation must be >= 0.") ;
if(std_dev > 0.0) if(std_dev > 0.0)
{ {
Gaussian<ARITHTYPE> gauss(std_dev); Gaussian<ARITHTYPE> gauss((ARITHTYPE)std_dev);
// first calculate required kernel sizes // first calculate required kernel sizes
int radius = (int)(3.0 * std_dev + 0.5); int radius = (int)(3.0 * std_dev + 0.5);
if(radius == 0) if(radius == 0)
radius = 1; radius = 1;
// allocate the kernel // allocate the kernel
kernel_.erase(kernel_.begin(), kernel_.end()); kernel_.erase(kernel_.begin(), kernel_.end());
kernel_.reserve(radius*2+1); kernel_.reserve(radius*2+1);
for(ARITHTYPE x = -radius; x <= radius; ++x) for(ARITHTYPE x = -(ARITHTYPE)radius; x <= (ARITHTYPE)radius; ++x)
{ {
kernel_.push_back(gauss(x)); kernel_.push_back(gauss(x));
} }
left_ = -radius; left_ = -radius;
right_ = radius; right_ = radius;
} }
else else
{ {
kernel_.erase(kernel_.begin(), kernel_.end()); kernel_.erase(kernel_.begin(), kernel_.end());
kernel_.push_back(1.0); kernel_.push_back(1.0);
skipping to change at line 1833 skipping to change at line 1847
if(order == 0) if(order == 0)
{ {
initGaussian(std_dev, norm); initGaussian(std_dev, norm);
return; return;
} }
vigra_precondition(std_dev > 0.0, vigra_precondition(std_dev > 0.0,
"Kernel1D::initGaussianDerivative(): " "Kernel1D::initGaussianDerivative(): "
"Standard deviation must be > 0."); "Standard deviation must be > 0.");
Gaussian<ARITHTYPE> gauss(std_dev, order); Gaussian<ARITHTYPE> gauss((ARITHTYPE)std_dev, order);
// first calculate required kernel sizes // first calculate required kernel sizes
int radius = (int)(3.0 * std_dev + 0.5 * order + 0.5); int radius = (int)(3.0 * std_dev + 0.5 * order + 0.5);
if(radius == 0) if(radius == 0)
radius = 1; radius = 1;
// allocate the kernels // allocate the kernels
kernel_.clear(); kernel_.clear();
kernel_.reserve(radius*2+1); kernel_.reserve(radius*2+1);
// fill the kernel and calculate the DC component // fill the kernel and calculate the DC component
// introduced by truncation of the Gaussian // introduced by truncation of the Gaussian
ARITHTYPE dc = 0.0; ARITHTYPE dc = 0.0;
for(ARITHTYPE x = -radius; x <= radius; ++x) for(ARITHTYPE x = -(ARITHTYPE)radius; x <= (ARITHTYPE)radius; ++x)
{ {
kernel_.push_back(gauss(x)); kernel_.push_back(gauss(x));
dc += kernel_[kernel_.size()-1]; dc += kernel_[kernel_.size()-1];
} }
dc /= (2.0*radius + 1.0); dc = ARITHTYPE(dc / (2.0*radius + 1.0));
// remove DC, but only if kernel correction is permitted by a non-zero // remove DC, but only if kernel correction is permitted by a non-zero
// value for norm // value for norm
if(norm != 0.0) if(norm != 0.0)
{ {
for(unsigned int i=0; i < kernel_.size(); ++i) for(unsigned int i=0; i < kernel_.size(); ++i)
{ {
kernel_[i] -= dc; kernel_[i] -= dc;
} }
} }
skipping to change at line 1888 skipping to change at line 1902
template <class ARITHTYPE> template <class ARITHTYPE>
void void
Kernel1D<ARITHTYPE>::initBinomial(int radius, Kernel1D<ARITHTYPE>::initBinomial(int radius,
value_type norm) value_type norm)
{ {
vigra_precondition(radius > 0, vigra_precondition(radius > 0,
"Kernel1D::initBinomial(): Radius must be > 0."); "Kernel1D::initBinomial(): Radius must be > 0.");
// allocate the kernel // allocate the kernel
InternalVector kernel(radius*2+1); InternalVector(radius*2+1).swap(kernel_);
typename InternalVector::iterator x = kernel_.begin() + radius;
int i,j;
for(i=0; i<radius*2+1; ++i) kernel[i] = 0;
// fill kernel // fill kernel
typename InternalVector::iterator x = kernel.begin() + radius; x[radius] = norm;
x[radius] = 1.0; for(int j=radius-1; j>=-radius; --j)
for(j=radius-1; j>=-radius; --j)
{ {
for(i=j; i<radius; ++i) x[j] = 0.5 * x[j+1];
for(int i=j+1; i<radius; ++i)
{ {
x[i] = (x[i] + x[i+1]) / 2.0; x[i] = 0.5 * (x[i] + x[i+1]);
} }
x[radius] /= 2.0; x[radius] *= 0.5;
}
// normalize
kernel_.erase(kernel_.begin(), kernel_.end());
kernel_.reserve(radius*2+1);
for(i=0; i<=radius*2+1; ++i)
{
kernel_.push_back(kernel[i] * norm);
} }
left_ = -radius; left_ = -radius;
right_ = radius; right_ = radius;
norm_ = norm; norm_ = norm;
// best border treatment for Binomial is BORDER_TREATMENT_REFLECT // best border treatment for Binomial is BORDER_TREATMENT_REFLECT
border_treatment_ = BORDER_TREATMENT_REFLECT; border_treatment_ = BORDER_TREATMENT_REFLECT;
} }
skipping to change at line 1961 skipping to change at line 1963
/***********************************************************************/ /***********************************************************************/
template <class ARITHTYPE> template <class ARITHTYPE>
void void
Kernel1D<ARITHTYPE>::initSymmetricDifference(value_type norm) Kernel1D<ARITHTYPE>::initSymmetricDifference(value_type norm)
{ {
kernel_.erase(kernel_.begin(), kernel_.end()); kernel_.erase(kernel_.begin(), kernel_.end());
kernel_.reserve(3); kernel_.reserve(3);
kernel_.push_back(0.5 * norm); kernel_.push_back(ARITHTYPE(0.5 * norm));
kernel_.push_back(0.0 * norm); kernel_.push_back(ARITHTYPE(0.0 * norm));
kernel_.push_back(-0.5 * norm); kernel_.push_back(ARITHTYPE(-0.5 * norm));
left_ = -1; left_ = -1;
right_ = 1; right_ = 1;
norm_ = norm; norm_ = norm;
// best border treatment for symmetric difference is // best border treatment for symmetric difference is
// BORDER_TREATMENT_REFLECT // BORDER_TREATMENT_REFLECT
border_treatment_ = BORDER_TREATMENT_REFLECT; border_treatment_ = BORDER_TREATMENT_REFLECT;
} }
 End of changes. 26 change blocks. 
52 lines changed or deleted 55 lines changed or added


 singular_value_decomposition.hxx   singular_value_decomposition.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2007 by Ullrich Koethe */ /* Copyright 2007 by Ullrich Koethe */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 2 change blocks. 
2 lines changed or deleted 1 lines changed or added


 sized_int.hxx   sized_int.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 42 skipping to change at line 40
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_SIZED_INT_HXX #ifndef VIGRA_SIZED_INT_HXX
#define VIGRA_SIZED_INT_HXX #define VIGRA_SIZED_INT_HXX
#include "metaprogramming.hxx" #include "metaprogramming.hxx"
#include <limits>
#if SHRT_MAX == 0x7FL
# define VIGRA_BITSOF_SHORT 8
#elif SHRT_MAX == 0x7FFFL
# define VIGRA_BITSOF_SHORT 16
#elif SHRT_MAX == 0x7FFFFFFFL
# define VIGRA_BITSOF_SHORT 32
#elif SHRT_MAX > 0xFFFFFFFFL
# define VIGRA_BITSOF_SHORT 64
#else
# define VIGRA_BITSOF_SHORT -1
#endif
#if INT_MAX == 0x7FL
# define VIGRA_BITSOF_INT 8
#elif INT_MAX == 0x7FFFL
# define VIGRA_BITSOF_INT 16
#elif INT_MAX == 0x7FFFFFFFL
# define VIGRA_BITSOF_INT 32
#elif INT_MAX > 0xFFFFFFFFL
# define VIGRA_BITSOF_INT 64
#else
# define VIGRA_BITSOF_INT -1
#endif
#if LONG_MAX == 0x7FL
# define VIGRA_BITSOF_LONG 8
#elif LONG_MAX == 0x7FFFL
# define VIGRA_BITSOF_LONG 16
#elif LONG_MAX == 0x7FFFFFFFL
# define VIGRA_BITSOF_LONG 32
#elif LONG_MAX > 0xFFFFFFFFL
# define VIGRA_BITSOF_LONG 64
#else
# define VIGRA_BITSOF_LONG -1
#endif
#if LLONG_MAX == 0x7FL
# define VIGRA_BITSOF_LONG_LONG 8
#elif LLONG_MAX == 0x7FFFL
# define VIGRA_BITSOF_LONG_LONG 16
#elif LLONG_MAX == 0x7FFFFFFFL
# define VIGRA_BITSOF_LONG_LONG 32
#elif LLONG_MAX > 0xFFFFFFFFL
# define VIGRA_BITSOF_LONG_LONG 64
#else
# define VIGRA_BITSOF_LONG_LONG -1
#endif
namespace vigra { namespace vigra {
class Int_type_not_supported_on_this_platform {}; class Int_type_not_supported_on_this_platform {};
#ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
namespace detail { namespace detail {
template<class T, class NEXT> template<class T, class NEXT>
 End of changes. 4 change blocks. 
3 lines changed or deleted 50 lines changed or added


 slanted_edge_mtf.hxx   slanted_edge_mtf.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2006 by Ullrich Koethe */ /* Copyright 1998-2006 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 278 skipping to change at line 276
void slantedEdgeShadingCorrection(Image & i, unsigned int edgeWidth) void slantedEdgeShadingCorrection(Image & i, unsigned int edgeWidth)
{ {
using namespace functor; using namespace functor;
// after prepareSlantedEdgeInput(), the white region is on the left // after prepareSlantedEdgeInput(), the white region is on the left
// find a plane that approximates the logarithm of the white ROI // find a plane that approximates the logarithm of the white ROI
transformImage(srcImageRange(i), destImage(i), log(Arg1() + Param(1.0)) ); transformImage(srcImageRange(i), destImage(i), log(Arg1() + Param(1.0)) );
unsigned int w = i.width(), unsigned int w = i.width(),
h = i.height(), h = i.height();
s = edgeWidth*h;
Matrix<double> m(3,3), r(3, 1), l(3, 1); Matrix<double> m(3,3), r(3, 1), l(3, 1);
for(unsigned int y = 0; y < h; ++y) for(unsigned int y = 0; y < h; ++y)
{ {
for(unsigned int x = 0; x < edgeWidth; ++x) for(unsigned int x = 0; x < edgeWidth; ++x)
{ {
l(0,0) = x; l(0,0) = x;
l(1,0) = y; l(1,0) = y;
l(2,0) = 1.0; l(2,0) = 1.0;
m += outer(l); m += outer(l);
 End of changes. 4 change blocks. 
5 lines changed or deleted 2 lines changed or added


 splineimageview.hxx   splineimageview.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2004 by Ullrich Koethe */ /* Copyright 1998-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 393 skipping to change at line 391
unsigned int height() const unsigned int height() const
{ return h_; } { return h_; }
/** The size of the image. /** The size of the image.
<tt>0 <= x <= size().x-1</tt> and <tt>0 <= y <= size().y-1</tt> <tt>0 <= x <= size().x-1</tt> and <tt>0 <= y <= size().y-1</tt>
are required for all access functions. are required for all access functions.
*/ */
size_type size() const size_type size() const
{ return size_type(w_, h_); } { return size_type(w_, h_); }
/** The shape of the image.
Same as size(), except for the return type.
*/
TinyVector<unsigned int, 2> shape() const
{ return TinyVector<unsigned int, 2>(w_, h_); }
/** The internal image holding the spline coefficients. /** The internal image holding the spline coefficients.
*/ */
InternalImage const & image() const InternalImage const & image() const
{ {
return image_; return image_;
} }
/** Get the array of polynomial coefficients for the facet containi ng /** Get the array of polynomial coefficients for the facet containi ng
the point <tt>(x, y)</tt>. The array <tt>res</tt> will be resiz ed to the point <tt>(x, y)</tt>. The array <tt>res</tt> will be resiz ed to
dimension <tt>(ORDER+1)x(ORDER+1)</tt>. From these coefficients , the dimension <tt>(ORDER+1)x(ORDER+1)</tt>. From these coefficients , the
skipping to change at line 549 skipping to change at line 553
} }
}; };
template <int i, class ValueType> template <int i, class ValueType>
struct SplineImageViewUnrollLoop2 struct SplineImageViewUnrollLoop2
{ {
template <class Array1, class RowIterator, class Array2> template <class Array1, class RowIterator, class Array2>
static ValueType static ValueType
exec(Array1 k, RowIterator r, Array2 x) exec(Array1 k, RowIterator r, Array2 x)
{ {
return k[i] * r[x[i]] + SplineImageViewUnrollLoop2<i-1, ValueType>: :exec(k, r, x); return ValueType(k[i] * r[x[i]]) + SplineImageViewUnrollLoop2<i-1, ValueType>::exec(k, r, x);
} }
}; };
template <class ValueType> template <class ValueType>
struct SplineImageViewUnrollLoop2<0, ValueType> struct SplineImageViewUnrollLoop2<0, ValueType>
{ {
template <class Array1, class RowIterator, class Array2> template <class Array1, class RowIterator, class Array2>
static ValueType static ValueType
exec(Array1 k, RowIterator r, Array2 x) exec(Array1 k, RowIterator r, Array2 x)
{ {
return k[0] * r[x[0]]; return ValueType(k[0] * r[x[0]]);
} }
}; };
} // namespace detail } // namespace detail
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
void void
SplineImageView<ORDER, VALUETYPE>::calculateIndices(double x, double y) con st SplineImageView<ORDER, VALUETYPE>::calculateIndices(double x, double y) con st
{ {
if(x == x_ && y == y_) if(x == x_ && y == y_)
skipping to change at line 642 skipping to change at line 646
unsigned int d, double * con st & c) const unsigned int d, double * con st & c) const
{ {
t += kcenter_; t += kcenter_;
for(int i = 0; i<ksize_; ++i) for(int i = 0; i<ksize_; ++i)
c[i] = k_(t-i, d); c[i] = k_(t-i, d);
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::convolve() const VALUETYPE SplineImageView<ORDER, VALUETYPE>::convolve() const
{ {
InternalValue sum; typedef typename NumericTraits<VALUETYPE>::RealPromote RealPromote;
sum = ky_[0]*detail::SplineImageViewUnrollLoop2<ORDER, InternalValue>:: RealPromote sum;
exec(kx_, image_.rowBegin(iy_[0]), ix_); sum = RealPromote(
ky_[0]*detail::SplineImageViewUnrollLoop2<ORDER, RealPromote>::exec(k
x_, image_.rowBegin(iy_[0]), ix_));
for(int j=1; j<ksize_; ++j) for(int j=1; j<ksize_; ++j)
{ {
sum += ky_[j]*detail::SplineImageViewUnrollLoop2<ORDER, InternalVal sum += RealPromote(
ue>::exec(kx_, image_.rowBegin(iy_[j]), ix_); ky_[j]*detail::SplineImageViewUnrollLoop2<ORDER, RealPromote>::ex
ec(kx_, image_.rowBegin(iy_[j]), ix_));
} }
return NumericTraits<VALUETYPE>::fromRealPromote(sum); return detail::RequiresExplicitCast<VALUETYPE>::cast(sum);
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
template <class Array> template <class Array>
void void
SplineImageView<ORDER, VALUETYPE>::coefficientArray(double x, double y, Arr ay & res) const SplineImageView<ORDER, VALUETYPE>::coefficientArray(double x, double y, Arr ay & res) const
{ {
typename Spline::WeightMatrix & weights = Spline::weights(); typename Spline::WeightMatrix & weights = Spline::weights();
InternalValue tmp[ksize_][ksize_]; double tmp[ksize_][ksize_];
calculateIndices(x, y); calculateIndices(x, y);
for(int j=0; j<ksize_; ++j) for(int j=0; j<ksize_; ++j)
{ {
for(int i=0; i<ksize_; ++i) for(int i=0; i<ksize_; ++i)
{ {
tmp[i][j] = 0.0; tmp[i][j] = 0.0;
for(int k=0; k<ksize_; ++k) for(int k=0; k<ksize_; ++k)
{ {
tmp[i][j] += weights[i][k]*image_(ix_[k], iy_[j]); tmp[i][j] += weights[i][k]*image_(ix_[k], iy_[j]);
skipping to change at line 714 skipping to change at line 721
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2(double x, double y) const VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2(double x, double y) const
{ {
return sq(dx(x,y)) + sq(dy(x,y)); return sq(dx(x,y)) + sq(dy(x,y));
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2x(double x, double y) const VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2x(double x, double y) const
{ {
return 2.0*(dx(x,y) * dxx(x,y) + dy(x,y) * dxy(x,y)); return VALUETYPE(2.0)*(dx(x,y) * dxx(x,y) + dy(x,y) * dxy(x,y));
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2y(double x, double y) const VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2y(double x, double y) const
{ {
return 2.0*(dx(x,y) * dxy(x,y) + dy(x,y) * dyy(x,y)); return VALUETYPE(2.0)*(dx(x,y) * dxy(x,y) + dy(x,y) * dyy(x,y));
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2xx(double x, double y) const VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2xx(double x, double y) const
{ {
return 2.0*(sq(dxx(x,y)) + dx(x,y) * dx3(x,y) + sq(dxy(x,y)) + dy(x,y) * dxxy(x,y)); return VALUETYPE(2.0)*(sq(dxx(x,y)) + dx(x,y) * dx3(x,y) + sq(dxy(x,y)) + dy(x,y) * dxxy(x,y));
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2yy(double x, double y) const VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2yy(double x, double y) const
{ {
return 2.0*(sq(dxy(x,y)) + dx(x,y) * dxyy(x,y) + sq(dyy(x,y)) + dy(x,y) * dy3(x,y)); return VALUETYPE(2.0)*(sq(dxy(x,y)) + dx(x,y) * dxyy(x,y) + sq(dyy(x,y) ) + dy(x,y) * dy3(x,y));
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2xy(double x, double y) const VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2xy(double x, double y) const
{ {
return 2.0*(dx(x,y) * dxxy(x,y) + dy(x,y) * dxyy(x,y) + dxy(x,y) * (dxx (x,y) + dyy(x,y))); return VALUETYPE(2.0)*(dx(x,y) * dxxy(x,y) + dy(x,y) * dxyy(x,y) + dxy( x,y) * (dxx(x,y) + dyy(x,y)));
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* SplineImageView0 */ /* SplineImageView0 */
/* */ /* */
/********************************************************/ /********************************************************/
template <class VALUETYPE, class INTERNAL_INDEXER> template <class VALUETYPE, class INTERNAL_INDEXER>
class SplineImageView0Base class SplineImageView0Base
{ {
skipping to change at line 947 skipping to change at line 954
unsigned int width() const unsigned int width() const
{ return w_; } { return w_; }
unsigned int height() const unsigned int height() const
{ return h_; } { return h_; }
size_type size() const size_type size() const
{ return size_type(w_, h_); } { return size_type(w_, h_); }
TinyVector<unsigned int, 2> shape() const
{ return TinyVector<unsigned int, 2>(w_, h_); }
template <class Array> template <class Array>
void coefficientArray(double x, double y, Array & res) const void coefficientArray(double x, double y, Array & res) const
{ {
res.resize(1, 1); res.resize(1, 1);
res(0, 0) = operator()(x,y); res(0, 0) = operator()(x,y);
} }
bool isInsideX(double x) const bool isInsideX(double x) const
{ {
return x >= 0.0 && x <= width() - 1.0; return x >= 0.0 && x <= width() - 1.0;
skipping to change at line 971 skipping to change at line 981
return y >= 0.0 && y <= height() - 1.0; return y >= 0.0 && y <= height() - 1.0;
} }
bool isInside(double x, double y) const bool isInside(double x, double y) const
{ {
return isInsideX(x) && isInsideY(y); return isInsideX(x) && isInsideY(y);
} }
bool isValid(double x, double y) const bool isValid(double x, double y) const
{ {
return x < 2.0*w_-2.0 && x > -w_+1.0 && y < 2.0*h_-2.0 && y > -h_+1 .0; return x < 2.0*w_-2.0 && x > 1.0-w_ && y < 2.0*h_-2.0 && y > 1.0-h_ ;
} }
bool sameFacet(double x0, double y0, double x1, double y1) const bool sameFacet(double x0, double y0, double x1, double y1) const
{ {
x0 = VIGRA_CSTD::floor(x0 + 0.5); x0 = VIGRA_CSTD::floor(x0 + 0.5);
y0 = VIGRA_CSTD::floor(y0 + 0.5); y0 = VIGRA_CSTD::floor(y0 + 0.5);
x1 = VIGRA_CSTD::floor(x1 + 0.5); x1 = VIGRA_CSTD::floor(x1 + 0.5);
y1 = VIGRA_CSTD::floor(y1 + 0.5); y1 = VIGRA_CSTD::floor(y1 + 0.5);
return x0 == x1 && y0 == y1; return x0 == x1 && y0 == y1;
} }
skipping to change at line 1336 skipping to change at line 1346
int iy = (int)std::floor(y); int iy = (int)std::floor(y);
if(iy == (int)h_ - 1) if(iy == (int)h_ - 1)
--iy; --iy;
double ty = y - iy; double ty = y - iy;
switch(dx) switch(dx)
{ {
case 0: case 0:
switch(dy) switch(dy)
{ {
case 0: case 0:
return NumericTraits<value_type>::fromRealPromote( return detail::RequiresExplicitCast<value_type>::cast(
(1.0-ty)*((1.0-tx)*internalIndexer_(ix,iy) + tx*internalIndexer_(ix+1,iy)) + (1.0-ty)*((1.0-tx)*internalIndexer_(ix,iy) + tx*internalIndexer_(ix+1,iy)) +
ty *((1.0-tx)*internalIndexer_(ix,iy+1) + t x*internalIndexer_(ix+1,iy+1))); ty *((1.0-tx)*internalIndexer_(ix,iy+1) + t x*internalIndexer_(ix+1,iy+1)));
case 1: case 1:
return NumericTraits<value_type>::fromRealPromote( return detail::RequiresExplicitCast<value_type>::cast(
((1.0-tx)*internalIndexer_(ix,iy+1) + tx*int ernalIndexer_(ix+1,iy+1)) - ((1.0-tx)*internalIndexer_(ix,iy+1) + tx*int ernalIndexer_(ix+1,iy+1)) -
((1.0-tx)*internalIndexer_(ix,iy) + tx*inter nalIndexer_(ix+1,iy))); ((1.0-tx)*internalIndexer_(ix,iy) + tx*inter nalIndexer_(ix+1,iy)));
default: default:
return NumericTraits<VALUETYPE>::zero(); return NumericTraits<VALUETYPE>::zero();
} }
case 1: case 1:
switch(dy) switch(dy)
{ {
case 0: case 0:
return NumericTraits<value_type>::fromRealPromote( return detail::RequiresExplicitCast<value_type>::cast(
(1.0-ty)*(internalIndexer_(ix+1,iy) - intern alIndexer_(ix,iy)) + (1.0-ty)*(internalIndexer_(ix+1,iy) - intern alIndexer_(ix,iy)) +
ty *(internalIndexer_(ix+1,iy+1) - internal Indexer_(ix,iy+1))); ty *(internalIndexer_(ix+1,iy+1) - internal Indexer_(ix,iy+1)));
case 1: case 1:
return detail::RequiresExplicitCast<value_type>::cast( return detail::RequiresExplicitCast<value_type>::cast(
(internalIndexer_(ix+1,iy+1) - internalIndexe r_(ix,iy+1)) - (internalIndexer_(ix+1,iy+1) - internalIndexe r_(ix,iy+1)) -
(internalIndexer_(ix+1,iy) - internalIndexer_ (ix,iy))); (internalIndexer_(ix+1,iy) - internalIndexer_ (ix,iy)));
default: default:
return NumericTraits<VALUETYPE>::zero(); return NumericTraits<VALUETYPE>::zero();
} }
default: default:
skipping to change at line 1513 skipping to change at line 1523
unsigned int width() const unsigned int width() const
{ return w_; } { return w_; }
unsigned int height() const unsigned int height() const
{ return h_; } { return h_; }
size_type size() const size_type size() const
{ return size_type(w_, h_); } { return size_type(w_, h_); }
TinyVector<unsigned int, 2> shape() const
{ return TinyVector<unsigned int, 2>(w_, h_); }
template <class Array> template <class Array>
void coefficientArray(double x, double y, Array & res) const; void coefficientArray(double x, double y, Array & res) const;
void calculateIndices(double x, double y, int & ix, int & iy, int & ix1 , int & iy1) const; void calculateIndices(double x, double y, int & ix, int & iy, int & ix1 , int & iy1) const;
bool isInsideX(double x) const bool isInsideX(double x) const
{ {
return x >= 0.0 && x <= width() - 1.0; return x >= 0.0 && x <= width() - 1.0;
} }
 End of changes. 21 change blocks. 
21 lines changed or deleted 34 lines changed or added


 splines.hxx   splines.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2004 by Ullrich Koethe */ /* Copyright 1998-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 static_assert.hxx   static_assert.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2004-2005 by Ullrich Koethe */ /* Copyright 2004-2005 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 stdconvolution.hxx   stdconvolution.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 60 skipping to change at line 58
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class KernelIterator, class KernelAccessor, class KernelIterator, class KernelAccessor,
class KSumType> class KSumType>
void internalPixelEvaluationByClip(int x, int y, int w, int h, SrcIterator xs, void internalPixelEvaluationByClip(int x, int y, int w, int h, SrcIterator xs,
SrcAccessor src_acc, DestIterator xd, De stAccessor dest_acc, SrcAccessor src_acc, DestIterator xd, De stAccessor dest_acc,
KernelIterator ki, Diff2D kul, Diff2D kl r, KernelAccessor ak, KernelIterator ki, Diff2D kul, Diff2D kl r, KernelAccessor ak,
KSumType norm) KSumType norm)
{ {
typedef typename typedef typename
NumericTraits<typename SrcAccessor::value_type>::RealPromote SumTyp PromoteTraits<typename SrcAccessor::value_type,
e; typename KernelAccessor::value_type>::Promote SumType
typedef ;
NumericTraits<typename DestAccessor::value_type> DestTraits; typedef typename DestAccessor::value_type DestType;
// calculate width and height of the kernel // calculate width and height of the kernel
int kernel_width = klr.x - kul.x + 1; int kernel_width = klr.x - kul.x + 1;
int kernel_height = klr.y - kul.y + 1; int kernel_height = klr.y - kul.y + 1;
SumType sum = NumericTraits<SumType>::zero(); SumType sum = NumericTraits<SumType>::zero();
int xx, yy; int xx, yy;
int x0, y0, x1, y1; int x0, y0, x1, y1;
y0 = (y<klr.y) ? -y : -klr.y; y0 = (y<klr.y) ? -y : -klr.y;
skipping to change at line 100 skipping to change at line 98
KernelIterator xk = yk; KernelIterator xk = yk;
for(xx=0; xx<kernel_width; ++xx, ++xxs.x, --xk.x) for(xx=0; xx<kernel_width; ++xx, ++xxs.x, --xk.x)
{ {
sum += ak(xk) * src_acc(xxs); sum += ak(xk) * src_acc(xxs);
ksum += ak(xk); ksum += ak(xk);
} }
} }
// store average in destination pixel // store average in destination pixel
dest_acc.set(DestTraits::fromRealPromote((norm / ksum) * sum), xd); dest_acc.set(detail::RequiresExplicitCast<DestType>::cast((norm / ksum)
* sum), xd);
} }
#if 0 #if 0
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class KernelIterator, class KernelAccessor> class KernelIterator, class KernelAccessor>
void internalPixelEvaluationByWrapReflectRepeat(int x, int y, int src_width , int src_height, SrcIterator xs, void internalPixelEvaluationByWrapReflectRepeat(int x, int y, int src_width , int src_height, SrcIterator xs,
SrcAccessor src_acc, DestIt erator xd, DestAccessor dest_acc, SrcAccessor src_acc, DestIt erator xd, DestAccessor dest_acc,
KernelIterator ki, Diff2D k ul, Diff2D klr, KernelAccessor ak, KernelIterator ki, Diff2D k ul, Diff2D klr, KernelAccessor ak,
skipping to change at line 482 skipping to change at line 479
vigra_precondition(klr.x >= 0 && klr.y >= 0, vigra_precondition(klr.x >= 0 && klr.y >= 0,
"convolveImage(): coordinates of " "convolveImage(): coordinates of "
"kernel's lower right must be >= 0."); "kernel's lower right must be >= 0.");
// use traits to determine SumType as to prevent possible overflow // use traits to determine SumType as to prevent possible overflow
typedef typename typedef typename
PromoteTraits<typename SrcAccessor::value_type, PromoteTraits<typename SrcAccessor::value_type,
typename KernelAccessor::value_type>::Promote SumType ; typename KernelAccessor::value_type>::Promote SumType ;
typedef typename typedef typename
NumericTraits<typename KernelAccessor::value_type>::RealPromote Ker nelSumType; NumericTraits<typename KernelAccessor::value_type>::RealPromote Ker nelSumType;
typedef typedef typename DestAccessor::value_type DestType;
NumericTraits<typename DestAccessor::value_type> DestTraits;
// calculate width and height of the image // calculate width and height of the image
int w = src_lr.x - src_ul.x; int w = src_lr.x - src_ul.x;
int h = src_lr.y - src_ul.y; int h = src_lr.y - src_ul.y;
// calculate width and height of the kernel // calculate width and height of the kernel
int kernel_width = klr.x - kul.x + 1; int kernel_width = klr.x - kul.x + 1;
int kernel_height = klr.y - kul.y + 1; int kernel_height = klr.y - kul.y + 1;
vigra_precondition(w >= kernel_width && h >= kernel_height, vigra_precondition(w >= kernel_width && h >= kernel_height,
skipping to change at line 549 skipping to change at line 545
typename SrcIterator::row_iterator xxe = xxs + kernel_width ; typename SrcIterator::row_iterator xxe = xxs + kernel_width ;
typename KernelIterator::row_iterator xk = yk.rowIterator( ); typename KernelIterator::row_iterator xk = yk.rowIterator( );
for(; xxs < xxe; ++xxs, --xk) for(; xxs < xxe; ++xxs, --xk)
{ {
sum += ak(xk) * src_acc(xxs); sum += ak(xk) * src_acc(xxs);
} }
} }
// store convolution result in destination pixel // store convolution result in destination pixel
dest_acc.set(DestTraits::fromRealPromote(sum), xd); dest_acc.set(detail::RequiresExplicitCast<DestType>::cast(sum), xd);
} }
} }
if(border == BORDER_TREATMENT_AVOID) if(border == BORDER_TREATMENT_AVOID)
return; // skip processing near the border return; // skip processing near the border
int interiorskip = w + kul.x - klr.x - 1; int interiorskip = w + kul.x - klr.x - 1;
int borderskipx; int borderskipx = 0;
int borderskipy; int borderskipy = 0;
int borderinc; int borderinc = 0;
if(border == BORDER_TREATMENT_REPEAT) if(border == BORDER_TREATMENT_REPEAT)
{ {
borderskipx = 0; borderskipx = 0;
borderskipy = 0; borderskipy = 0;
borderinc = 0; borderinc = 0;
} }
else if(border == BORDER_TREATMENT_REFLECT) else if(border == BORDER_TREATMENT_REFLECT)
{ {
borderskipx = -1; borderskipx = -1;
borderskipy = -1; borderskipy = -1;
skipping to change at line 586 skipping to change at line 582
borderinc = 1; borderinc = 1;
} }
// create iterators for the entire image // create iterators for the entire image
yd = dest_ul; yd = dest_ul;
ys = src_ul; ys = src_ul;
// work on entire image (but skip the already computed points in the lo op) // work on entire image (but skip the already computed points in the lo op)
for(int y = 0; y < h; ++y, ++ys.y, ++yd.y) for(int y = 0; y < h; ++y, ++ys.y, ++yd.y)
{ {
int top = std::max(static_cast<IntBiggest>(-klr.y), int top = int(std::max(static_cast<IntBiggest>(-klr.y),
static_cast<IntBiggest>(src_ul.y - ys.y)); static_cast<IntBiggest>(src_ul.y - ys.y))
int bottom = std::min(static_cast<IntBiggest>(-kul.y), );
static_cast<IntBiggest>(src_lr.y - ys.y - 1)) int bottom = int(std::min(static_cast<IntBiggest>(-kul.y),
; static_cast<IntBiggest>(src_lr.y - ys.y -
1)));
// create x iterators // create x iterators
DestIterator xd(yd); DestIterator xd(yd);
SrcIterator xs(ys); SrcIterator xs(ys);
for(int x = 0; x < w; ++x, ++xs.x, ++xd.x) for(int x = 0; x < w; ++x, ++xs.x, ++xd.x)
{ {
// check if we are away from the border // check if we are away from the border
if(y >= klr.y && y < h+kul.y && x == klr.x) if(y >= klr.y && y < h+kul.y && x == klr.x)
{ {
skipping to change at line 644 skipping to change at line 640
} }
yys = xs + Size2D(0, bottom + borderskipy); yys = xs + Size2D(0, bottom + borderskipy);
yk = ki - Size2D(0, bottom + 1); yk = ki - Size2D(0, bottom + 1);
for(yy = bottom + 1; yy <= -kul.y; ++yy, yys.y += borderinc , --yk.y) for(yy = bottom + 1; yy <= -kul.y; ++yy, yys.y += borderinc , --yk.y)
{ {
internalPixelEvaluationByWrapReflectRepeat(yys.rowItera tor(), src_acc, yk.rowIterator(), ak, internalPixelEvaluationByWrapReflectRepeat(yys.rowItera tor(), src_acc, yk.rowIterator(), ak,
left, right, kul.x, klr.x, borderskipx, borderinc, sum); left, right, kul.x, klr.x, borderskipx, borderinc, sum);
} }
// store convolution result in destination pixel // store convolution result in destination pixel
dest_acc.set(DestTraits::fromRealPromote(sum), xd); dest_acc.set(detail::RequiresExplicitCast<DestType>::cast(s um), xd);
// internalPixelEvaluationByWrapReflectRepeat(x, y, w, h, xs , src_acc, xd, dest_acc, ki, kul, klr, ak, border); // internalPixelEvaluationByWrapReflectRepeat(x, y, w, h, xs , src_acc, xd, dest_acc, ki, kul, klr, ak, border);
} }
} }
} }
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class KernelIterator, class KernelAccessor> class KernelIterator, class KernelAccessor>
skipping to change at line 909 skipping to change at line 905
typename SrcIterator::row_iterator xxend = xxs + kernel_wid th; typename SrcIterator::row_iterator xxend = xxs + kernel_wid th;
typename MaskIterator::row_iterator xxm = yym.rowIterator() ; typename MaskIterator::row_iterator xxm = yym.rowIterator() ;
typename KernelIterator::row_iterator xk = yk.rowIterator( ); typename KernelIterator::row_iterator xk = yk.rowIterator( );
for(xx=0; xxs < xxend; ++xxs, --xk, ++xxm) for(xx=0; xxs < xxend; ++xxs, --xk, ++xxm)
{ {
if(!am(xxm)) continue; if(!am(xxm)) continue;
if(first) if(first)
{ {
sum = ak(xk) * src_acc(xxs); sum = detail::RequiresExplicitCast<SumType>::cast(a k(xk) * src_acc(xxs));
ksum = ak(xk); ksum = ak(xk);
first = false; first = false;
} }
else else
{ {
sum += ak(xk) * src_acc(xxs); sum = detail::RequiresExplicitCast<SumType>::cast(s um + ak(xk) * src_acc(xxs));
ksum += ak(xk); ksum += ak(xk);
} }
} }
} }
// store average in destination pixel // store average in destination pixel
if(!first && if(!first &&
ksum != NumericTraits<KSumType>::zero()) ksum != NumericTraits<KSumType>::zero())
{ {
dest_acc.set(DestTraits::fromRealPromote((norm / ksum) * su dest_acc.set(DestTraits::fromRealPromote(
m), xd); detail::RequiresExplicitCast<SumType>::cast((n
orm / ksum) * sum)), xd);
} }
} }
} }
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class MaskIterator, class MaskAccessor, class MaskIterator, class MaskAccessor,
class KernelIterator, class KernelAccessor> class KernelIterator, class KernelAccessor>
inline inline
skipping to change at line 1230 skipping to change at line 1227
<b> Required Interface:</b> <b> Required Interface:</b>
The kernel's value_type must be a linear algebra. The kernel's value_type must be a linear algebra.
\code \code
vigra::Kernel2D<...>::value_type v; vigra::Kernel2D<...>::value_type v;
v = v * v; v = v * v;
\endcode \endcode
*/ */
void initSeparable(Kernel1D<value_type> & kx, void initSeparable(Kernel1D<value_type> const & kx,
Kernel1D<value_type> & ky) Kernel1D<value_type> const & ky)
{ {
left_ = Diff2D(kx.left(), ky.left()); left_ = Diff2D(kx.left(), ky.left());
right_ = Diff2D(kx.right(), ky.right()); right_ = Diff2D(kx.right(), ky.right());
int w = right_.x - left_.x + 1; int w = right_.x - left_.x + 1;
int h = right_.y - left_.y + 1; int h = right_.y - left_.y + 1;
kernel_.resize(w, h); kernel_.resize(w, h);
norm_ = kx.norm() * ky.norm(); norm_ = kx.norm() * ky.norm();
typedef typename Kernel1D<value_type>::Iterator KIter; typedef typename Kernel1D<value_type>::const_iterator KIter;
typename Kernel1D<value_type>::Accessor ka; typename Kernel1D<value_type>::Accessor ka;
KIter kiy = ky.center() + left_.y; KIter kiy = ky.center() + left_.y;
Iterator iy = center() + left_; Iterator iy = center() + left_;
for(int y=left_.y; y<=right_.y; ++y, ++kiy, ++iy.y) for(int y=left_.y; y<=right_.y; ++y, ++kiy, ++iy.y)
{ {
KIter kix = kx.center() + left_.x; KIter kix = kx.center() + left_.x;
Iterator ix = iy; Iterator ix = iy;
for(int x=left_.x; x<=right_.x; ++x, ++kix, ++ix.x) for(int x=left_.x; x<=right_.x; ++x, ++kix, ++ix.x)
skipping to change at line 1321 skipping to change at line 1318
typename BasicImage<value_type>::iterator iend = kernel_.end(); typename BasicImage<value_type>::iterator iend = kernel_.end();
norm_ = *i; norm_ = *i;
++i; ++i;
for(; i!= iend; ++i) for(; i!= iend; ++i)
{ {
norm_ += *i; norm_ += *i;
} }
} }
/** Init as a 2D Gaussian function with given standard deviation an
d norm.
*/
void initGaussian(double std_dev, value_type norm)
{
Kernel1D<value_type> gauss;
gauss.initGaussian(std_dev, norm);
initSeparable(gauss, gauss);
}
/** Init as a 2D Gaussian function with given standard deviation an
d unit norm.
*/
void initGaussian(double std_dev)
{
initGaussian(std_dev, NumericTraits<value_type>::one());
}
/** Init the 2D kernel as a circular averaging filter. The norm wil l be /** Init the 2D kernel as a circular averaging filter. The norm wil l be
calculated as calculated as
<TT>NumericTraits<value_type>::one() / (number of non-zero kern el values)</TT>. <TT>NumericTraits<value_type>::one() / (number of non-zero kern el values)</TT>.
The kernel's value_type must be a linear space. The kernel's value_type must be a linear space.
<b> Required Interface:</b> <b> Required Interface:</b>
\code \code
value_type v = vigra::NumericTraits<value_type>::one(); value_type v = vigra::NumericTraits<value_type>::one();
 End of changes. 16 change blocks. 
28 lines changed or deleted 45 lines changed or added


 stdimage.hxx   stdimage.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 stdimagefunctions.hxx   stdimagefunctions.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 symmetry.hxx   symmetry.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 203 skipping to change at line 201
int dx = NumericTraits<int>::fromRealPromote(scale * VIGRA_CSTD ::cos(angle)); int dx = NumericTraits<int>::fromRealPromote(scale * VIGRA_CSTD ::cos(angle));
int dy = NumericTraits<int>::fromRealPromote(scale * VIGRA_CSTD ::sin(angle)); int dy = NumericTraits<int>::fromRealPromote(scale * VIGRA_CSTD ::sin(angle));
int xx = x + dx; int xx = x + dx;
int yy = y - dy; int yy = y - dy;
if(xx >= 0 && xx < w && yy >= 0 && yy < h) if(xx >= 0 && xx < w && yy >= 0 && yy < h)
{ {
orientationCounter(xx, yy) += 1; orientationCounter(xx, yy) += 1;
magnitudeAccumulator(xx, yy) += magnitude; magnitudeAccumulator(xx, yy) += detail::RequiresExplicitCas t<TmpType>::cast(magnitude);
} }
xx = x - dx; xx = x - dx;
yy = y + dy; yy = y + dy;
if(xx >= 0 && xx < w && yy >= 0 && yy < h) if(xx >= 0 && xx < w && yy >= 0 && yy < h)
{ {
orientationCounter(xx, yy) -= 1; orientationCounter(xx, yy) -= 1;
magnitudeAccumulator(xx, yy) -= magnitude; magnitudeAccumulator(xx, yy) -= detail::RequiresExplicitCas t<TmpType>::cast(magnitude);
} }
} }
} }
int maxOrientation = 0; int maxOrientation = 0;
TmpType maxMagnitude = NumericTraits<TmpType>::zero(); TmpType maxMagnitude = NumericTraits<TmpType>::zero();
for(y=0; y<h; ++y) for(y=0; y<h; ++y)
{ {
for(int x = 0; x<w; ++x) for(int x = 0; x<w; ++x)
skipping to change at line 241 skipping to change at line 239
if(m > maxMagnitude) if(m > maxMagnitude)
maxMagnitude = m; maxMagnitude = m;
} }
} }
for(y=0; y<h; ++y) for(y=0; y<h; ++y)
{ {
for(int x = 0; x<w; ++x) for(int x = 0; x<w; ++x)
{ {
double o = (double)orientationCounter(x, y) / maxOrientation; double o = (double)orientationCounter(x, y) / maxOrientation;
magnitudeAccumulator(x, y) = o * o * magnitudeAccumulator(x, y) / maxMagnitude; magnitudeAccumulator(x, y) = detail::RequiresExplicitCast<TmpTy pe>::cast(o * o * magnitudeAccumulator(x, y) / maxMagnitude);
} }
} }
gaussianSmoothing(srcImageRange(magnitudeAccumulator), destIter(dul, ad ), 0.25*scale); gaussianSmoothing(srcImageRange(magnitudeAccumulator), destIter(dul, ad ), 0.25*scale);
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline inline
void radialSymmetryTransform( void radialSymmetryTransform(
 End of changes. 6 change blocks. 
6 lines changed or deleted 4 lines changed or added


 tensorutilities.hxx   tensorutilities.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2002-2004 by Ullrich Koethe */ /* Copyright 2002-2004 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 43 skipping to change at line 41
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_TENSORUTILITIES_HXX #ifndef VIGRA_TENSORUTILITIES_HXX
#define VIGRA_TENSORUTILITIES_HXX #define VIGRA_TENSORUTILITIES_HXX
#include <cmath> #include <cmath>
#include "utilities.hxx" #include "utilities.hxx"
#include "mathutil.hxx"
namespace vigra { namespace vigra {
/** \addtogroup TensorImaging Tensor Image Processing /** \addtogroup TensorImaging Tensor Image Processing
*/ */
//@{ //@{
/********************************************************/ /********************************************************/
/* */ /* */
/* vectorToTensor */ /* vectorToTensor */
skipping to change at line 64 skipping to change at line 63
/********************************************************/ /********************************************************/
/** \brief Calculate the tensor (outer) product of a 2D vector with itself. /** \brief Calculate the tensor (outer) product of a 2D vector with itself.
This function is useful to transform vector images into a tensor repres entation This function is useful to transform vector images into a tensor repres entation
that can be used as input to tensor based processing and analysis funct ions that can be used as input to tensor based processing and analysis funct ions
(e.g. tensor smoothing). The imput pixel type must be vectors of length 2, whereas (e.g. tensor smoothing). The imput pixel type must be vectors of length 2, whereas
the output must contain vectors of length 3 which will represent the te nsor components the output must contain vectors of length 3 which will represent the te nsor components
in the order t11, t12 (== t21 due to symmetry), t22. in the order t11, t12 (== t21 due to symmetry), t22.
<b>Note:</b> By default, this function negates the second component of <b>Note:</b> In order to account for the left-handedness of the image c
the vector oordinate system,
in order to turn a left handed vector (the usual resul of convolution, the second tensor component (t12) can be negated by setting <tt>negateC
e.g. a gradient filter, because <tt>y</tt> runs from top to bottom) omponent2 = false</tt>.
into a right handed tensor (as is required by all tensor function in VI Angles will then be interpreted counter-clockwise rather than clockwise
GRA). This . By default,
behavior can be switched off by setting <tt>negateComponent2 = false</t this behavior is switched off.
t>.
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void vectorToTensor(SrcIterator sul, SrcIterator slr, SrcAccessor s rc, void vectorToTensor(SrcIterator sul, SrcIterator slr, SrcAccessor s rc,
DestIterator dul, DestAccessor dest, DestIterator dul, DestAccessor dest,
bool negateComponent2 = true); bool negateComponent2 = false);
} }
\endcode \endcode
use argument objects in conjunction with \ref ArgumentObjectFactories : use argument objects in conjunction with \ref ArgumentObjectFactories :
\code \code
namespace vigra { namespace vigra {
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void vectorToTensor(triple<SrcIterator, SrcIterator, SrcAccessor> s , void vectorToTensor(triple<SrcIterator, SrcIterator, SrcAccessor> s ,
pair<DestIterator, DestAccessor> d, pair<DestIterator, DestAccessor> d,
bool negateComponent2 = true); bool negateComponent2 = false);
} }
\endcode \endcode
<b> Usage:</b> <b> Usage:</b>
<b>\#include</b> \<<a href="tensorutilities_8hxx-source.html">vigra/ten sorutilities.hxx</a>\> <b>\#include</b> \<<a href="tensorutilities_8hxx-source.html">vigra/ten sorutilities.hxx</a>\>
\code \code
FImage img(w,h); FImage img(w,h);
FVector2Image gradient(w,h); FVector2Image gradient(w,h);
skipping to change at line 157 skipping to change at line 155
} }
} }
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline inline
void vectorToTensor(SrcIterator sul, SrcIterator slr, SrcAccessor src, void vectorToTensor(SrcIterator sul, SrcIterator slr, SrcAccessor src,
DestIterator dul, DestAccessor dest) DestIterator dul, DestAccessor dest)
{ {
vectorToTensor(sul, slr, src, dul, dest, true); vectorToTensor(sul, slr, src, dul, dest, false);
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline inline
void vectorToTensor(triple<SrcIterator, SrcIterator, SrcAccessor> s, void vectorToTensor(triple<SrcIterator, SrcIterator, SrcAccessor> s,
pair<DestIterator, DestAccessor> d, pair<DestIterator, DestAccessor> d,
bool negateComponent2) bool negateComponent2)
{ {
vectorToTensor(s.first, s.second, s.third, d.first, d.second, negateCom ponent2); vectorToTensor(s.first, s.second, s.third, d.first, d.second, negateCom ponent2);
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline inline
void vectorToTensor(triple<SrcIterator, SrcIterator, SrcAccessor> s, void vectorToTensor(triple<SrcIterator, SrcIterator, SrcAccessor> s,
pair<DestIterator, DestAccessor> d) pair<DestIterator, DestAccessor> d)
{ {
vectorToTensor(s.first, s.second, s.third, d.first, d.second, true); vectorToTensor(s.first, s.second, s.third, d.first, d.second, false);
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* tensorEigenRepresentation */ /* tensorEigenRepresentation */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Calculate eigen representation of a symmetric 2x2 tensor. /** \brief Calculate eigen representation of a symmetric 2x2 tensor.
This function turns a 3-band image representing the tensor components This function turns a 3-band image representing the tensor components
t11, t12 (== t21 due to symmetry), t22 into the a 3-band image holding the eigen t11, t12 (== t21 due to symmetry), t22 into the a 3-band image holding the eigen
representation e1, e2, and angle, where e1 \> e2. The original tensor m representation e1, e2, and angle, where e1 \> e2. When the tensor is
ust be defined in a left-handed coordinate system (the default on images), the
defined in a right-handed coordinate system, and the angle of the tenso angle will
r will then be given in clockwise orientation, starting at the x-axis. Otherwi
then be given in mathematical positive (counter-clockwise) orientation, se, it
starting will be given in counter-clockwise orientation.
at the x-axis.
<b> Declarations:</b> <b> Declarations:</b>
pass arguments explicitly: pass arguments explicitly:
\code \code
namespace vigra { namespace vigra {
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void tensorEigenRepresentation(SrcIterator sul, SrcIterator slr, Sr cAccessor src, void tensorEigenRepresentation(SrcIterator sul, SrcIterator slr, Sr cAccessor src,
DestIterator dul, DestAccessor dest) ; DestIterator dul, DestAccessor dest) ;
skipping to change at line 254 skipping to change at line 252
{ {
typename SrcIterator::row_iterator s = sul.rowIterator(); typename SrcIterator::row_iterator s = sul.rowIterator();
typename SrcIterator::row_iterator send = s + w; typename SrcIterator::row_iterator send = s + w;
typename DestIterator::row_iterator d = dul.rowIterator(); typename DestIterator::row_iterator d = dul.rowIterator();
for(; s < send; ++s, ++d) for(; s < send; ++s, ++d)
{ {
typedef typename typedef typename
NumericTraits<typename SrcAccessor::component_type>::RealPro mote TmpType; NumericTraits<typename SrcAccessor::component_type>::RealPro mote TmpType;
TmpType d1 = src.getComponent(s,0) + src.getComponent(s,2); TmpType d1 = src.getComponent(s,0) + src.getComponent(s,2);
TmpType d2 = src.getComponent(s,0) - src.getComponent(s,2); TmpType d2 = src.getComponent(s,0) - src.getComponent(s,2);
TmpType d3 = 2.0 * src.getComponent(s,1); TmpType d3 = TmpType(2.0) * src.getComponent(s,1);
TmpType d4 = VIGRA_CSTD::sqrt(sq(d2) + sq(d3)); TmpType d4 = (TmpType)hypot(d2, d3);
dest.setComponent(0.5 * (d1 + d4), d, 0); // large EV dest.setComponent(0.5 * (d1 + d4), d, 0); // large EV
dest.setComponent(0.5 * (d1 - d4), d, 1); // small EV dest.setComponent(0.5 * (d1 - d4), d, 1); // small EV
if(d2==0.0 && d3==0.0) if(d2==0.0 && d3==0.0)
{ {
dest.setComponent(0, d, 2); // orientation dest.setComponent(0, d, 2); // orientation
} }
else else
{ {
dest.setComponent(0.5 * VIGRA_CSTD::atan2(d3, d2), d, 2); / / orientation dest.setComponent(0.5 * VIGRA_CSTD::atan2(d3, d2), d, 2); / / orientation
skipping to change at line 445 skipping to change at line 443
typename SrcIterator::row_iterator send = s + w; typename SrcIterator::row_iterator send = s + w;
typename DestIterator1::row_iterator e = edgeul.rowIterator(); typename DestIterator1::row_iterator e = edgeul.rowIterator();
typename DestIterator2::row_iterator c = cornerul.rowIterator(); typename DestIterator2::row_iterator c = cornerul.rowIterator();
for(; s < send; ++s, ++e, ++c) for(; s < send; ++s, ++e, ++c)
{ {
typedef typename typedef typename
NumericTraits<typename SrcAccessor::component_type>::RealPro mote TmpType; NumericTraits<typename SrcAccessor::component_type>::RealPro mote TmpType;
TmpType d1 = src.getComponent(s,0) + src.getComponent(s,2); TmpType d1 = src.getComponent(s,0) + src.getComponent(s,2);
TmpType d2 = src.getComponent(s,0) - src.getComponent(s,2); TmpType d2 = src.getComponent(s,0) - src.getComponent(s,2);
TmpType d3 = 2.0 * src.getComponent(s,1); TmpType d3 = 2.0 * src.getComponent(s,1);
TmpType d4 = VIGRA_CSTD::sqrt(sq(d2) + sq(d3)); TmpType d4 = (TmpType)hypot(d2, d3);
edge.setComponent(d4, e, 0); // edgeness = difference of EVs edge.setComponent(d4, e, 0); // edgeness = difference of EVs
if(d2 == 0.0 && d3 == 0.0) if(d2 == 0.0 && d3 == 0.0)
{ {
edge.setComponent(0.0, e, 1); // orientation edge.setComponent(0.0, e, 1); // orientation
} }
else else
{ {
edge.setComponent(0.5 * VIGRA_CSTD::atan2(d3, d2), e, 1); / / orientation edge.setComponent(0.5 * VIGRA_CSTD::atan2(d3, d2), e, 1); / / orientation
} }
 End of changes. 12 change blocks. 
25 lines changed or deleted 22 lines changed or added


 tiff.hxx   tiff.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 1251 skipping to change at line 1249
catch(...) catch(...)
{ {
delete[] buf; delete[] buf;
throw; throw;
} }
delete[] buf; delete[] buf;
} }
template <class ImageIterator, class Accessor> template <class ImageIterator, class Accessor>
void void
createUShortScalarTiffImage(ImageIterator upperleft, ImageIterator lowerrig
ht,
Accessor a, TiffImage * tiff)
{
int w = lowerright.x - upperleft.x;
int h = lowerright.y - upperleft.y;
TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 16);
TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
int bufsize = TIFFScanlineSize(tiff);
tdata_t * buf = new tdata_t[bufsize];
ImageIterator ys(upperleft);
try
{
for(int y=0; y<h; ++y, ++ys.y)
{
uint16 * p = (uint16 *)buf;
ImageIterator xs(ys);
for(int x=0; x<w; ++x, ++xs.x)
{
p[x] = a(xs);
}
TIFFWriteScanline(tiff, buf, y);
}
}
catch(...)
{
delete[] buf;
throw;
}
delete[] buf;
}
template <class ImageIterator, class Accessor>
void
createIScalarTiffImage(ImageIterator upperleft, ImageIterator lowerright, createIScalarTiffImage(ImageIterator upperleft, ImageIterator lowerright,
Accessor a, TiffImage * tiff) Accessor a, TiffImage * tiff)
{ {
int w = lowerright.x - upperleft.x; int w = lowerright.x - upperleft.x;
int h = lowerright.y - upperleft.y; int h = lowerright.y - upperleft.y;
TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w); TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w);
TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h); TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h);
TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 32); TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 32);
TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
skipping to change at line 1403 skipping to change at line 1444
template <class ImageIterator, class Accessor> template <class ImageIterator, class Accessor>
static void static void
exec(ImageIterator upperleft, ImageIterator lowerright, exec(ImageIterator upperleft, ImageIterator lowerright,
Accessor a, TiffImage * tiff) Accessor a, TiffImage * tiff)
{ {
createShortScalarTiffImage(upperleft, lowerright, a, tiff); createShortScalarTiffImage(upperleft, lowerright, a, tiff);
} }
}; };
template <> template <>
struct CreateTiffImage<unsigned short>
{
template <class ImageIterator, class Accessor>
static void
exec(ImageIterator upperleft, ImageIterator lowerright,
Accessor a, TiffImage * tiff)
{
createUShortScalarTiffImage(upperleft, lowerright, a, tiff);
}
};
template <>
struct CreateTiffImage<int> struct CreateTiffImage<int>
{ {
template <class ImageIterator, class Accessor> template <class ImageIterator, class Accessor>
static void static void
exec(ImageIterator upperleft, ImageIterator lowerright, exec(ImageIterator upperleft, ImageIterator lowerright,
Accessor a, TiffImage * tiff) Accessor a, TiffImage * tiff)
{ {
createIScalarTiffImage(upperleft, lowerright, a, tiff); createIScalarTiffImage(upperleft, lowerright, a, tiff);
} }
}; };
 End of changes. 5 change blocks. 
3 lines changed or deleted 57 lines changed or added


 tinyvector.hxx   tinyvector.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 46 skipping to change at line 44
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_TINYVECTOR_HXX #ifndef VIGRA_TINYVECTOR_HXX
#define VIGRA_TINYVECTOR_HXX #define VIGRA_TINYVECTOR_HXX
#include <cmath> // abs(double) #include <cmath> // abs(double)
#include <cstdlib> // abs(int) #include <cstdlib> // abs(int)
#include <iosfwd> // ostream #include <iosfwd> // ostream
#include "config.hxx" #include "config.hxx"
#include "error.hxx" #include "error.hxx"
#include "metaprogramming.hxx"
#include "numerictraits.hxx" #include "numerictraits.hxx"
#include "memory.hxx"
#include "mathutil.hxx" #include "mathutil.hxx"
#include "diff2d.hxx"
#ifdef VIGRA_CHECK_BOUNDS
#define VIGRA_ASSERT_INSIDE(diff) \
vigra_precondition(diff >= 0, "Index out of bounds");\
vigra_precondition(diff < SIZE, "Index out of bounds");
#else
#define VIGRA_ASSERT_INSIDE(diff)
#endif
namespace vigra { namespace vigra {
using VIGRA_CSTD::abs; using VIGRA_CSTD::abs;
using VIGRA_CSTD::ceil; using VIGRA_CSTD::ceil;
using VIGRA_CSTD::floor; using VIGRA_CSTD::floor;
template <class V1, int SIZE, class D1, class D2> template <class V1, int SIZE, class D1, class D2>
class TinyVectorBase; class TinyVectorBase;
skipping to change at line 78 skipping to change at line 87
{ \ { \
for(int i=0; i<LEVEL; ++i) \ for(int i=0; i<LEVEL; ++i) \
(left[i]) OPER (right[i]); \ (left[i]) OPER (right[i]); \
} }
#define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \ #define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \
template <class T1, class T2> \ template <class T1, class T2> \
static void NAME(T1 * left, T2 right) \ static void NAME(T1 * left, T2 right) \
{ \ { \
for(int i=0; i<LEVEL; ++i) \ for(int i=0; i<LEVEL; ++i) \
(left[i]) OPER (right); \ (left[i]) = detail::RequiresExplicitCast<T1>::cast((left[i]) OP ER (right)); \
} }
template <int LEVEL> template <int LEVEL>
struct ExecLoop struct ExecLoop
{ {
template <class T1, class T2> template <class T1, class T2>
static void assignCast(T1 * left, T2 const * right) static void assignCast(T1 * left, T2 const * right)
{ {
for(int i=0; i<LEVEL; ++i) for(int i=0; i<LEVEL; ++i)
left[i] = detail::RequiresExplicitCast<T1>::cast(right[i]); left[i] = detail::RequiresExplicitCast<T1>::cast(right[i]);
} }
template <class T1, class T2>
static void reverseAssign(T1 * left, T2 const * right)
{
for(int i=0; i<LEVEL; ++i)
left[i] = right[-i];
}
template <class T1, class T2>
static void assignScalar(T1 * left, T2 right)
{
for(int i=0; i<LEVEL; ++i)
left[i] = detail::RequiresExplicitCast<T1>::cast(right);
}
VIGRA_EXEC_LOOP(assign, =) VIGRA_EXEC_LOOP(assign, =)
VIGRA_EXEC_LOOP(add, +=) VIGRA_EXEC_LOOP(add, +=)
VIGRA_EXEC_LOOP(sub, -=) VIGRA_EXEC_LOOP(sub, -=)
VIGRA_EXEC_LOOP(mul, *=) VIGRA_EXEC_LOOP(mul, *=)
VIGRA_EXEC_LOOP(div, /=)
VIGRA_EXEC_LOOP(neg, = -) VIGRA_EXEC_LOOP(neg, = -)
VIGRA_EXEC_LOOP(abs, = vigra::abs) VIGRA_EXEC_LOOP(abs, = vigra::abs)
VIGRA_EXEC_LOOP(floor, = vigra::floor) VIGRA_EXEC_LOOP(floor, = vigra::floor)
VIGRA_EXEC_LOOP(ceil, = vigra::ceil) VIGRA_EXEC_LOOP(ceil, = vigra::ceil)
VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote) VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
VIGRA_EXEC_LOOP_SCALAR(assignScalar, =) VIGRA_EXEC_LOOP_SCALAR(mulScalar, *)
VIGRA_EXEC_LOOP_SCALAR(mulScalar, *=) VIGRA_EXEC_LOOP_SCALAR(divScalar, /)
VIGRA_EXEC_LOOP_SCALAR(divScalar, /=)
template <class T1, class T2> template <class T1, class T2>
static bool notEqual(T1 const * left, T2 const * right) static bool notEqual(T1 const * left, T2 const * right)
{ {
for(int i=0; i<LEVEL; ++i) for(int i=0; i<LEVEL; ++i)
if(left[i] != right[i]) if(left[i] != right[i])
return true; return true;
return false; return false;
} }
skipping to change at line 218 skipping to change at line 241
static void NAME(T1 * left, T2 const * right) \ static void NAME(T1 * left, T2 const * right) \
{ \ { \
(*left) OPER (*right); \ (*left) OPER (*right); \
UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \ UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \
} }
#define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \ #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \
template <class T1, class T2> \ template <class T1, class T2> \
static void NAME(T1 * left, T2 right) \ static void NAME(T1 * left, T2 right) \
{ \ { \
(*left) OPER (right); \ (*left) = detail::RequiresExplicitCast<T1>::cast((*left) OPER (righ t)); \
UnrollLoop<LEVEL-1>::NAME(left+1, right); \ UnrollLoop<LEVEL-1>::NAME(left+1, right); \
} }
template <int LEVEL> template <int LEVEL>
struct UnrollLoop struct UnrollLoop
{ {
template <class T1, class T2> template <class T1, class T2>
static void reverseAssign(T1 * left, T2 const * right)
{
*left = *right;
UnrollLoop<LEVEL-1>::reverseAssign(left+1, right-1);
}
template <class T1, class T2>
static void assignCast(T1 * left, T2 const * right) static void assignCast(T1 * left, T2 const * right)
{ {
*left = detail::RequiresExplicitCast<T1>::cast(*right); *left = detail::RequiresExplicitCast<T1>::cast(*right);
UnrollLoop<LEVEL-1>::assignCast(left+1, right+1); UnrollLoop<LEVEL-1>::assignCast(left+1, right+1);
} }
template <class T1, class T2>
static void assignScalar(T1 * left, T2 right)
{
*left = detail::RequiresExplicitCast<T1>::cast(right);
UnrollLoop<LEVEL-1>::assignScalar(left+1, right);
}
VIGRA_UNROLL_LOOP(assign, =) VIGRA_UNROLL_LOOP(assign, =)
VIGRA_UNROLL_LOOP(add, +=) VIGRA_UNROLL_LOOP(add, +=)
VIGRA_UNROLL_LOOP(sub, -=) VIGRA_UNROLL_LOOP(sub, -=)
VIGRA_UNROLL_LOOP(mul, *=) VIGRA_UNROLL_LOOP(mul, *=)
VIGRA_UNROLL_LOOP(div, /=)
VIGRA_UNROLL_LOOP(neg, = -) VIGRA_UNROLL_LOOP(neg, = -)
VIGRA_UNROLL_LOOP(abs, = vigra::abs) VIGRA_UNROLL_LOOP(abs, = vigra::abs)
VIGRA_UNROLL_LOOP(floor, = vigra::floor) VIGRA_UNROLL_LOOP(floor, = vigra::floor)
VIGRA_UNROLL_LOOP(ceil, = vigra::ceil) VIGRA_UNROLL_LOOP(ceil, = vigra::ceil)
VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote ) VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote )
VIGRA_UNROLL_LOOP_SCALAR(assignScalar, =) VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *)
VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *=) VIGRA_UNROLL_LOOP_SCALAR(divScalar, /)
VIGRA_UNROLL_LOOP_SCALAR(divScalar, /=)
template <class T1, class T2> template <class T1, class T2>
static bool notEqual(T1 const * left, T2 const * right) static bool notEqual(T1 const * left, T2 const * right)
{ {
return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1, right+1); return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1, right+1);
} }
template <class T> template <class T>
static typename NumericTraits<T>::Promote static typename NumericTraits<T>::Promote
dot(T const * d) dot(T const * d)
skipping to change at line 281 skipping to change at line 318
} }
}; };
#undef VIGRA_UNROLL_LOOP #undef VIGRA_UNROLL_LOOP
#undef VIGRA_UNROLL_LOOP_SCALAR #undef VIGRA_UNROLL_LOOP_SCALAR
template <> template <>
struct UnrollLoop<0> struct UnrollLoop<0>
{ {
template <class T1, class T2> template <class T1, class T2>
static void reverseAssign(T1, T2) {}
template <class T1, class T2>
static void assignCast(T1, T2) {} static void assignCast(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void assign(T1, T2) {} static void assign(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void assignScalar(T1, T2) {} static void assignScalar(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void add(T1, T2) {} static void add(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void sub(T1, T2) {} static void sub(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
skipping to change at line 314 skipping to change at line 353
template <class T1, class T2> template <class T1, class T2>
static void abs(T1, T2) {} static void abs(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void floor(T1, T2) {} static void floor(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void ceil(T1, T2) {} static void ceil(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static bool notEqual(T1, T2) { return false; } static bool notEqual(T1, T2) { return false; }
}; };
template <bool PREDICATE>
struct TinyVectorIf
{
template <class T, class F>
struct res
{
typedef T type;
};
};
template <>
struct TinyVectorIf<false>
{
template <class T, class F>
struct res
{
typedef F type;
};
};
template <int SIZE> template <int SIZE>
struct LoopType struct LoopType
{ {
typedef typename TinyVectorIf<SIZE < 5>:: typedef typename IfBool<(SIZE < 5), UnrollLoop<SIZE>, ExecLoop<SIZE> >:
template res<UnrollLoop<SIZE>, ExecLoop<SIZE> >::type type; :type type;
}; };
struct DontInit {}; struct DontInit {};
inline DontInit dontInit() {return DontInit(); } inline DontInit dontInit() {return DontInit(); }
} // namespace detail } // namespace detail
template <class T, int SIZE> template <class T, int SIZE>
class TinyVector; class TinyVector;
skipping to change at line 445 skipping to change at line 464
/** Initialize from another sequence (must have length SIZE!) /** Initialize from another sequence (must have length SIZE!)
*/ */
template <class Iterator> template <class Iterator>
void init(Iterator i, Iterator end) void init(Iterator i, Iterator end)
{ {
vigra_precondition(end-i == SIZE, vigra_precondition(end-i == SIZE,
"TinyVector::init(): Sequence has wrong size."); "TinyVector::init(): Sequence has wrong size.");
Loop::assignCast(data_, i); Loop::assignCast(data_, i);
} }
/** Initialize with constant value
*/
void init(value_type initial)
{
Loop::assignScalar(data_, initial);
}
/** Component-wise add-assignment /** Component-wise add-assignment
*/ */
template <class T1, class D1, class D2> template <class T1, class D1, class D2>
DERIVED & operator+=(TinyVectorBase<T1, SIZE, D1, D2> const & r) DERIVED & operator+=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
{ {
Loop::add(data_, r.begin()); Loop::add(data_, r.begin());
return static_cast<DERIVED &>(*this); return static_cast<DERIVED &>(*this);
} }
/** Component-wise subtract-assignment /** Component-wise subtract-assignment
skipping to change at line 472 skipping to change at line 498
/** Component-wise multiply-assignment /** Component-wise multiply-assignment
*/ */
template <class T1, class D1, class D2> template <class T1, class D1, class D2>
DERIVED & operator*=(TinyVectorBase<T1, SIZE, D1, D2> const & r) DERIVED & operator*=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
{ {
Loop::mul(data_, r.begin()); Loop::mul(data_, r.begin());
return static_cast<DERIVED &>(*this); return static_cast<DERIVED &>(*this);
} }
/** Component-wise divide-assignment
*/
template <class T1, class D1, class D2>
DERIVED & operator/=(TinyVectorBase<T1, SIZE, D1, D2> const & r)
{
Loop::div(data_, r.begin());
return static_cast<DERIVED &>(*this);
}
/** Component-wise scalar multiply-assignment /** Component-wise scalar multiply-assignment
*/ */
DERIVED & operator*=(double r) DERIVED & operator*=(double r)
{ {
Loop::mulScalar(data_, r); Loop::mulScalar(data_, r);
return static_cast<DERIVED &>(*this); return static_cast<DERIVED &>(*this);
} }
/** Component-wise scalar divide-assignment /** Component-wise scalar divide-assignment
*/ */
skipping to change at line 505 skipping to change at line 540
/** Calculate squared magnitude. /** Calculate squared magnitude.
*/ */
SquaredNormType squaredMagnitude() const SquaredNormType squaredMagnitude() const
{ {
return Loop::squaredNorm(data_); return Loop::squaredNorm(data_);
} }
/** Access component by index. /** Access component by index.
*/ */
reference operator[](difference_type i) { return data_[i]; } reference operator[](difference_type i)
{
VIGRA_ASSERT_INSIDE(i);
return data_[i];
}
/** Get component by index. /** Get component by index.
*/ */
const_reference operator[](difference_type i) const { return data_[i]; const_reference operator[](difference_type i) const
} {
VIGRA_ASSERT_INSIDE(i);
return data_[i];
}
/** Get random access iterator to begin of vector. /** Get random access iterator to begin of vector.
*/ */
iterator begin() { return data_; } iterator begin() { return data_; }
/** Get random access iterator past-the-end of vector. /** Get random access iterator past-the-end of vector.
*/ */
iterator end() { return data_ + SIZE; } iterator end() { return data_ + SIZE; }
/** Get const random access iterator to begin of vector. /** Get const random access iterator to begin of vector.
*/ */
skipping to change at line 587 skipping to change at line 631
typedef typename BaseType::pointer pointer; typedef typename BaseType::pointer pointer;
typedef typename BaseType::const_pointer const_pointer; typedef typename BaseType::const_pointer const_pointer;
typedef typename BaseType::iterator iterator; typedef typename BaseType::iterator iterator;
typedef typename BaseType::const_iterator const_iterator; typedef typename BaseType::const_iterator const_iterator;
typedef typename BaseType::size_type size_type; typedef typename BaseType::size_type size_type;
typedef typename BaseType::difference_type difference_type; typedef typename BaseType::difference_type difference_type;
typedef typename BaseType::scalar_multiplier scalar_multiplier; typedef typename BaseType::scalar_multiplier scalar_multiplier;
typedef typename BaseType::SquaredNormType SquaredNormType; typedef typename BaseType::SquaredNormType SquaredNormType;
typedef typename BaseType::NormType NormType; typedef typename BaseType::NormType NormType;
enum ReverseCopyTag { ReverseCopy };
/** Construction with constant value /** Construction with constant value
*/ */
explicit TinyVector(value_type const & initial) explicit TinyVector(value_type const & initial)
: BaseType() : BaseType()
{ {
Loop::assignScalar(BaseType::begin(), initial); Loop::assignScalar(BaseType::begin(), initial);
} }
/** Construction with Diff2D (only implemented for 2D TinyVector)
*/
explicit TinyVector(Diff2D const & initial)
: BaseType()
{
BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial.
x);
BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial.
y);
}
/** Construction with explicit values. /** Construction with explicit values.
Call only if SIZE == 2 Call only if SIZE == 2
*/ */
TinyVector(value_type const & i1, value_type const & i2) TinyVector(value_type const & i1, value_type const & i2)
: BaseType() : BaseType()
{ {
BaseType::data_[0] = i1; BaseType::data_[0] = i1;
BaseType::data_[1] = i2; BaseType::data_[1] = i2;
} }
skipping to change at line 629 skipping to change at line 684
TinyVector(value_type const & i1, value_type const & i2, TinyVector(value_type const & i1, value_type const & i2,
value_type const & i3, value_type const & i4) value_type const & i3, value_type const & i4)
: BaseType() : BaseType()
{ {
BaseType::data_[0] = i1; BaseType::data_[0] = i1;
BaseType::data_[1] = i2; BaseType::data_[1] = i2;
BaseType::data_[2] = i3; BaseType::data_[2] = i3;
BaseType::data_[3] = i4; BaseType::data_[3] = i4;
} }
/** Construction with explicit values.
Call only if SIZE == 5
*/
TinyVector(value_type const & i1, value_type const & i2,
value_type const & i3, value_type const & i4,
value_type const & i5)
: BaseType()
{
BaseType::data_[0] = i1;
BaseType::data_[1] = i2;
BaseType::data_[2] = i3;
BaseType::data_[3] = i4;
BaseType::data_[4] = i5;
}
/** Default constructor (initializes all components with zero) /** Default constructor (initializes all components with zero)
*/ */
TinyVector() TinyVector()
: BaseType() : BaseType()
{ {
Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero ()); Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero ());
} }
/** Copy constructor. /** Copy constructor.
*/ */
skipping to change at line 653 skipping to change at line 722
} }
/** Constructor from C array. /** Constructor from C array.
*/ */
explicit TinyVector(const_pointer data) explicit TinyVector(const_pointer data)
: BaseType() : BaseType()
{ {
Loop::assign(BaseType::data_, data); Loop::assign(BaseType::data_, data);
} }
/** Constructor by reverse copy from C array.
Usage:
\code
TinyVector<int, 3> v(1,2,3);
TinyVector<int, 3> reverse(v.begin(), TinyVector<int, 3>::Rever
seCopy);
\endcode
*/
explicit TinyVector(const_pointer data, ReverseCopyTag)
: BaseType()
{
Loop::reverseAssign(BaseType::data_, data+SIZE-1);
}
/** Copy assignment. /** Copy assignment.
*/ */
TinyVector & operator=(TinyVector const & r) TinyVector & operator=(TinyVector const & r)
{ {
Loop::assign(BaseType::data_, r.data_); Loop::assign(BaseType::data_, r.data_);
return *this; return *this;
} }
/** Assignment from Diff2D.
*/
TinyVector & operator=(Diff2D const & r)
{
BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(r.x);
BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(r.y);
return *this;
}
/** Copy with type conversion.
*/
template <class U>
TinyVector(TinyVector<U, SIZE> const & r)
: BaseType()
{
Loop::assignCast(BaseType::data_, r.begin());
}
/** Copy with type conversion. /** Copy with type conversion.
*/ */
template <class U, class DATA, class DERIVED> template <class U, class DATA, class DERIVED>
TinyVector(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r) TinyVector(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r)
: BaseType() : BaseType()
{ {
Loop::assignCast(BaseType::data_, r.begin()); Loop::assignCast(BaseType::data_, r.begin());
} }
/** Copy assignment with type conversion. /** Copy assignment with type conversion.
*/ */
template <class U, class DATA, class DERIVED> template <class U, class DATA, class DERIVED>
TinyVector & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r ) TinyVector & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r )
{ {
Loop::assignCast(BaseType::data_, r.begin()); Loop::assignCast(BaseType::data_, r.begin());
return *this; return *this;
} }
explicit TinyVector(SkipInitializationTag)
: BaseType()
{}
explicit TinyVector(detail::DontInit) explicit TinyVector(detail::DontInit)
: BaseType() : BaseType()
{} {}
}; };
/** \brief Wrapper for fixed size vectors. /** \brief Wrapper for fixed size vectors.
This class wraps an array of size SIZE of the specified VALUETYPE. This class wraps an array of size SIZE of the specified VALUETYPE.
Thus, the array can be accessed with an interface similar to Thus, the array can be accessed with an interface similar to
that of std::vector (except that there are no functions that of std::vector (except that there are no functions
skipping to change at line 1036 skipping to change at line 1141
{ {
typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promot e; typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promot e;
}; };
template <class T, int SIZE> template <class T, int SIZE>
struct PromoteTraits<double, TinyVectorView<T, SIZE> > struct PromoteTraits<double, TinyVectorView<T, SIZE> >
{ {
typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promot e; typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> Promot e;
}; };
template<class T, int SIZE>
struct CanSkipInitialization<TinyVectorView<T, SIZE> >
{
typedef typename CanSkipInitialization<T>::type type;
static const bool value = type::asBool;
};
template<class T, int SIZE>
struct CanSkipInitialization<TinyVector<T, SIZE> >
{
typedef typename CanSkipInitialization<T>::type type;
static const bool value = type::asBool;
};
#else // NO_PARTIAL_TEMPLATE_SPECIALIZATION #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
#define TINYVECTOR_NUMTRAITS(T, SIZE) \ #define TINYVECTOR_NUMTRAITS(T, SIZE) \
template<>\ template<>\
struct NumericTraits<TinyVector<T, SIZE> >\ struct NumericTraits<TinyVector<T, SIZE> >\
{\ {\
typedef TinyVector<T, SIZE> Type;\ typedef TinyVector<T, SIZE> Type;\
typedef TinyVector<NumericTraits<T>::Promote, SIZE> Promote;\ typedef TinyVector<NumericTraits<T>::Promote, SIZE> Promote;\
typedef TinyVector<NumericTraits<T>::RealPromote, SIZE> RealPromote;\ typedef TinyVector<NumericTraits<T>::RealPromote, SIZE> RealPromote;\
typedef TinyVector<NumericTraits<T>::ComplexPromote, SIZE> ComplexPromo te;\ typedef TinyVector<NumericTraits<T>::ComplexPromote, SIZE> ComplexPromo te;\
skipping to change at line 1187 skipping to change at line 1306
/// component-wise multiplication /// component-wise multiplication
template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
inline inline
typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promot e typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promot e
operator*(TinyVectorBase<V1, SIZE, D1, D2> const & l, operator*(TinyVectorBase<V1, SIZE, D1, D2> const & l,
TinyVectorBase<V2, SIZE, D3, D4> const & r) TinyVectorBase<V2, SIZE, D3, D4> const & r)
{ {
return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZ E> >::Promote(l) *= r; return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZ E> >::Promote(l) *= r;
} }
/// component-wise division
template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4>
inline
typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promot
e
operator/(TinyVectorBase<V1, SIZE, D1, D2> const & l,
TinyVectorBase<V2, SIZE, D3, D4> const & r)
{
return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZ
E> >::Promote(l) /= r;
}
/// component-wise left scalar multiplication /// component-wise left scalar multiplication
template <class V, int SIZE, class D1, class D2> template <class V, int SIZE, class D1, class D2>
inline inline
typename NumericTraits<TinyVector<V, SIZE> >::RealPromote typename NumericTraits<TinyVector<V, SIZE> >::RealPromote
operator*(double v, TinyVectorBase<V, SIZE, D1, D2> const & r) operator*(double v, TinyVectorBase<V, SIZE, D1, D2> const & r)
{ {
return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) *= v; return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) *= v;
} }
/// component-wise right scalar multiplication /// component-wise right scalar multiplication
skipping to change at line 1310 skipping to change at line 1439
template <class V, int SIZE> template <class V, int SIZE>
inline inline
typename TinyVector<V, SIZE>::SquaredNormType typename TinyVector<V, SIZE>::SquaredNormType
squaredNorm(TinyVector<V, SIZE> const & t) squaredNorm(TinyVector<V, SIZE> const & t)
{ {
return t.squaredMagnitude(); return t.squaredMagnitude();
} }
//@} //@}
} // namespace vigra } // namespace vigra
#undef VIGRA_ASSERT_INSIDE
#endif // VIGRA_TINYVECTOR_HXX #endif // VIGRA_TINYVECTOR_HXX
 End of changes. 31 change blocks. 
37 lines changed or deleted 171 lines changed or added


 transformimage.hxx   transformimage.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 418 skipping to change at line 416
int x,y; int x,y;
SrcImageIterator sy = srcul; SrcImageIterator sy = srcul;
DestImageIterator dy = destul; DestImageIterator dy = destul;
static const Diff2D left(-1,0); static const Diff2D left(-1,0);
static const Diff2D right(1,0); static const Diff2D right(1,0);
static const Diff2D top(0,-1); static const Diff2D top(0,-1);
static const Diff2D bottom(0,1); static const Diff2D bottom(0,1);
typename NumericTraits<typename SrcAccessor::value_type>::RealPromote typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP
diffx, diffy; romote TmpType;
TmpType diffx, diffy;
SrcImageIterator sx = sy; SrcImageIterator sx = sy;
DestImageIterator dx = dy; DestImageIterator dx = dy;
diffx = sa(sx) - sa(sx, right); diffx = sa(sx) - sa(sx, right);
diffy = sa(sx) - sa(sx, bottom); diffy = sa(sx) - sa(sx, bottom);
da.set(grad(diffx, diffy), dx); da.set(grad(diffx, diffy), dx);
for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x) for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
{ {
diffx = (sa(sx, left) - sa(sx, right)) / 2.0; diffx = (sa(sx, left) - sa(sx, right)) / TmpType(2.0);
diffy = sa(sx) - sa(sx, bottom); diffy = sa(sx) - sa(sx, bottom);
da.set(grad(diffx, diffy), dx); da.set(grad(diffx, diffy), dx);
} }
diffx = sa(sx, left) - sa(sx); diffx = sa(sx, left) - sa(sx);
diffy = sa(sx) - sa(sx, bottom); diffy = sa(sx) - sa(sx, bottom);
da.set(grad(diffx, diffy), dx); da.set(grad(diffx, diffy), dx);
++sy.y; ++sy.y;
++dy.y; ++dy.y;
for(y=2; y<h; ++y, ++sy.y, ++dy.y) for(y=2; y<h; ++y, ++sy.y, ++dy.y)
{ {
sx = sy; sx = sy;
dx = dy; dx = dy;
diffx = sa(sx) - sa(sx, right); diffx = sa(sx) - sa(sx, right);
diffy = (sa(sx, top) - sa(sx, bottom)) / 2.0; diffy = (sa(sx, top) - sa(sx, bottom)) / TmpType(2.0);
da.set(grad(diffx, diffy), dx); da.set(grad(diffx, diffy), dx);
for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x) for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
{ {
diffx = (sa(sx, left) - sa(sx, right)) / 2.0; diffx = (sa(sx, left) - sa(sx, right)) / TmpType(2.0);
diffy = (sa(sx, top) - sa(sx, bottom)) / 2.0; diffy = (sa(sx, top) - sa(sx, bottom)) / TmpType(2.0);
da.set(grad(diffx, diffy), dx); da.set(grad(diffx, diffy), dx);
} }
diffx = sa(sx, left) - sa(sx); diffx = sa(sx, left) - sa(sx);
diffy = (sa(sx, top) - sa(sx, bottom)) / 2.0; diffy = (sa(sx, top) - sa(sx, bottom)) / TmpType(2.0);
da.set(grad(diffx, diffy), dx); da.set(grad(diffx, diffy), dx);
} }
sx = sy; sx = sy;
dx = dy; dx = dy;
diffx = sa(sx) - sa(sx, right); diffx = sa(sx) - sa(sx, right);
diffy = sa(sx, top) - sa(sx); diffy = sa(sx, top) - sa(sx);
da.set(grad(diffx, diffy), dx); da.set(grad(diffx, diffy), dx);
for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x) for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
{ {
diffx = (sa(sx, left) - sa(sx, right)) / 2.0; diffx = (sa(sx, left) - sa(sx, right)) / TmpType(2.0);
diffy = sa(sx, top) - sa(sx); diffy = sa(sx, top) - sa(sx);
da.set(grad(diffx, diffy), dx); da.set(grad(diffx, diffy), dx);
} }
diffx = sa(sx, left) - sa(sx); diffx = sa(sx, left) - sa(sx);
diffy = sa(sx, top) - sa(sx); diffy = sa(sx, top) - sa(sx);
da.set(grad(diffx, diffy), dx); da.set(grad(diffx, diffy), dx);
} }
template <class SrcImageIterator, class SrcAccessor, template <class SrcImageIterator, class SrcAccessor,
skipping to change at line 1237 skipping to change at line 1235
typedef PixelType result_type; typedef PixelType result_type;
/** \deprecated use argument_type and result_type /** \deprecated use argument_type and result_type
*/ */
typedef PixelType value_type; typedef PixelType value_type;
/** Init functor for argument range <TT>[min, max]</TT>. /** Init functor for argument range <TT>[min, max]</TT>.
<TT>gamma</TT> values < 1 will increase brightness, > 1 <TT>gamma</TT> values < 1 will increase brightness, > 1
will decrease it (gamma == 1 means no change). will decrease it (gamma == 1 means no change).
*/ */
GammaFunctor(promote_type gamma, GammaFunctor(double gamma,
argument_type const & min, argument_type const & max) argument_type const & min, argument_type const & max)
: gamma_(gamma), : gamma_((promote_type)gamma),
min_(min), min_(min),
diff_(max - min), diff_(max - min),
zero_(NumericTraits<promote_type>::zero()), zero_(NumericTraits<promote_type>::zero()),
one_(NumericTraits<promote_type>::one()) one_(NumericTraits<promote_type>::one())
{} {}
/** Calculate modified gray or color value /** Calculate modified gray or color value
*/ */
result_type operator()(argument_type const & v) const result_type operator()(argument_type const & v) const
{ {
 End of changes. 11 change blocks. 
13 lines changed or deleted 12 lines changed or added


 tuple.hxx   tuple.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
 End of changes. 3 change blocks. 
3 lines changed or deleted 1 lines changed or added


 utilities.hxx   utilities.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2002 by Ullrich Koethe */ /* Copyright 1998-2002 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 47 skipping to change at line 45
#ifndef VIGRA_BASICS_HXX #ifndef VIGRA_BASICS_HXX
#define VIGRA_BASICS_HXX #define VIGRA_BASICS_HXX
#include "config.hxx" #include "config.hxx"
#include "error.hxx" #include "error.hxx"
#include "metaprogramming.hxx" #include "metaprogramming.hxx"
#include "tuple.hxx" #include "tuple.hxx"
#include "diff2d.hxx" #include "diff2d.hxx"
#include "mathutil.hxx" #include "mathutil.hxx"
#include <string>
#include <sstream>
namespace vigra {
/** Convert a value to a string. Available for integral and floating point
types
and void *.
*/
doxygen_overloaded_function(template <class T> std::string asString(T t))
#define VIGRA_AS_STRING(T) \
inline std::string asString(T t) \
{ \
std::stringstream s; \
s << t; \
return s.str(); \
}
VIGRA_AS_STRING(bool)
VIGRA_AS_STRING(signed char)
VIGRA_AS_STRING(unsigned char)
VIGRA_AS_STRING(signed short)
VIGRA_AS_STRING(unsigned short)
VIGRA_AS_STRING(signed long)
VIGRA_AS_STRING(unsigned long)
VIGRA_AS_STRING(signed long long)
VIGRA_AS_STRING(unsigned long long)
VIGRA_AS_STRING(signed int)
VIGRA_AS_STRING(unsigned int)
VIGRA_AS_STRING(float)
VIGRA_AS_STRING(double)
VIGRA_AS_STRING(long double)
VIGRA_AS_STRING(void *)
#undef VIGRA_AS_STRING
} // namespace std
/*! \page Utilities Utilities /*! \page Utilities Utilities
Basic helper functionality needed throughout. Basic helper functionality needed throughout.
<UL style="list-style-image:url(documents/bullet.gif)"> <UL style="list-style-image:url(documents/bullet.gif)">
<LI> \ref vigra::ArrayVector <LI> \ref vigra::ArrayVector
<BR>&nbsp;&nbsp;&nbsp;<em>replacement for std::vector</em> <BR>&nbsp;&nbsp;&nbsp;<em>replacement for std::vector</em>
<LI> \ref RangesAndPoints <LI> \ref RangesAndPoints
<BR>&nbsp;&nbsp;&nbsp;<em>2-dimensional positions, extents, and re ctangles</em> <BR>&nbsp;&nbsp;&nbsp;<em>2-dimensional positions, extents, and re ctangles</em>
<LI> \ref PixelNeighborhood <LI> \ref PixelNeighborhood
 End of changes. 4 change blocks. 
3 lines changed or deleted 39 lines changed or added


 voxelneighborhood.hxx   voxelneighborhood.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2006-2007 by F. Heinrich, B. Seppke, Ullrich Koethe */ /* Copyright 2006-2007 by F. Heinrich, B. Seppke, Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 100 skipping to change at line 98
(y == 0 (y == 0
? TopBorder ? TopBorder
: y == height-1 : y == height-1
? BottomBorder ? BottomBorder
: NotAtBorder) | : NotAtBorder) |
(z == 0 (z == 0
? FrontBorder ? FrontBorder
: z == depth-1 : z == depth-1
? RearBorder ? RearBorder
: NotAtBorder)); : NotAtBorder));
}; }
inline AtVolumeBorder isAtVolumeBorder(Diff3D const & p, Diff3D const & sha
pe)
{
return isAtVolumeBorder(p[0], p[1], p[2], shape[0], shape[1], shape[2])
;
}
/** \brief Find out whether a voxel is at a scan-order relevant volume bord er. /** \brief Find out whether a voxel is at a scan-order relevant volume bord er.
This function checks if \a x == 0 or \a y == 0 or \a z == \a 0 and retu rns the This function checks if \a x == 0 or \a y == 0 or \a z == \a 0 and retu rns the
appropriate value of \ref vigra::AtVolumeBorder, or zero when the v oxel is appropriate value of \ref vigra::AtVolumeBorder, or zero when the v oxel is
not at te volume border. not at te volume border.
The behavior of the function is undefined if (x,y,z) is not inside the volume. The behavior of the function is undefined if (x,y,z) is not inside the volume.
*/ */
inline AtVolumeBorder isAtVolumeBorderCausal(int x, int y, int z, int width , int height, int depth) inline AtVolumeBorder isAtVolumeBorderCausal(int x, int y, int z, int /* wi dth */, int /* height */, int /* depth */)
{ {
return static_cast<AtVolumeBorder>((x == 0 return static_cast<AtVolumeBorder>((x == 0
? LeftBorder ? LeftBorder
: NotAtBorder) | : NotAtBorder) |
(y == 0 (y == 0
? TopBorder ? TopBorder
: NotAtBorder) | : NotAtBorder) |
(z == 0 (z == 0
? FrontBorder ? FrontBorder
: NotAtBorder)); : NotAtBorder));
}; }
/** TODO: Write new comment \brief Find out whether a voxel is at a scan-or der relevant volume border. /** TODO: Write new comment \brief Find out whether a voxel is at a scan-or der relevant volume border.
This function checks if \a x == 0 or \a y == 0 or \a z == \a 0 and retu rns the This function checks if \a x == 0 or \a y == 0 or \a z == \a 0 and retu rns the
appropriate value of \ref vigra::AtVolumeBorder, or zero when the v oxel is appropriate value of \ref vigra::AtVolumeBorder, or zero when the v oxel is
not at te volume border. not at te volume border.
The behavior of the function is undefined if (x,y,z) is not inside the volume. The behavior of the function is undefined if (x,y,z) is not inside the volume.
*/ */
inline AtVolumeBorder isAtVolumeBorderAntiCausal(int x, int y, int z, int w idth, int height, int depth) inline AtVolumeBorder isAtVolumeBorderAntiCausal(int x, int y, int z, int w idth, int height, int depth)
{ {
return static_cast<AtVolumeBorder>((x == width-1 return static_cast<AtVolumeBorder>((x == width-1
? RightBorder ? RightBorder
: NotAtBorder) | : NotAtBorder) |
(y == height-1 (y == height-1
? BottomBorder ? BottomBorder
: NotAtBorder) | : NotAtBorder) |
(z == depth-1 (z == depth-1
? RearBorder ? RearBorder
: NotAtBorder)); : NotAtBorder));
}; }
/********************************************************/ /********************************************************/
/* */ /* */
/* Neighborhood3DSix */ /* Neighborhood3DSix */
/* */ /* */
/********************************************************/ /********************************************************/
/** 3D 6-Neighborhood. */ /** 3D 6-Neighborhood. */
namespace Neighborhood3DSix namespace Neighborhood3DSix
{ {
skipping to change at line 180 skipping to change at line 184
AntiCausalFirst = Behind, AntiCausalFirst = Behind,
AntiCausalLast = East, AntiCausalLast = East,
InitialDirection = InFront, InitialDirection = InFront,
OppositeDirPrefix = 1, OppositeDirPrefix = 1,
OppositeOffset = 3 OppositeOffset = 3
}; };
static unsigned int directionBit(Direction d) static unsigned int directionBit(Direction d)
{ {
static unsigned int b[] = { 1 << (InFront + 1), static unsigned int b[] = { 1 << InFront,
1 << (North + 1), 1 << North,
1 << (West + 1), 1 << West,
1 << (Behind + 1), 1 << Behind,
1 << (South + 1), 1 << South,
1 << (East + 1) 1 << East
}; };
return b[d]; return b[d];
}; };
/** The number of valid neighbors if the current center is at the volum e border. /** The number of valid neighbors if the current center is at the volum e border.
*/ */
static unsigned int nearBorderDirectionCount(AtVolumeBorder b) static unsigned int nearBorderDirectionCount(AtVolumeBorder b)
{ {
static unsigned int c[] = { 6, 5, 5, 0, 5, 4, 4, 0, 5, 4, static unsigned int c[] = { 6, 5, 5, 0, 5, 4, 4, 0, 5, 4,
4, 0, 0, 0, 0, 0, 5, 4, 4, 0, 4, 0, 0, 0, 0, 0, 5, 4, 4, 0,
skipping to change at line 518 skipping to change at line 522
AntiCausalLast = East, AntiCausalLast = East,
InitialDirection = InFrontNorthWest, InitialDirection = InFrontNorthWest,
OppositeDirPrefix = -1, OppositeDirPrefix = -1,
OppositeOffset = 25 OppositeOffset = 25
}; };
static unsigned int directionBit(Direction d) static unsigned int directionBit(Direction d)
{ {
static unsigned int b[] = { static unsigned int b[] = {
1 << (InFrontNorthWest+1), 1 << InFrontNorthWest,
1 << (InFrontNorth+1), 1 << InFrontNorth,
1 << (InFrontNorthEast+1), 1 << InFrontNorthEast,
1 << (InFrontWest+1), 1 << InFrontWest,
1 << (InFront+1), 1 << InFront,
1 << (InFrontEast+1), 1 << InFrontEast,
1 << (InFrontSouthWest+1), 1 << InFrontSouthWest,
1 << (InFrontSouth+1), 1 << InFrontSouth,
1 << (InFrontSouthEast+1), 1 << InFrontSouthEast,
1 << (NorthWest+1), 1 << NorthWest,
1 << (North+1), 1 << North,
1 << (NorthEast+1), 1 << NorthEast,
1 << (West+1), 1 << West,
1 << (East+1), 1 << East,
1 << (SouthWest+1), 1 << SouthWest,
1 << (South+1), 1 << South,
1 << (SouthEast+1), 1 << SouthEast,
1 << (BehindNorthWest+1), 1 << BehindNorthWest,
1 << (BehindNorth+1), 1 << BehindNorth,
1 << (BehindNorthEast+1), 1 << BehindNorthEast,
1 << (BehindWest+1), 1 << BehindWest,
1 << (Behind+1), 1 << Behind,
1 << (BehindEast+1), 1 << BehindEast,
1 << (BehindSouthWest+1), 1 << BehindSouthWest,
1 << (BehindSouth+1), 1 << BehindSouth,
1 << (BehindSouthEast+1) 1 << BehindSouthEast
}; };
return b[d]; return b[d];
}; };
/** The number of valid neighbors if the current center is at the volum e border. /** The number of valid neighbors if the current center is at the volum e border.
*/ */
static unsigned int nearBorderDirectionCount(AtVolumeBorder b) static unsigned int nearBorderDirectionCount(AtVolumeBorder b)
{ {
static unsigned int c[] = { 26, 17, 17, 0, 17, 11, 11, 0, 17, 11, static unsigned int c[] = { 26, 17, 17, 0, 17, 11, 11, 0, 17, 11,
11, 0, 0, 0, 0, 0, 17, 11, 11, 0, 11, 0, 0, 0, 0, 0, 17, 11, 11, 0,
skipping to change at line 1388 skipping to change at line 1392
case Neighborhood3DSix::North : case Neighborhood3DSix::North :
return North; return North;
case Neighborhood3DSix::West : case Neighborhood3DSix::West :
return West; return West;
case Neighborhood3DSix::East : case Neighborhood3DSix::East :
return East; return East;
case Neighborhood3DSix::South : case Neighborhood3DSix::South :
return South; return South;
case Neighborhood3DSix::Behind : case Neighborhood3DSix::Behind :
return Behind; return Behind;
default:
vigra_fail("NeighborCode3D::code(): Internal error -- inval
id direction code.");
} }
return Error; return Error;
} }
/** transform Diff3D offset into corresponding direction code. /** transform Diff3D offset into corresponding direction code.
The code <tt>Direction::Error</tt> will be returned if <tt>diff</tt> The code <tt>Direction::Error</tt> will be returned if <tt>diff</tt>
is not in the 3DTwentySix-Neighborhood. is not in the 3DTwentySix-Neighborhood.
*/ */
static Direction code(Diff3D const & diff) static Direction code(Diff3D const & diff)
{ {
 End of changes. 12 change blocks. 
39 lines changed or deleted 48 lines changed or added


 watersheds.hxx   watersheds.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2005 by Ullrich Koethe */ /* Copyright 1998-2005 by Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 45 skipping to change at line 43
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_WATERSHEDS_HXX #ifndef VIGRA_WATERSHEDS_HXX
#define VIGRA_WATERSHEDS_HXX #define VIGRA_WATERSHEDS_HXX
#include <functional> #include <functional>
#include "mathutil.hxx" #include "mathutil.hxx"
#include "stdimage.hxx" #include "stdimage.hxx"
#include "pixelneighborhood.hxx" #include "pixelneighborhood.hxx"
#include "union_find.hxx"
namespace vigra { namespace vigra {
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class Neighborhood> class Neighborhood>
unsigned int watershedLabeling(SrcIterator upperlefts, unsigned int watershedLabeling(SrcIterator upperlefts,
SrcIterator lowerrights, SrcAccessor sa, SrcIterator lowerrights, SrcAccessor sa,
DestIterator upperleftd, DestAccessor da, DestIterator upperleftd, DestAccessor da,
Neighborhood neighborhood) Neighborhood)
{ {
typedef typename DestAccessor::value_type LabelType;
int w = lowerrights.x - upperlefts.x; int w = lowerrights.x - upperlefts.x;
int h = lowerrights.y - upperlefts.y; int h = lowerrights.y - upperlefts.y;
int x,y,i; int x,y;
SrcIterator ys(upperlefts); SrcIterator ys(upperlefts);
SrcIterator xs(ys); SrcIterator xs(ys);
DestIterator yd(upperleftd);
DestIterator xd(yd);
// temporary image to store region labels // temporary image to store region labels
typedef IImage LabelImage; detail::UnionFindArray<LabelType> labels;
typedef LabelImage::traverser LabelTraverser;
LabelImage labelimage(w, h);
LabelTraverser yt = labelimage.upperLeft();
LabelTraverser xt(yt);
// Kovalevsky's clever idea to use
// image iterator and scan order iterator simultaneously
LabelImage::ScanOrderIterator label = labelimage.begin();
// initialize the neighborhood circulators // initialize the neighborhood circulators
NeighborOffsetCirculator<Neighborhood> ncstart(Neighborhood::CausalFirs t); NeighborOffsetCirculator<Neighborhood> ncstart(Neighborhood::CausalFirs t);
NeighborOffsetCirculator<Neighborhood> ncstartBorder(Neighborhood::Nort h); NeighborOffsetCirculator<Neighborhood> ncstartBorder(Neighborhood::Nort h);
NeighborOffsetCirculator<Neighborhood> ncend(Neighborhood::CausalLast); NeighborOffsetCirculator<Neighborhood> ncend(Neighborhood::CausalLast);
++ncend; ++ncend;
NeighborOffsetCirculator<Neighborhood> ncendBorder(Neighborhood::North) ; NeighborOffsetCirculator<Neighborhood> ncendBorder(Neighborhood::North) ;
++ncendBorder; ++ncendBorder;
// pass 1: scan image from upper left to lower right // pass 1: scan image from upper left to lower right
skipping to change at line 97 skipping to change at line 90
// Each component will be represented by a tree of pixels. Each // Each component will be represented by a tree of pixels. Each
// pixel contains the scan order address of its parent in the // pixel contains the scan order address of its parent in the
// tree. In order for pass 2 to work correctly, the parent must // tree. In order for pass 2 to work correctly, the parent must
// always have a smaller scan order address than the child. // always have a smaller scan order address than the child.
// Therefore, we can merge trees only at their roots, because the // Therefore, we can merge trees only at their roots, because the
// root of the combined tree must have the smallest scan order // root of the combined tree must have the smallest scan order
// address among all the tree's pixels/ nodes. The root of each // address among all the tree's pixels/ nodes. The root of each
// tree is distinguished by pointing to itself (it contains its // tree is distinguished by pointing to itself (it contains its
// own scan order address). This condition is enforced whenever a // own scan order address). This condition is enforced whenever a
// new region is found or two regions are merged // new region is found or two regions are merged
xs = ys; da.set(labels.finalizeLabel(labels.nextFreeLabel()), xd);
xt = yt;
*xt = 0;
++xs.x; ++xs.x;
++xt.x; ++xd.x;
for(x = 1; x != w; ++x, ++xs.x, ++xt.x) for(x = 1; x != w; ++x, ++xs.x, ++xd.x)
{ {
if((*xs & Neighborhood::directionBit(Neighborhood::West)) || if((sa(xs) & Neighborhood::directionBit(Neighborhood::West)) ||
(xs[Neighborhood::west()] & Neighborhood::directionBit(Neighborh (sa(xs, Neighborhood::west()) & Neighborhood::directionBit(Neigh
ood::East))) borhood::East)))
{ {
*xt = xt[Neighborhood::west()]; da.set(da(xd, Neighborhood::west()), xd);
} }
else else
{ {
*xt = x; da.set(labels.finalizeLabel(labels.nextFreeLabel()), xd);
} }
} }
++ys.y; ++ys.y;
++yt.y; ++yd.y;
for(y = 1; y != h; ++y, ++ys.y, ++yt.y) for(y = 1; y != h; ++y, ++ys.y, ++yd.y)
{ {
xs = ys; xs = ys;
xt = yt; xd = yd;
for(x = 0; x != w; ++x, ++xs.x, ++xt.x) for(x = 0; x != w; ++x, ++xs.x, ++xd.x)
{ {
NeighborOffsetCirculator<Neighborhood> nc(x == w-1 NeighborOffsetCirculator<Neighborhood> nc(x == w-1
? ncstartBorder ? ncstartBorder
: ncstart); : ncstart);
NeighborOffsetCirculator<Neighborhood> nce(x == 0 NeighborOffsetCirculator<Neighborhood> nce(x == 0
? ncendBorder ? ncendBorder
: ncend); : ncend);
*xt = x + w*y; // default: new region LabelType currentLabel = labels.nextFreeLabel();
for(; nc != nce; ++nc) for(; nc != nce; ++nc)
{ {
if((*xs & nc.directionBit()) || (xs[*nc] & nc.oppositeDirec tionBit())) if((sa(xs) & nc.directionBit()) || (sa(xs, *nc) & nc.opposi teDirectionBit()))
{ {
int neighborLabel = xt[*nc]; currentLabel = labels.makeUnion(da(xd,*nc), currentLabe
// find the root label of a label tree l);
while(neighborLabel != label[neighborLabel])
{
neighborLabel = label[neighborLabel];
}
if(neighborLabel < *xt) // always keep the smallest amo
ng the possible labels
{
label[*xt] = neighborLabel;
*xt = neighborLabel;
}
else
{
label[neighborLabel] = *xt;
}
} }
} }
da.set(labels.finalizeLabel(currentLabel), xd);
} }
} }
unsigned int count = labels.makeContiguous();
// pass 2: assign one label to each region (tree) // pass 2: assign one label to each region (tree)
// so that labels form a consecutive sequence 1, 2, ... // so that labels form a consecutive sequence 1, 2, ...
DestIterator yd(upperleftd); yd = upperleftd;
unsigned int count = 0;
i = 0;
for(y=0; y != h; ++y, ++yd.y) for(y=0; y != h; ++y, ++yd.y)
{ {
DestIterator xd(yd); DestIterator xd(yd);
for(x = 0; x != w; ++x, ++xd.x, ++i) for(x = 0; x != w; ++x, ++xd.x)
{ {
if(label[i] == i) da.set(labels[da(xd)], xd);
{
label[i] = ++count;
}
else
{
label[i] = label[label[i]];
}
da.set(label[i], xd);
} }
} }
return count; return count;
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void prepareWatersheds(SrcIterator upperlefts, SrcIterator lowerrights, Src Accessor sa, void prepareWatersheds(SrcIterator upperlefts, SrcIterator lowerrights, Src Accessor sa,
DestIterator upperleftd, DestAccessor da, DestIterator upperleftd, DestAccessor da,
FourNeighborCode) FourNeighborCode)
 End of changes. 25 change blocks. 
63 lines changed or deleted 31 lines changed or added


 watersheds3d.hxx   watersheds3d.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2006-2007 by F. Heinrich, B. Seppke, Ullrich Koethe */ /* Copyright 2006-2007 by F. Heinrich, B. Seppke, Ullrich Koethe */
/* Cognitive Systems Group, University of Hamburg, Germany */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* ( Version 1.6.0, Aug 13 2008 ) */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
/* files (the "Software"), to deal in the Software without */ /* files (the "Software"), to deal in the Software without */
/* restriction, including without limitation the rights to use, */ /* restriction, including without limitation the rights to use, */
/* copy, modify, merge, publish, distribute, sublicense, and/or */ /* copy, modify, merge, publish, distribute, sublicense, and/or */
/* sell copies of the Software, and to permit persons to whom the */ /* sell copies of the Software, and to permit persons to whom the */
skipping to change at line 43 skipping to change at line 41
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_watersheds3D_HXX #ifndef VIGRA_watersheds3D_HXX
#define VIGRA_watersheds3D_HXX #define VIGRA_watersheds3D_HXX
#include "voxelneighborhood.hxx" #include "voxelneighborhood.hxx"
#include "multi_array.hxx" #include "multi_array.hxx"
#include "union_find.hxx"
namespace vigra namespace vigra
{ {
template <class SrcIterator, class SrcAccessor, class SrcShape, template <class SrcIterator, class SrcAccessor, class SrcShape,
class DestIterator, class DestAccessor, class Neighborhood3D> class DestIterator, class DestAccessor, class Neighborhood3D>
int preparewatersheds3D( SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa, int preparewatersheds3D( SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa,
DestIterator d_Iter, DestAccessor da, Neighborhood 3D) DestIterator d_Iter, DestAccessor da, Neighborhood 3D)
{ {
//basically needed for iteration and border-checks //basically needed for iteration and border-checks
skipping to change at line 85 skipping to change at line 84
{ {
AtVolumeBorder atBorder = isAtVolumeBorder(x,y,z,w,h,d); AtVolumeBorder atBorder = isAtVolumeBorder(x,y,z,w,h,d);
typename SrcAccessor::value_type v = sa(xs); typename SrcAccessor::value_type v = sa(xs);
// the following choice causes minima to point // the following choice causes minima to point
// to their lowest neighbor -- would this be better??? // to their lowest neighbor -- would this be better???
// typename SrcAccessor::value_type v = NumericTraits<typen ame SrcAccessor::value_type>::max(); // typename SrcAccessor::value_type v = NumericTraits<typen ame SrcAccessor::value_type>::max();
int o = 0; // means center is minimum int o = 0; // means center is minimum
typename SrcAccessor::value_type my_v = v; typename SrcAccessor::value_type my_v = v;
if(atBorder == NotAtBorder) if(atBorder == NotAtBorder)
{ {
#if 0
NeighborhoodTraverser<SrcIterator, Neighborhood3D> c(x
s), cend(c);
#endif /* #if 0 */
NeighborhoodCirculator<SrcIterator, Neighborhood3D> c( xs), cend(c); NeighborhoodCirculator<SrcIterator, Neighborhood3D> c( xs), cend(c);
do { do {
if(sa(c) < v) if(sa(c) < v)
{ {
v = sa(c); v = sa(c);
o = c.directionBit(); o = c.directionBit();
} }
else if(sa(c) == my_v && my_v == v) else if(sa(c) == my_v && my_v == v)
{ {
o = o | c.directionBit(); o = o | c.directionBit();
} }
} }
while(++c != cend); while(++c != cend);
} }
else else
{ {
#if 0
RestrictedNeighborhoodTraverser<SrcIterator, Neighborho
od3D> c(xs, atBorder), cend(c);
#endif /* #if 0 */
RestrictedNeighborhoodCirculator<SrcIterator, Neighborh ood3D> c(xs, atBorder), cend(c); RestrictedNeighborhoodCirculator<SrcIterator, Neighborh ood3D> c(xs, atBorder), cend(c);
do { do {
if(sa(c) < v) if(sa(c) < v)
{ {
v = sa(c); v = sa(c);
o = c.directionBit(); o = c.directionBit();
} }
else if(sa(c) == my_v && my_v == v) else if(sa(c) == my_v && my_v == v)
{ {
o = o | c.directionBit(); o = o | c.directionBit();
skipping to change at line 139 skipping to change at line 130
return local_min_count; return local_min_count;
} }
template <class SrcIterator, class SrcAccessor,class SrcShape, template <class SrcIterator, class SrcAccessor,class SrcShape,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class Neighborhood3D> class Neighborhood3D>
unsigned int watershedLabeling3D( SrcIterator s_Iter, SrcShape srcShape, Sr cAccessor sa, unsigned int watershedLabeling3D( SrcIterator s_Iter, SrcShape srcShape, Sr cAccessor sa,
DestIterator d_Iter, DestAccessor da, DestIterator d_Iter, DestAccessor da,
Neighborhood3D) Neighborhood3D)
{ {
typedef typename DestAccessor::value_type LabelType;
//basically needed for iteration and border-checks //basically needed for iteration and border-checks
int w = srcShape[0], h = srcShape[1], d = srcShape[2]; int w = srcShape[0], h = srcShape[1], d = srcShape[2];
int x,y,z, i; int x,y,z;
//declare and define Iterators for all three dims at src //declare and define Iterators for all three dims at src
SrcIterator zs = s_Iter; SrcIterator zs = s_Iter;
SrcIterator ys(zs); DestIterator zd = d_Iter;
SrcIterator xs(ys);
// temporary image to store region labels // temporary image to store region labels
typedef vigra::MultiArray<3,int> LabelVolume; detail::UnionFindArray<LabelType> labels;
typedef LabelVolume::traverser LabelTraverser;
LabelVolume labelvolume(srcShape);
//Declare traversers for all three dims at target
LabelTraverser zt = labelvolume.traverser_begin();
LabelTraverser yt(zt);
LabelTraverser xt(yt);
// Kovalevsky's clever idea to use
// image iterator and scan order iterator simultaneously
// memory order indicates label
LabelVolume::iterator label = labelvolume.begin();
// initialize the neighborhood traversers // initialize the neighborhood traversers
#if 0
NeighborOffsetTraverser<Neighborhood3D> nc(Neighborhood3D::CausalFirst)
;
NeighborOffsetTraverser<Neighborhood3D> nce(Neighborhood3D::CausalLast)
;
#endif /* #if 0 */
NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhood3D::CausalFirst ); NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhood3D::CausalFirst );
NeighborOffsetCirculator<Neighborhood3D> nce(Neighborhood3D::CausalLast ); NeighborOffsetCirculator<Neighborhood3D> nce(Neighborhood3D::CausalLast );
++nce; ++nce;
// pass 1: scan image from upper left front to lower right back // pass 1: scan image from upper left front to lower right back
// to find connected components // to find connected components
// Each component will be represented by a tree of pixels. Each // Each component will be represented by a tree of pixels. Each
// pixel contains the scan order address of its parent in the // pixel contains the scan order address of its parent in the
// tree. In order for pass 2 to work correctly, the parent must // tree. In order for pass 2 to work correctly, the parent must
// always have a smaller scan order address than the child. // always have a smaller scan order address than the child.
// Therefore, we can merge trees only at their roots, because the // Therefore, we can merge trees only at their roots, because the
// root of the combined tree must have the smallest scan order // root of the combined tree must have the smallest scan order
// address among all the tree's pixels/ nodes. The root of each // address among all the tree's pixels/ nodes. The root of each
// tree is distinguished by pointing to itself (it contains its // tree is distinguished by pointing to itself (it contains its
// own scan order address). This condition is enforced whenever a // own scan order address). This condition is enforced whenever a
// new region is found or two regions are merged // new region is found or two regions are merged
i=0; for(z = 0; z != d; ++z, ++zs.dim2(), ++zd.dim2())
for(z = 0; z != d; ++z, ++zs.dim2(), ++zt.dim2())
{ {
ys = zs; SrcIterator ys = zs;
yt = zt; DestIterator yd = zd;
for(y = 0; y != h; ++y, ++ys.dim1(), ++yt.dim1()) for(y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1())
{ {
xs = ys; SrcIterator xs = ys;
xt = yt; DestIterator xd = yd;
for(x = 0; x != w; ++x, ++xs.dim0(), ++xt.dim0(), ++i) for(x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0())
{ {
*xt = i; // default: new region LabelType currentLabel = labels.nextFreeLabel(); // default : new region
//queck whether there is a special borde threatment to be u sed or not //queck whether there is a special borde threatment to be u sed or not
AtVolumeBorder atBorder = isAtVolumeBorderCausal(x,y,z,w,h, z); AtVolumeBorder atBorder = isAtVolumeBorderCausal(x,y,z,w,h, z);
//We are not at the border! //We are not at the border!
if(atBorder == NotAtBorder) if(atBorder == NotAtBorder)
{ {
#if 0
nc = NeighborOffsetTraverser<Neighborhood3D>(Neighborho
od3D::CausalFirst);
#endif /* #if 0 */
nc = NeighborOffsetCirculator<Neighborhood3D>(Neighborh ood3D::CausalFirst); nc = NeighborOffsetCirculator<Neighborhood3D>(Neighborh ood3D::CausalFirst);
do do
{ {
// Direction of NTraversr Neighbor's direct ion bit is pointing // Direction of NTraversr Neighbor's direct ion bit is pointing
// = Direction of voxel towards us? // = Direction of voxel towards us?
if((*xs & nc.directionBit()) || (xs[*nc] & nc.oppos iteDirectionBit())) if((sa(xs) & nc.directionBit()) || (sa(xs,*nc) & nc .oppositeDirectionBit()))
{ {
int neighborLabel = xt[*nc]; currentLabel = labels.makeUnion(da(xd,*nc), cur
rentLabel);
// find the root label of a label tree
while(neighborLabel != label[neighborLabel])
{
neighborLabel = label[neighborLabel];
}
if(neighborLabel < *xt) // always keep the smal
lest among the possible neighbor labels
{
label[*xt] = neighborLabel;
*xt = neighborLabel;
}
else
{
label[neighborLabel] = *xt;
}
} }
++nc; ++nc;
}while(nc!=nce); }while(nc!=nce);
} }
//we are at a border - handle this!! //we are at a border - handle this!!
else else
{ {
#if 0
nc = NeighborOffsetTraverser<Neighborhood3D>(Neighborho
od3D::nearBorderDirectionsCausal(atBorder,0));
#endif /* #if 0 */
nc = NeighborOffsetCirculator<Neighborhood3D>(Neighborh ood3D::nearBorderDirectionsCausal(atBorder,0)); nc = NeighborOffsetCirculator<Neighborhood3D>(Neighborh ood3D::nearBorderDirectionsCausal(atBorder,0));
int j=0; int j=0;
while(nc.direction() != Neighborhood3D::Error) while(nc.direction() != Neighborhood3D::Error)
{ {
// Direction of NTraversr Neighbor's direct ion bit is pointing // Direction of NTraversr Neighbor's direct ion bit is pointing
// = Direction of voxel towards us? // = Direction of voxel towards us?
if((*xs & nc.directionBit()) || (xs[*nc] & nc.oppos iteDirectionBit())) if((sa(xs) & nc.directionBit()) || (sa(xs,*nc) & nc .oppositeDirectionBit()))
{ {
int neighborLabel = xt[*nc]; currentLabel = labels.makeUnion(da(xd,*nc), cur
rentLabel);
// find the root label of a label tree
while(neighborLabel != label[neighborLabel])
{
neighborLabel = label[neighborLabel];
}
if(neighborLabel < *xt) // always keep the smal
lest among the possible neighbor labels
{
label[*xt] = neighborLabel;
*xt = neighborLabel;
}
else
{
label[neighborLabel] = *xt;
}
} }
nc.turnTo(Neighborhood3D::nearBorderDirectionsCausa l(atBorder,++j)); nc.turnTo(Neighborhood3D::nearBorderDirectionsCausa l(atBorder,++j));
} }
} }
da.set(labels.finalizeLabel(currentLabel), xd);
} }
} }
} }
unsigned int count = labels.makeContiguous();
// pass 2: assign one label to each region (tree) // pass 2: assign one label to each region (tree)
// so that labels form a consecutive sequence 1, 2, ... // so that labels form a consecutive sequence 1, 2, ...
DestIterator zd = d_Iter; zd = d_Iter;
unsigned int count = 0;
i= 0;
for(z=0; z != d; ++z, ++zd.dim2()) for(z=0; z != d; ++z, ++zd.dim2())
{ {
DestIterator yd(zd); DestIterator yd(zd);
for(y=0; y != h; ++y, ++yd.dim1()) for(y=0; y != h; ++y, ++yd.dim1())
{ {
DestIterator xd(yd); DestIterator xd(yd);
for(x = 0; x != w; ++x, ++xd.dim0(), ++i) for(x = 0; x != w; ++x, ++xd.dim0())
{ {
if(label[i] == i) da.set(labels[da(xd)], xd);
{
label[i] = count++;
}
else
{
label[i] = label[label[i]]; // compress trees
}
da.set(label[i]+1, xd);
} }
} }
} }
return count; return count;
} }
/** \addtogroup SeededRegionGrowing Region Segmentation Algorithms /** \addtogroup SeededRegionGrowing Region Segmentation Algorithms
Region growing, watersheds, and voronoi tesselation Region growing, watersheds, and voronoi tesselation
*/ */
//@{ //@{
skipping to change at line 459 skipping to change at line 380
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class Neighborhood3D> class Neighborhood3D>
unsigned int watersheds3D( SrcIterator s_Iter, SrcShape srcShape, SrcAccess or sa, unsigned int watersheds3D( SrcIterator s_Iter, SrcShape srcShape, SrcAccess or sa,
DestIterator d_Iter, DestAccessor da, Neighborho od3D neighborhood3D) DestIterator d_Iter, DestAccessor da, Neighborho od3D neighborhood3D)
{ {
//create temporary volume to store the DAG of directions to minima //create temporary volume to store the DAG of directions to minima
if ((int)Neighborhood3D::DirectionCount>7){ //If we have 3D-TwentySix Neighborhood if ((int)Neighborhood3D::DirectionCount>7){ //If we have 3D-TwentySix Neighborhood
vigra::MultiArray<3,int> orientationVolume(srcShape); vigra::MultiArray<3,int> orientationVolume(srcShape);
int local_min_count= preparewatersheds3D( s_Iter, srcShape, sa, preparewatersheds3D( s_Iter, srcShape, sa,
destMultiArray(orientatio destMultiArray(orientationVolume).first, destM
nVolume).first, destMultiArray(orientationVolume).second, ultiArray(orientationVolume).second,
neighborhood3D); neighborhood3D);
return watershedLabeling3D( srcMultiArray(orientationVolume).first, srcShape, srcMultiArray(orientationVolume).second, return watershedLabeling3D( srcMultiArray(orientationVolume).first, srcShape, srcMultiArray(orientationVolume).second,
d_Iter, da, d_Iter, da,
neighborhood3D); neighborhood3D);
} }
else{ else{
vigra::MultiArray<3,unsigned char> orientationVolume(srcShape); vigra::MultiArray<3,unsigned char> orientationVolume(srcShape);
int local_min_count= preparewatersheds3D( s_Iter, srcShape, sa, preparewatersheds3D( s_Iter, srcShape, sa,
destMultiArray(orientatio destMultiArray(orientationVolume).first, dest
nVolume).first, destMultiArray(orientationVolume).second, MultiArray(orientationVolume).second,
neighborhood3D); neighborhood3D);
return watershedLabeling3D( srcMultiArray(orientationVolume).first, srcShape, srcMultiArray(orientationVolume).second, return watershedLabeling3D( srcMultiArray(orientationVolume).first, srcShape, srcMultiArray(orientationVolume).second,
d_Iter, da, d_Iter, da,
neighborhood3D); neighborhood3D);
} }
} }
template <class SrcIterator, class SrcShape, class SrcAccessor, template <class SrcIterator, class SrcShape, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline unsigned int watersheds3DSix( vigra::triple<SrcIterator, SrcShape, S rcAccessor> src, inline unsigned int watersheds3DSix( vigra::triple<SrcIterator, SrcShape, S rcAccessor> src,
 End of changes. 30 change blocks. 
120 lines changed or deleted 35 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/