Eigen functions of the day: normalize() and stableNormalize().

c-plus-plus eigen

In computer vision, I find myself needing unit vectors, a lot. In other words, doing the following in C++,

Vector3d v;

// v's unnormalized value is computed. 

v /= v.norm();

I also need image homogenous coordinates ‘normalized’, in other words, dividing the vector by the third element (scale):

Vector3d v;

// v's unnormalized value is computed. Something like v = P*X;

v /= v(2);

I looked up the Eigen function normalize(), docs, and normalize() will return a unit vector - the first case I mention. Here’s the Eigen code:

// from Dot.h
template<typename Derived>
inline void MatrixBase<Derived>::normalize()
{
  RealScalar z = squaredNorm();
  // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU
  if(z>RealScalar(0))
    derived() /= numext::sqrt(z);
}

So one could write

Vector3d v;

// v's unnormalized value is computed. 

v.normalize();

oohhh but then by poking around in the .h files (which I really recommend), I came across stableNormalize(), docs, which computes the unit vector (of a non-zero vector) whole reducing under- and over-flow risks:

/** Normalizes the vector while avoid underflow and overflow
  *
  * \only_for_vectors
  *
  * This method is analogue to the normalize() method, but it reduces the risk of
  * underflow and overflow when computing the norm.
  *
  * \warning If the input vector is too small (i.e., this->norm()==0), then \c *this is left unchanged.
  *
  * \sa stableNorm(), stableNormalized(), normalize()
  */
template<typename Derived>
inline void MatrixBase<Derived>::stableNormalize()
{
  RealScalar w = cwiseAbs().maxCoeff();
  RealScalar z = (derived()/w).squaredNorm();
  if(z>RealScalar(0))
    derived() /= numext::sqrt(z)*w;
}

and the function can be used like this:

Vector3d v;

// v's unnormalized value is computed. 

v.stableNormalize();

© Amy Tabb 2018 - 2023. All rights reserved. The contents of this site reflect my personal perspectives and not those of any other entity.