Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

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 undefined 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)

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():

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
}

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 undefined 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)

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
}

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 (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
}

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 (int)NaN(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
}