如何在不使用 OpenCV 中的内置函数翻转的情况下进行翻转?
Posted
技术标签:
【中文标题】如何在不使用 OpenCV 中的内置函数翻转的情况下进行翻转?【英文标题】:How to do flipping without using the inbuilt function flip in OpenCV? 【发布时间】:2015-10-10 15:03:00 【问题描述】:谁能帮我解决这个问题,如何在不使用内置翻转功能的情况下翻转图像,即使用 OpenCV 在 C++ 中翻转(src 图像,目标图像,1 或 0)。我是这个软件的新手,所以请帮忙。
【问题讨论】:
为什么不想使用内置函数? 刚被困住,想做很多艰苦的工作:D 【参考方案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 );
【讨论】:
【参考方案2】:假设您有充分的理由不使用 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
而不是 Mat3b
。
完整代码供参考:
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;
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();
int main(void)
Mat3b img = imread("path_to_image");
Mat3b flipped;
flip(img, flipped, -1);
Mat3b custom;
custom_flip(img, custom, -1);
imshow("OpenCV flip", flipped);
imshow("Custom flip", custom);
waitKey();
return 0;
【讨论】:
非常感谢!!你的回答对我帮助很大。 :) @akankshasaini 很高兴它有帮助!在 SO 中,我们通过投票表示感谢(并最终标记为答案):D @sturkmen 乍一看我同意那里的答案。缓存在您的测试中也起着重要作用,这可能会使结果产生偏差。例如尝试使用 times = 10。也尝试切换测试的顺序,你会得到不同的结果。此外,当您第一次调用flip
时,您正在创建 DstImg。在开始时创建它。
@Miki 感谢您的评论。我换了顺序,但结果是一样的。以上是关于如何在不使用 OpenCV 中的内置函数翻转的情况下进行翻转?的主要内容,如果未能解决你的问题,请参考以下文章
如何在不指定列名的情况下使用 bigquery 对表中的每一列调用内置函数?
在不使用 opencv 的情况下在 python 中应用 Homography 变换
如何在不调用索引函数或任何内置函数的情况下获取列表中的索引?