Can someone explain how one would do this sclicing operation in c++ opencv
y[..., 0:2] = (y[..., 0:2] * 2 - 0.5 + grid) * stride
when y is with a shape(1,3,80,80,85).
I know that I can extract it with the range using ROI but when I do the computation with the submatrix. How do put the ROI back to original matrix. Any suggestions welcome.
Hello,
As far as I know, operating on a ROI only creates a view of the original Mat, not a new data buffer, so any computation performed on the ROI will effectively be reflected in the original Mat as well.
You might be interested in functions
operator() and locateROI
I eventually did it with using ranges with cv::Mat subarray = input_array(ranges);
but the problem is that how do I re-apply the submatrix to the input_array. The internet suggests
cv::mat subarray = input_array(ranges)
cv::mat tmp = input_array.clone()
subarray.copyTo(tmp)
input_array
is what ?
(not part of the API)
and why the clone()
?
also, can you please explain the context of your operation ?
(even in python, those 2 lines don’t seem to fit together for me …)
I’ll clarify then. Lets say you have an Mat with dimensions (3,80,80,85) lets call it input_array, you need to extract a sub matrix with (3,80,80,2) which is done with following code.
const int sz[] = {3,80,80,85};
cv::Mat input_array(4,sz,CV_32F,cv::Scalar(114.0));
std::vector<cv::Range> ranges;
ranges.push_back(cv::Range::all());
ranges.push_back(cv::Range::all());
ranges.push_back(cv::Range::all());
ranges.push_back(cv::Range(0, 2));
cv::Mat subarray = input_array(ranges);
subarray = (subarray * 2 - 0.5 + grid) * stride;
Now how do you apply the submatrix changes back to the input_array, the shape of subarray is the same it does not change or is there a better way to do it.
I hope it made things more clear.
Dear sycc,
subarray is effectively a view of input_array.
I haven’t debugged your code, but check out the example below (it’s an image and not a general multi-dimensional array because it makes visualization easier):
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
int main() {
cv::Mat input_array(80, 80, CV_8UC3, cv::Scalar(255,0,0)); //3 channels, 80x80, completely blue
cv::imshow("", input_array);
cv::waitKey(0);
std::vector<cv::Range> ranges;
ranges.push_back(cv::Range::all());
ranges.push_back(cv::Range(0, 20));
cv::Mat subarray = input_array(ranges); //subarray is a view of the first 20 columns of the image
subarray = cv::Scalar(0, 255, 0); //change the color to green
cv::imshow("", input_array);
cv::waitKey(0);
subarray = subarray / 2; //halven the intensity of the green
cv::imshow("", input_array);
cv::waitKey(0);
return 0;
}
you don’t have to, it happens ‘in-place’:
const int sz[] = {3,8,8,5}; // slightly smaller for viz.
cv::Mat input_array(4,sz,CV_32F,cv::Scalar(1.0));
std::vector<cv::Range> ranges;
ranges.push_back(cv::Range::all());
ranges.push_back(cv::Range::all());
ranges.push_back(cv::Range::all());
ranges.push_back(cv::Range(0, 2));
cv::Mat subarray = input_array(ranges);
cout << subarray.size << endl;
subarray = subarray * 2; // some op
cout << Mat(8,8,CV_32F,input_array.ptr(0));
3 x 8 x 8 x 2
[2, 2, 1, 1, 1, 2, 2, 1;
1, 1, 2, 2, 1, 1, 1, 2;
2, 1, 1, 1, 2, 2, 1, 1;
1, 2, 2, 1, 1, 1, 2, 2;
1, 1, 1, 2, 2, 1, 1, 1;
2, 2, 1, 1, 1, 2, 2, 1;
1, 1, 2, 2, 1, 1, 1, 2;
2, 1, 1, 1, 2, 2, 1, 1]