Ask Your Question
1

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

asked 2012-08-01 18:44:01 -0600

LoopUniverse gravatar image

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 flag offensive close merge delete

1 answer

Sort by » oldest newest most voted
1

answered 2012-08-02 01:49:28 -0600

sammy gravatar image

updated 2012-08-02 07:24:50 -0600

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 floating and integer

When a finite value of real floating 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 undefined.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
}
edit flag offensive delete link more

Question Tools

Stats

Asked: 2012-08-01 18:44:01 -0600

Seen: 3,149 times

Last updated: Aug 02 '12