Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

access sub-matrix of a multidimensional Mat in OpenCV

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!!

like image 811
TSL_ Avatar asked Sep 11 '12 12:09

TSL_


1 Answers

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.

like image 194
remi Avatar answered Sep 28 '22 05:09

remi