如何在不使用OpenCV中的内置函数翻转的情况下进行翻转?

时间:2015-10-10 15:03:01

标签: opencv opencv3.0

任何人都可以帮我解决这个问题,如何在不使用内置翻转功能的情况下翻转图像,即使用OpenCV在C ++中翻转(src图像,目标图像,1或0)。我是这个软件的新手所以请帮助。

2 个答案:

答案 0 :(得分:1)

OpenCV的翻转功能使用内部flipHoriz or flipVert功能。

static void
flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
{
    int i, j, limit = (int)(((size.width + 1)/2)*esz);
    AutoBuffer<int> _tab(size.width*esz);
    int* tab = _tab;

    for( i = 0; i < size.width; i++ )
        for( size_t k = 0; k < esz; k++ )
            tab[i*esz + k] = (int)((size.width - i - 1)*esz + k);

    for( ; size.height--; src += sstep, dst += dstep )
    {
        for( i = 0; i < limit; i++ )
        {
            j = tab[i];
            uchar t0 = src[i], t1 = src[j];
            dst[i] = t1; dst[j] = t0;
        }
    }
}

static void
flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, size_t esz )
{
    const uchar* src1 = src0 + (size.height - 1)*sstep;
    uchar* dst1 = dst0 + (size.height - 1)*dstep;
    size.width *= (int)esz;

    for( int y = 0; y < (size.height + 1)/2; y++, src0 += sstep, src1 -= sstep,
                                                  dst0 += dstep, dst1 -= dstep )
    {
        int i = 0;
        if( ((size_t)src0|(size_t)dst0|(size_t)src1|(size_t)dst1) % sizeof(int) == 0 )
        {
            for( ; i <= size.width - 16; i += 16 )
            {
                int t0 = ((int*)(src0 + i))[0];
                int t1 = ((int*)(src1 + i))[0];

                ((int*)(dst0 + i))[0] = t1;
                ((int*)(dst1 + i))[0] = t0;

                t0 = ((int*)(src0 + i))[1];
                t1 = ((int*)(src1 + i))[1];

                ((int*)(dst0 + i))[1] = t1;
                ((int*)(dst1 + i))[1] = t0;

                t0 = ((int*)(src0 + i))[2];
                t1 = ((int*)(src1 + i))[2];

                ((int*)(dst0 + i))[2] = t1;
                ((int*)(dst1 + i))[2] = t0;

                t0 = ((int*)(src0 + i))[3];
                t1 = ((int*)(src1 + i))[3];

                ((int*)(dst0 + i))[3] = t1;
                ((int*)(dst1 + i))[3] = t0;
            }

            for( ; i <= size.width - 4; i += 4 )
            {
                int t0 = ((int*)(src0 + i))[0];
                int t1 = ((int*)(src1 + i))[0];

                ((int*)(dst0 + i))[0] = t1;
                ((int*)(dst1 + i))[0] = t0;
            }
        }

        for( ; i < size.width; i++ )
        {
            uchar t0 = src0[i];
            uchar t1 = src1[i];

            dst0[i] = t1;
            dst1[i] = t0;
        }
    }
}

//您可以使用下面的小修改

void myflip( InputArray _src, OutputArray _dst, int flip_mode )
{
CV_Assert( _src.dims() <= 2 );
Size size = _src.size();

if (flip_mode < 0)
{
    if (size.width == 1)
        flip_mode = 0;
    if (size.height == 1)
        flip_mode = 1;
}

if ((size.width == 1 && flip_mode > 0) ||
    (size.height == 1 && flip_mode == 0) ||
    (size.height == 1 && size.width == 1 && flip_mode < 0))
{
    return _src.copyTo(_dst);
}

Mat src = _src.getMat();
int type = src.type();
_dst.create( size, type );
Mat dst = _dst.getMat();

size_t esz = CV_ELEM_SIZE(type);

if( flip_mode <= 0 )
    flipVert( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
else
    flipHoriz( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );

if( flip_mode < 0 )
    flipHoriz( dst.ptr(), dst.step, dst.ptr(), dst.step, dst.size(), esz );
}

答案 1 :(得分:0)

假设您有充分的理由不使用OpenCV flip功能,您可以编写自定义功能。

对于此示例,我将使用CV_8UC3图像。我将在最后指出如何将其扩展为不同的格式。

让我们首先看一下如何翻转图像x轴,它对应于cv::flip(src, dst, 1)。给定src图像,dst图像将具有相同的y坐标,x坐标为src.cols - 1 - x坐标。在实践中:

void flip_lr(const Mat3b& src, Mat3b& dst)
{
    Mat3b _dst(src.rows, src.cols);
    for (int r = 0; r < _dst.rows; ++r) {
        for (int c = 0; c < _dst.cols; ++c) {
            _dst(r, c) = src(r, src.cols - 1 - c);
        }
    }
    dst = _dst;
}

然后,要绕y轴(对应cv::flip(src, dst, 0)),dst将具有相同的x坐标,y将为src.rows - 1 - y。但是,您可以重复使用上述功能,只需转置dst矩阵,在x轴上应用翻转,然后转置回来。在实践中:

dst = src.t();
flip_lr(dst, dst);
dst = dst.t();

然后,要翻转两个轴,对应cv::flip(src, dst, -1),您只需要在x和y轴上组合翻转:

flip_lr(src, dst);
dst = dst.t();
flip_lr(dst, dst);
dst = dst.t();

您可以将此功能包含在自定义翻转函数中,该函数采用与cv::flip相同的参数:

void custom_flip(const Mat3b& src, Mat3b& dst, int code)
{
    if (code > 0)
    {   // Flip x axis
        flip_lr(src, dst);
    }
    else if (code == 0)
    {
        // Flip y axis
        dst = src.t();
        flip_lr(dst, dst);
        dst = dst.t();
    }
    else // code < 0
    {
        // Flip x and y axis
        flip_lr(src, dst);
        dst = dst.t();
        flip_lr(dst, dst);
        dst = dst.t();
    }
}

请注意,您可以将其调整为不同的格式,只需修改flip_lr函数,并注意在custom_flip内调用相应的版本,现在将接受Mat而不是{{ 1}}。

完整的参考代码:

Mat3b