Patrizio Bertoni
Patrizio Bertoni

Reputation: 2712

shift image content in OpenCV

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

Upvotes: 3

Views: 1974

Answers (1)

Miki
Miki

Reputation: 41765

Both approach work ok, even if using an affine transform is an overkill here. You probably have an error in the code you didn't show in the question.

Also, you can use colRange, which will simplify your code.

Check that results of both approaches are equivalent, and no extra unwanted columns appears:

#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;
}

This are the data of the first iteration.

Original data

[ 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]

Data shifted by copying 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]

Data shifted by warping

[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]

Upvotes: 2

Related Questions