Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ / OpenCV - How can I reshape a cv::Mat?

Tags:

c++

opencv

I have a cv::Mat that has the dimensions of 40 rows X 32 columns.

However, I need to reshape this cv::Mat so that it will have 100 rows X 32 columns, willing the empty elements with 0.

I have tried using the code:

cv::Mat mat1 = <from somewhere else>
mat1.reshape(mat1.cols, 100);

But it's failing with the error:

OpenCV Error: Bad argument (The total number of matrix elements is not divisible by the new number of rows) in reshape.

Has anyone had any experience in reshaping cv::Mat matrices? Likewise, I would really like to be able to take a 100 rows X 32 columns matrix and go back to a 40 rows X 32 columns matrix (and just truncate the extra rows); but I'm assuming if I solve one problem then I'll solve the other.

like image 983
Brett Avatar asked Mar 09 '14 21:03

Brett


2 Answers

Here is an easy way to do this by using Mat::copyTo():

Mat padded = Mat(100, 32, CV_8UC1, Scalar(0));
mat1.copyTo(padded(Rect(0, 0, mat1.cols, mat1.rows)));

On the other hand, if you want to get 40x32 back from the 100x32 Mat, it is also quite easy to do:

Rect roi(0, 0, 32, 40);
Mat mat1 = padded(roi);

Note that, Mat::reshape() is not suitable here as no extra elements are included into the new matrix and no elements are excluded.

like image 195
herohuyongtao Avatar answered Sep 30 '22 01:09

herohuyongtao


You can slice a Mat object using the Range class in OpenCV. Ranges are exclusive which means that Range(0, 4) will refer to rows 1, 2 and 3 (it will not refer to row 4).

Here is an example that copies a 4x3 matrix into a 6x3 matrix. You can use this with any number of rows and columns:

Mat onesMat = Mat::ones(4, 3, CV_8UC1);
Mat zerosMat = Mat::zeros(6, 3, CV_8UC1);

cout<<"Before copying:"<<endl;
cout<<onesMat<<endl<<zerosMat<<endl;

// Copy onesMat to zerosMat. Destination rows [0,4), columns [0,3)
onesMat.copyTo(zerosMat(Range(0,4), Range(0,3)));


cout<<"After copying:"<<endl;
cout<<onesMat<<endl<<zerosMat<<endl;

And here is the output of the program:

Before copying:
[1, 1, 1;
  1, 1, 1;
  1, 1, 1;
  1, 1, 1]
[0, 0, 0;
  0, 0, 0;
  0, 0, 0;
  0, 0, 0;
  0, 0, 0;
  0, 0, 0]
After copying:
[1, 1, 1;
  1, 1, 1;
  1, 1, 1;
  1, 1, 1]
[1, 1, 1;
  1, 1, 1;
  1, 1, 1;
  1, 1, 1;
  0, 0, 0;
  0, 0, 0]
like image 26
Ove Avatar answered Sep 30 '22 01:09

Ove