OpenCV函数cvRemap源代码

cvRemap源代码

void cv::remap( InputArray _src, OutputArray _dst,
                InputArray _map1, InputArray _map2,
                int interpolation, int borderType, const Scalar& borderValue )
{
    static RemapNNFunc nn_tab[] =
    {
        remapNearest<uchar>, remapNearest<schar>, remapNearest<ushort>, remapNearest<short>,
        remapNearest<int>, remapNearest<float>, remapNearest<double>, 0
    };

    static RemapFunc linear_tab[] =
    {
        remapBilinear<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, RemapVec_8u, short>, 0,
        remapBilinear<Cast<float, ushort>, RemapNoVec, float>,
        remapBilinear<Cast<float, short>, RemapNoVec, float>, 0,
        remapBilinear<Cast<float, float>, RemapNoVec, float>,
        remapBilinear<Cast<double, double>, RemapNoVec, float>, 0
    };

    static RemapFunc cubic_tab[] =
    {
        remapBicubic<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, short, INTER_REMAP_COEF_SCALE>, 0,
        remapBicubic<Cast<float, ushort>, float, 1>,
        remapBicubic<Cast<float, short>, float, 1>, 0,
        remapBicubic<Cast<float, float>, float, 1>,
        remapBicubic<Cast<double, double>, float, 1>, 0
    };

    static RemapFunc lanczos4_tab[] =
    {
        remapLanczos4<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, short, INTER_REMAP_COEF_SCALE>, 0,
        remapLanczos4<Cast<float, ushort>, float, 1>,
        remapLanczos4<Cast<float, short>, float, 1>, 0,
        remapLanczos4<Cast<float, float>, float, 1>,
        remapLanczos4<Cast<double, double>, float, 1>, 0
    };

    Mat src = _src.getMat(), map1 = _map1.getMat(), map2 = _map2.getMat();
    
    CV_Assert( (!map2.data || map2.size() == map1.size()));
    
    _dst.create( map1.size(), src.type() );
    Mat dst = _dst.getMat();
    if( dst.data == src.data )
        src = src.clone();

    int depth = src.depth(), map_depth = map1.depth();
    RemapNNFunc nnfunc = 0;
    RemapFunc ifunc = 0;
    const void* ctab = 0;
    bool fixpt = depth == CV_8U;
    bool planar_input = false;

    if( interpolation == INTER_NEAREST )
    {
        nnfunc = nn_tab[depth];
        CV_Assert( nnfunc != 0 );

        if( map1.type() == CV_16SC2 && !map2.data ) // the data is already in the right format
        {
            nnfunc( src, dst, map1, borderType, borderValue );
            return;
        }
    }
    else
    {
        if( interpolation == INTER_AREA )
            interpolation = INTER_LINEAR;

        if( interpolation == INTER_LINEAR )
            ifunc = linear_tab[depth];
        else if( interpolation == INTER_CUBIC )
            ifunc = cubic_tab[depth];
        else if( interpolation == INTER_LANCZOS4 )
            ifunc = lanczos4_tab[depth];
        else
            CV_Error( CV_StsBadArg, "Unknown interpolation method" );
        CV_Assert( ifunc != 0 );
        ctab = initInterTab2D( interpolation, fixpt );
    }

    const Mat *m1 = &map1, *m2 = &map2;

    if( (map1.type() == CV_16SC2 && (map2.type() == CV_16UC1 || map2.type() == CV_16SC1)) ||
        (map2.type() == CV_16SC2 && (map1.type() == CV_16UC1 || map1.type() == CV_16SC1)) )
    {
        if( map1.type() != CV_16SC2 )
            std::swap(m1, m2);
        if( ifunc )
        {
            ifunc( src, dst, *m1, *m2, ctab, borderType, borderValue );
            return;
        }
    }
    else
    {
        CV_Assert( (map1.type() == CV_32FC2 && !map2.data) ||
            (map1.type() == CV_32FC1 && map2.type() == CV_32FC1) );
        planar_input = map1.channels() == 1;
    }

    int x, y, x1, y1;
    const int buf_size = 1 << 14;
    int brows0 = std::min(128, dst.rows);
    int bcols0 = std::min(buf_size/brows0, dst.cols);
    brows0 = std::min(buf_size/bcols0, dst.rows);
#if CV_SSE2
    bool useSIMD = checkHardwareSupport(CV_CPU_SSE2);
#endif

    Mat _bufxy(brows0, bcols0, CV_16SC2), _bufa;
    if( !nnfunc )
        _bufa.create(brows0, bcols0, CV_16UC1);

    for( y = 0; y < dst.rows; y += brows0 )
    {
        for( x = 0; x < dst.cols; x += bcols0 )
        {
            int brows = std::min(brows0, dst.rows - y);
            int bcols = std::min(bcols0, dst.cols - x);
            Mat dpart(dst, Rect(x, y, bcols, brows));
            Mat bufxy(_bufxy, Rect(0, 0, bcols, brows));

            if( nnfunc )
            {
                if( map_depth != CV_32F )
                {
                    for( y1 = 0; y1 < brows; y1++ )
                    {
                        short* XY = (short*)(bufxy.data + bufxy.step*y1);
                        const short* sXY = (const short*)(m1->data + m1->step*(y+y1)) + x*2;
                        const ushort* sA = (const ushort*)(m2->data + m2->step*(y+y1)) + x;

                        for( x1 = 0; x1 < bcols; x1++ )
                        {
                            int a = sA[x1] & (INTER_TAB_SIZE2-1);
                            XY[x1*2] = sXY[x1*2] + NNDeltaTab_i[a][0];
                            XY[x1*2+1] = sXY[x1*2+1] + NNDeltaTab_i[a][1];
                        }
                    }
                }
                else if( !planar_input )
                    map1(Rect(0,0,bcols,brows)).convertTo(bufxy, bufxy.depth());
                else
                {
                    for( y1 = 0; y1 < brows; y1++ )
                    {
                        short* XY = (short*)(bufxy.data + bufxy.step*y1);
                        const float* sX = (const float*)(map1.data + map1.step*(y+y1)) + x;
                        const float* sY = (const float*)(map2.data + map2.step*(y+y1)) + x;
                        x1 = 0;

                    #if CV_SSE2
                        if( useSIMD )
                        {
                            for( ; x1 <= bcols - 8; x1 += 8 )
                            {
                                __m128 fx0 = _mm_loadu_ps(sX + x1);
                                __m128 fx1 = _mm_loadu_ps(sX + x1 + 4);
                                __m128 fy0 = _mm_loadu_ps(sY + x1);
                                __m128 fy1 = _mm_loadu_ps(sY + x1 + 4);
                                __m128i ix0 = _mm_cvtps_epi32(fx0);
                                __m128i ix1 = _mm_cvtps_epi32(fx1);
                                __m128i iy0 = _mm_cvtps_epi32(fy0);
                                __m128i iy1 = _mm_cvtps_epi32(fy1);
                                ix0 = _mm_packs_epi32(ix0, ix1);
                                iy0 = _mm_packs_epi32(iy0, iy1);
                                ix1 = _mm_unpacklo_epi16(ix0, iy0);
                                iy1 = _mm_unpackhi_epi16(ix0, iy0);
                                _mm_storeu_si128((__m128i*)(XY + x1*2), ix1);
                                _mm_storeu_si128((__m128i*)(XY + x1*2 + 8), iy1);
                            }
                        }
                    #endif

                        for( ; x1 < bcols; x1++ )
                        {
                            XY[x1*2] = saturate_cast<short>(sX[x1]);
                            XY[x1*2+1] = saturate_cast<short>(sY[x1]);
                        }
                    }
                }
                nnfunc( src, dpart, bufxy, borderType, borderValue );
                continue;
            }

            Mat bufa(_bufa, Rect(0,0,bcols, brows));
            for( y1 = 0; y1 < brows; y1++ )
            {
                short* XY = (short*)(bufxy.data + bufxy.step*y1);
                ushort* A = (ushort*)(bufa.data + bufa.step*y1);

                if( planar_input )
                {
                    const float* sX = (const float*)(map1.data + map1.step*(y+y1)) + x;
                    const float* sY = (const float*)(map2.data + map2.step*(y+y1)) + x;

                    x1 = 0;
                #if CV_SSE2
                    if( useSIMD )
                    {
                        __m128 scale = _mm_set1_ps((float)INTER_TAB_SIZE);
                        __m128i mask = _mm_set1_epi32(INTER_TAB_SIZE-1);
                        for( ; x1 <= bcols - 8; x1 += 8 )
                        {
                            __m128 fx0 = _mm_loadu_ps(sX + x1);
                            __m128 fx1 = _mm_loadu_ps(sX + x1 + 4);
                            __m128 fy0 = _mm_loadu_ps(sY + x1);
                            __m128 fy1 = _mm_loadu_ps(sY + x1 + 4);
                            __m128i ix0 = _mm_cvtps_epi32(_mm_mul_ps(fx0, scale));
                            __m128i ix1 = _mm_cvtps_epi32(_mm_mul_ps(fx1, scale));
                            __m128i iy0 = _mm_cvtps_epi32(_mm_mul_ps(fy0, scale));
                            __m128i iy1 = _mm_cvtps_epi32(_mm_mul_ps(fy1, scale));
                            __m128i mx0 = _mm_and_si128(ix0, mask);
                            __m128i mx1 = _mm_and_si128(ix1, mask);
                            __m128i my0 = _mm_and_si128(iy0, mask);
                            __m128i my1 = _mm_and_si128(iy1, mask);
                            mx0 = _mm_packs_epi32(mx0, mx1);
                            my0 = _mm_packs_epi32(my0, my1);
                            my0 = _mm_slli_epi16(my0, INTER_BITS);
                            mx0 = _mm_or_si128(mx0, my0);
                            _mm_storeu_si128((__m128i*)(A + x1), mx0);
                            ix0 = _mm_srai_epi32(ix0, INTER_BITS);
                            ix1 = _mm_srai_epi32(ix1, INTER_BITS);
                            iy0 = _mm_srai_epi32(iy0, INTER_BITS);
                            iy1 = _mm_srai_epi32(iy1, INTER_BITS);
                            ix0 = _mm_packs_epi32(ix0, ix1);
                            iy0 = _mm_packs_epi32(iy0, iy1);
                            ix1 = _mm_unpacklo_epi16(ix0, iy0);
                            iy1 = _mm_unpackhi_epi16(ix0, iy0);
                            _mm_storeu_si128((__m128i*)(XY + x1*2), ix1);
                            _mm_storeu_si128((__m128i*)(XY + x1*2 + 8), iy1);
                        }
                    }
                #endif

                    for( ; x1 < bcols; x1++ )
                    {
                        int sx = cvRound(sX[x1]*INTER_TAB_SIZE);
                        int sy = cvRound(sY[x1]*INTER_TAB_SIZE);
                        int v = (sy & (INTER_TAB_SIZE-1))*INTER_TAB_SIZE + (sx & (INTER_TAB_SIZE-1));
                        XY[x1*2] = (short)(sx >> INTER_BITS);
                        XY[x1*2+1] = (short)(sy >> INTER_BITS);
                        A[x1] = (ushort)v;
                    }
                }
                else
                {
                    const float* sXY = (const float*)(map1.data + map1.step*(y+y1)) + x*2;

                    for( x1 = 0; x1 < bcols; x1++ )
                    {
                        int sx = cvRound(sXY[x1*2]*INTER_TAB_SIZE);
                        int sy = cvRound(sXY[x1*2+1]*INTER_TAB_SIZE);
                        int v = (sy & (INTER_TAB_SIZE-1))*INTER_TAB_SIZE + (sx & (INTER_TAB_SIZE-1));
                        XY[x1*2] = (short)(sx >> INTER_BITS);
                        XY[x1*2+1] = (short)(sy >> INTER_BITS);
                        A[x1] = (ushort)v;
                    }
                }
            }
            ifunc(src, dpart, bufxy, bufa, ctab, borderType, borderValue);
        }
    }
}


评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值