# Behavior of "Not-a-Number" (NaN) values in remap

In the cv::remap function, is the behavior specified when values in the "map" arrays are NaN (not-a-number)? Or is the behavior unspecified and having NaN's in the "map" arrays should simply not be done?

The behavior I am seeing (v2.4.1) is pixels where the map value are NaN, the destination value corresponds to the "source image" value at coordinate (0, 0). This appears to be true regardless of the border mode I use.

edit retag close merge delete

Sort by » oldest newest most voted

NaN's are not explicitely handled by remap().

What it happens there is that you convert a floating point value of NaN to integer (to use it as index in the src matrix). Cf to the C standard,

6.3.1.4 Real ﬂoating and integer

When a ﬁnite value of real ﬂoating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undeﬁned.50)

Probably, in your case, the behavoiur is to map NaN's to 0. So, when you access src(NaN, NaN) you actually see src(0, 0), but it's a good chance that it will crash with a different compiler/architecture/processor

The intended way to handle pixels that are not defined in the source image is to set them as real values outside the src image:

x,y < 0, 0


or

x, y > width-1, height-1


When this happens, they are treated according to the two border parameters (borderType, borderValue)

Update

I've checked on Win7, VS2010, and (unsigned int)NaN is 0, confirming your finding.

Bonus

If you really want to know what's inside, here is the OpenCV procedure called by saturate_cast<int>, which is called by convertMaps() which in turn is called by remap(). It converts the float coordinates into a complicated mesh of integer math, by rounding and shifts.

CV_INLINE  int  cvRound( double value )
{
#if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ && defined __SSE2__ && !defined __APPLE__)
__m128d t = _mm_set_sd( value );
return _mm_cvtsd_si32(t);
#elif defined _MSC_VER && defined _M_IX86
int t;
__asm
{
fld value;
fistp t;
}
return t;
#elif defined HAVE_LRINT || defined CV_ICC || defined __GNUC__
#  ifdef HAVE_TEGRA_OPTIMIZATION
TEGRA_ROUND(value);
#  else
return (int)lrint(value);
#  endif
#else
// while this is not IEEE754-compliant rounding, it's usually a good enough approximation
return (int)(value + (value >= 0 ? 0.5 : -0.5));
#endif
}

more

Official site

GitHub

Wiki

Documentation