3

My task is to periodically update a cv::Mat m of r rows and c cols, in this way:

  1. shift by 1 column the whole m to the right, dropping away the last column at position c-1
  2. randomly generate the new column at position 0
  3. refresh the plot of m

This will result in a sort of belt conveyor simulation, for the sake of clarity. However, the problem arises in point 1 when m has to be shifted.

I found two different solutions, namely A and B, both ending in the same result. This suggests me that I'm doing something wrong.

Method A follows:

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;

Method B follows:

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;

And here's the output as an example small m (random values are spawning on the left):

cycle 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

cycle 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

cycle 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

it is clear that an extra column made of zeros appears somehow... and I really cannot figure how.

P.S. If I set offset = 3 the output scales by a factor 2, and so on.

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

cycle 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
4

1 回答 1

2

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

此外,您可以使用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]
于 2015-11-17T12:11:03.350 回答