基于OpenCV的循环行、列移动函数circShift()

///*12 在Matlab中有个circshift()函数,可以实现行、列的循环移动
///    在返卷积运算中,会用到这个函数。所以,在Opencv中我也定义同样功能的函数
///    该函数有3个参数,第1个src是输入矩阵或图像,第2、3个参数分别是
///    沿着'行'方向移动的函数,和沿着‘列’方向移动的列数。
以前在写这段代码的时候,没有考虑效率问题,今天重写改写了程序。函数名、3个形参,与malab中用到的完全一致。
与matlab不同的是,本函数不能一次同时执行行、列平移。
同时本文也给了另外一个版本,用remap函数实现矩阵的平行移动,而且可以同时实现行、列的循环平移,这一点上与matlab完全一样了。
最近又搞了个平行加速版,用paralle_for_,可以对处理764×1162尺寸的图像提高2ms,参见函数三。速度比函数二提高了2ms。而函数一却是函数三的6倍速度
函数一:
void circShift(Mat&src,//原矩阵
                  int shift_m,//循环移动的行数或列数
                  const int RowOrCol=1)//默认为1,表示行循环移动;否则列循环
{
    int m=shift_m;
    int rows=src.rows;
    m %=rows;
    if(m<0)
        m=rows+m;
    else if(m==0){
        return ;
    }
    if(RowOrCol!=1)//如果是列偏移,将原矩阵转置
        src=src.t();
    src.push_back( src(Range(0,m),Range::all()));//将准备平移的行添加到src的末尾
    src.data +=src.step[0]*m;//将data指针下移m行
    src.pop_back(m);//将末尾多余的行移除
    if(RowOrCol!=1)//将转置矩阵复原
        src=src.t();

}

 函数二,remap实现:

void circshift(Mat&src,//原图像
               Size size)//height>0循环上一移,反之循环下移;width>0循环左移,反之右移
{
    Mat srcx(src.size(),CV_32F);
    Mat srcy(src.size(),CV_32F);
    int rows=src.rows,cols=src.cols;
    int height=size.height%rows;
    int width=size.width%cols;
if(height<0)
height +=rows;
if(width<0)
width +=cols;float x,y;
for(int i=0;i<rows;i++) 
{
for(int j=0;j<cols;j++)
{
x
=(j+width)%cols;
y
=(i+height)%rows;
srcx.ptr
<float>(i)[j]=x;
srcy.ptr
<float>(i)[j]=y;
}
}
remap(src,src,srcx,srcy,INTER_NEAREST);
}

 函数三,加速版746×1162尺寸的图像,比前面的函数二提高了2ms,不过最快的还是函数一,是函数三的6倍:

void circshift(Mat&src,//原图像
               Size size)//height>0循环上一移,反之循环下移;width>0循环左移,反之右移
{
    Mat srcx(src.size(),CV_32F);
    Mat srcy(src.size(),CV_32F);
    int rows=src.rows,cols=src.cols;
    int height=size.height%rows;
    int width=size.width%cols;
    float *psrcx=(float*)srcx.data;
    float *psrcy=(float*)srcy.data;
    int totalPixs=src.rows*src.cols;
    parallel_for_(Range(0,totalPixs),[&](const Range&range){
        for(int r=range.start;r<range.end;r++)
        {
            int i=r/rows;//第i行
            int j=r%cols;//第j列
            psrcx[r]=(j+width+cols)%cols;
            psrcy[r]=(i+height+rows)%rows;
        }
        remap(src,src,srcx,srcy,INTER_NEAREST);
    });

 


测试程序,对imgc移动3列:



int
main() { // Mat img1=imread("D:/CodeWork/MyImage/baboon.jpg",0); Mat imgc=(Mat_<uchar>(9,12) <<0,1,2,3,4,5,6,7,8,9,10,11, 0,1,2,3,4,5,6,7,8,9,10,11, 0,1,2,3,4,5,6,7,8,9,10,11, 0,1,2,3,4,5,6,7,8,9,10,11, 0,1,2,3,4,5,6,7,8,9,10,11, 0,1,2,3,4,5,6,7,8,9,10,11, 0,1,2,3,4,5,6,7,8,9,10,11, 0,1,2,3,4,5,6,7,8,9,10,11, 0,1,2,3,4,5,6,7,8,9,10,11); Mat imgr=imgc.t(); cout<<"original imgc="<<endl<<imgc<<endl; circShift(imgc,0,3); // circShift(imgc,0,3); cout<<"3 cols-shifted imgc="<<endl<<imgc<<endl; waitKey(); return 0; }

 

运行结果如下:

 

测试程序,对imgr移动3行:

 

int main()
{
//    Mat img1=imread("D:/CodeWork/MyImage/baboon.jpg",0);
    Mat imgc=(Mat_<uchar>(9,12)
           <<0,1,2,3,4,5,6,7,8,9,10,11,
             0,1,2,3,4,5,6,7,8,9,10,11,
             0,1,2,3,4,5,6,7,8,9,10,11,
             0,1,2,3,4,5,6,7,8,9,10,11,
             0,1,2,3,4,5,6,7,8,9,10,11,
             0,1,2,3,4,5,6,7,8,9,10,11,
             0,1,2,3,4,5,6,7,8,9,10,11,
             0,1,2,3,4,5,6,7,8,9,10,11,
             0,1,2,3,4,5,6,7,8,9,10,11);
    Mat imgr=imgc.t();
    cout<<"original imgr="<<endl<<imgr<<endl;
    circShift(imgr,0,3);
    cout<<"3 rows-shifted imgr="<<endl<<imgr<<endl;
    waitKey();
    return 0;
}

运行结果如下:

 

posted @ 2018-02-07 10:12  凤凰_1  阅读(1716)  评论(0编辑  收藏  举报