Extend-Robotics / camera_aravis

A ROS1 driver for GenICam based GigE and USB3 cameras.
Other
1 stars 1 forks source link

make sure FloatToUint pixel format adapter rounds #17

Closed bmegli closed 1 year ago

bmegli commented 1 year ago

Otherwise it will introduce errors of up to 1 unit (as opposed to 1/2 unit)

bmegli commented 1 year ago

https://github.com/Extend-Robotics/camera_aravis/blob/64e2b421131af630e644395f6f8cfad45adf26bc/src/conversion_utils.cpp#L430

https://github.com/Extend-Robotics/camera_aravis/blob/64e2b421131af630e644395f6f8cfad45adf26bc/src/conversion_utils.cpp#L464-L470

bmegli commented 1 year ago

Investigating OpenCV convertTo

https://github.com/opencv/opencv/blob/96f23e3da1d304a6582514542843b5a3ef740a1a/modules/core/src/convert.dispatch.cpp#L205-L214

    BinaryFunc func = noScale ? getConvertFunc(sdepth, ddepth) : getConvertScaleFunc(sdepth, ddepth);
    double scale[] = {alpha, beta};
    int cn = channels();
    CV_Assert( func != 0 );

    if( dims <= 2 )
    {
        Size sz = getContinuousSize2D(src, dst, cn);
        func( src.data, src.step, 0, 0, dst.data, dst.step, sz, scale );
    }

```C

BinaryFunc getConvertFunc(int sdepth, int ddepth)
{
    CV_INSTRUMENT_REGION();
    CV_CPU_DISPATCH(getConvertFunc, (sdepth, ddepth),
        CV_CPU_DISPATCH_MODES_ALL);
}
bmegli commented 1 year ago

Easier to investigate with older OpenCV

DEF_CVT_SCALE_FUNC(32f16u, float, ushort, float);
DEF_CVT_FUNC(32f16u, float, ushort);
bmegli commented 1 year ago
#define DEF_CVT_SCALE_FUNC(suffix, stype, dtype, wtype) \
static void cvtScale##suffix( const stype* src, size_t sstep, const uchar*, size_t, \
dtype* dst, size_t dstep, Size size, double* scale) \
{ \
    cvtScale_(src, sstep, dst, dstep, size, (wtype)scale[0], (wtype)scale[1]); \
}

#define DEF_CVT_FUNC(suffix, stype, dtype) \
static void cvt##suffix( const stype* src, size_t sstep, const uchar*, size_t, \
                         dtype* dst, size_t dstep, Size size, double*) \
{ \
    cvt_(src, sstep, dst, dstep, size); \
}
bmegli commented 1 year ago

The most basic variant in the past

template<typename T, typename DT> static void
cvt_( const T* src, size_t sstep,
      DT* dst, size_t dstep, Size size )
{
    sstep /= sizeof(src[0]);
    dstep /= sizeof(dst[0]);

    for( ; size.height--; src += sstep, dst += dstep )
    {
        int x = 0;
        #if CV_ENABLE_UNROLLED
        for( ; x <= size.width - 4; x += 4 )
        {
            DT t0, t1;
            t0 = saturate_cast<DT>(src[x]);
            t1 = saturate_cast<DT>(src[x+1]);
            dst[x] = t0; dst[x+1] = t1;
            t0 = saturate_cast<DT>(src[x+2]);
            t1 = saturate_cast<DT>(src[x+3]);
            dst[x+2] = t0; dst[x+3] = t1;
        }
        #endif
        for( ; x < size.width; x++ )
            dst[x] = saturate_cast<DT>(src[x]);
    }
}
bmegli commented 1 year ago
template<> inline ushort saturate_cast<ushort>(float v)
{ int iv = cvRound(v); return saturate_cast<ushort>(iv); }
template<> inline ushort saturate_cast<ushort>(int v)
{ return (ushort)((unsigned)v <= (unsigned)USHRT_MAX ? v : v > 0 ? USHRT_MAX : 0); }

So it was

bmegli commented 1 year ago

That was just one of many potential paths in OpenCV (and old one) but let's assume other are consistent