Reputation: 2712
My task is to periodically update a cv::Mat m
of r
rows and c
cols, in this way:
1
column the whole m
to the right, dropping away the last column at position c-1
0
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
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