8

according to this post and from OpenCV documentation, I can initialize and access each element of a multidimensional Mat.

Actually, I firstly coded in MATLAB and now need to convert to OpenCV. MATLAB matrix supports sub-matrix access like: a(:,:,3) or b(:,:,3:5)

Can this be done in OpenCV? as far as I know, this can be done with 2D Mat. How about more that 2D??

Edit01: moreover, with multidimensional Mat, the properties cols and rows are not enough to characterize 3 sizes of the matrix. There are cases with dimension larger than 3. How to store these properties?

Edit02:

// create a 100x100x100 8-bit array
int sz[] = {100, 100, 100};
Mat bigCube(3, sz, CV_8U, Scalar::all(0));

I give up the idea of sub-matrix access with OpenCV Mat. Perhaps, it's not supported in OpenCV. But from this sample code, the constructor receives the 3rd dimension from 'sz'. Which property of Mat this 3rd dimension is passed to? probably in this case, rows = 100, cols = 100, the other ?? = 100 I'm lost with OPenCV documentation

Edit03: tracking Mat class from OpenCV source I've found the definition of the constructor in Edit02 from mat.hpp:

inline Mat::Mat(int _dims, const int* _sz, int _type, const Scalar& _s)
    : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0),
    datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows)
{
    create(_dims, _sz, _type);
    *this = _s;
}  

the next question is where and how "create" function here is defined? => tracing this Mat definition in OpenCV probably helps me to modify/customize my own features in Mat matrix

PS: excuse me if my post is written too messy!! I'm a novic programmer, trying to solve my programming problem. Plz feel free to correct me if my approach is not good or right enough. Thank you!!

Community
  • 1
  • 1
TSL_
  • 2,049
  • 3
  • 34
  • 55
  • I've core.hpp to see all the declarations of constructor, including the one for multi-dimensional Mat. But I could not find where the definition, I mean the coding of that constructor, to see which property the 3rd dimension goes to. Where is that source code?? – TSL_ Sep 12 '12 at 02:45
  • That would be there : /modules/core/src/matrix.cpp. I am editing my answer concerning your original problem below – remi Sep 12 '12 at 13:06
  • Did you end up writing this code? I'm about to have to do the same thing... – kmac Oct 24 '14 at 21:35
  • @ShawnLe Could you please accept remi's answer? – acj Aug 26 '16 at 12:33

2 Answers2

6

You can easily access sub-matrix of 2D cv::Mat using functions rowRange, colRange or even

cv::Mat subMat = originalMat(cv::Rect(x,y,width,height));

Also, the number of channels in a matrix, that you can define in the matrix constructor, can be used as the third dimension (but it is limited to 256 or 512 i think).

There is also the templated cv::Mat_ class that you can adapt to fit your purpose

[edit]

I have checked the constructor for >2 dimensional matrices. When you run it the rows and cols field of Mat are set to -1. The actual matrix size is store in Mat::size as an array of int. For matrix of dimensions >2 you cannot use the submatrices constructors using a cv::Rect or rowRange/colRange.

I'm afraid you have to do a bit of work to extract submatrices for dim>2, working directly with the row data. But you can use the information stored in Mat::step which tells you the layout of the array. This is explained in the official documentation.

remi
  • 3,914
  • 1
  • 19
  • 37
  • ..so you mean, I ought to write separate functions to do this kind of matrix access?? or to add them to the Mat class by writing myMat for example?? this is kind of silly question, but as an amateur programmer, I really want to know how things are done in the way of professionals – TSL_ Sep 13 '12 at 12:19
  • Professionals just try to do things work :) In your case it can be useful to write a function for accessing N-dimensional data. I would not bother writing a new class. – remi Sep 14 '12 at 09:07
  • I don't wanna close this post as I want to accomplish it by writing my own class/functions and post them here like an exercise. So excuse me for that :) – TSL_ Sep 14 '12 at 10:59
0

you can create sub-matrix by:

cv::Mat subMat(100,100,CV_8U, bigCube.ptr(0));

subMat is a 2-D matrix so you can do what you want.

xiadeye
  • 441
  • 1
  • 3
  • 8