在OpenCV中移动图像内容

shift image content in OpenCV

本文关键字:图像 移动 OpenCV      更新时间:2023-10-16

我的任务是定期更新r行和c列的cv::Mat m,方法如下:

  1. 1列向右移动整个m,在位置c-1处去掉最后一列
  2. 在位置0随机生成新列
  3. 刷新m的绘图

为了清楚起见,这将产生一种带式输送机模拟。然而,当m必须移位时,问题出现在点1

我找到了两种不同的解决方案,即AB,结果都是一样的。这表明我做错了什么。

方法A如下:

int offset = 1;
cv::Mat tmp = cv::Mat::zeros(m.size(), m.type());
cv::Rect rect_src(0, 0, m.cols-offset, m.rows);
cv::Rect rect_dst(offset, 0, m.cols-offset, m.rows);
cv::Mat in = m(rect_src);
cv::Mat out = tmp(rect_dst);
in.copyTo(out);
m = temp;

方法B如下:

int offset = 1;
cv::Mat trans_mat = (cv::Mat_<double>(2, 3) << 1, 0, offset, 0, 1, 0);
cv::Mat warped;
warpAffine(m, warped, trans_mat, m.size());
m = warped;

这里的输出是一个小m的例子(随机值在左边生成):

循环1

90      0       0       0       0       0       0       0       0
143     0       0       0       0       0       0       0       0
0       0       0       0       0       0       0       0       0

循环2

0       0       90      0       0       0       0       0       0
0       0       143     0       0       0       0       0       0
0       0       0       0       0       0       0       0       0

循环3

0       0       144     0       90      0       0       0       0
0       0       161     0       143     0       0       0       0
0       0       0       0       0       0       0       0       0

很明显,会以某种方式出现一个由零组成的额外列。。。我真的不知道该怎么做。

附言:如果我设置offset = 3,输出按因子2缩放,依此类推

90      0       0       0       0       0       0       0       0
143     0       0       0       0       0       0       0       0
0       0       0       0       0       0       0       0       0

循环2

0       0       0       0       0       0       90      0       0
0       0       0       0       0       0       143     0       0
0       0       0       0       0       0       0       0       0

这两种方法都可以正常工作,即使在这里使用仿射变换是过度的。你可能在问题中没有显示的代码中有错误。

此外,您还可以使用colRange,这将简化您的代码。

检查两种方法的结果是否相等,并且没有出现额外的不需要的列:

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
    Mat1b img(3, 10);
    randu(img, Scalar(0), Scalar(255));
    Mat1b img2 = img.clone();
    //imshow("img", img);
    //waitKey();
    cout << img << endl << endl;
    int offset = 1;
    Mat trans_mat = (Mat_<double>(2, 3) << 1, 0, offset, 0, 1, 0);
    for (int i = 0; i < 100; ++i)
    {
        // Random data
        Mat1b randomData(img.rows, offset);
        randu(randomData, Scalar(0), Scalar(255));
        // Copying roi
        img.colRange(0, img.cols - offset).copyTo(img.colRange(offset, img.cols));
        randomData.copyTo(img.colRange(0, offset));
        //randu(img.colRange(0, offset), Scalar(0), Scalar(255));
        // Warping
        cv::Mat warped;
        warpAffine(img2, warped, trans_mat, img2.size());
        img2 = warped.clone();
        randomData.copyTo(img2.colRange(0, offset));
        //randu(img2.colRange(0, offset), Scalar(0), Scalar(255));
        //imshow("img", img2);
        //waitKey();
        cout << img << endl << endl;
        cout << img2 << endl << endl;
    }   
    return 0;
}

这是第一次迭代的数据。

原始数据

[ 91,   2,  79, 179,  52, 205, 236,   8, 181, 239;
  26, 248, 207, 218,  45, 183, 158, 101, 102,  18;
 118,  68, 210, 139, 198, 207, 211, 181, 162, 197]

通过复制roi 转移的数据

[191,  91,   2,  79, 179,  52, 205, 236,   8, 181;
 196,  26, 248, 207, 218,  45, 183, 158, 101, 102;
  40, 118,  68, 210, 139, 198, 207, 211, 181, 162]

通过扭曲移动的数据

[191,  91,   2,  79, 179,  52, 205, 236,   8, 181;
 196,  26, 248, 207, 218,  45, 183, 158, 101, 102;
  40, 118,  68, 210, 139, 198, 207, 211, 181, 162]