I am creating a multi-dimensional MAT object, and would like to get the size of the object - e.g.,
const int sz[] = {10,10,9};
Mat temp(3,sz,CV_64F);
std::cout << "temp.dims = " << temp.dims << " temp.size = " << temp.size() << " temp.channels = " << temp.channels() << std::endl;
I believe the resulting MAT to be 10x10x9, and I'd like to confirm, but the COUT statement gives:
temp.dims = 3 temp.size = [10 x 10] temp.channels = 1
I was hoping to see either:
temp.dims = 3 temp.size = [10 x 10 x 9] temp.channels = 1
Or:
temp.dims = 3 temp.size = [10 x 10] temp.channels = 9
How can I get the dimensionality of this Mat object? I didn't see any methods in Mat::Mat or MatND
You just found yourself one of the many flaws of the OpenCV C++ API.
If you take a look at the source code of OpenCV, version 2.4.6.1, you will realize cv::Mat::size
is a member object of type cv::Mat::MSize
, which is defined as
struct CV_EXPORTS MSize
{
MSize(int* _p);
Size operator()() const;
const int& operator[](int i) const;
int& operator[](int i);
operator const int*() const;
bool operator == (const MSize& sz) const;
bool operator != (const MSize& sz) const;
int* p;
};
Thus cv::Mat::size()
actually refers to cv::Mat::MSize::operator ()()
, whose return type Size
is defined as
typedef Size_<int> Size2i;
typedef Size2i Size;
Quoting from the OpenCV manual, Size
is a
"Template class for specifying the size of an image or rectangle. The class includes two members called width and height."
In other words, Size
is only suitable for 2D matrices.
Fortunately all hope is not lost as you can use cv::Mat::MSize::operator [](int i)
to get the size of the matrix along its i-th dimension.
const int sz[] = {10,10,9};
cv::Mat temp(3,sz,CV_64F);
std::cout << "temp.dims = " << temp.dims << "temp.size = [";
for(int i = 0; i < temp.dims; ++i) {
if(i) std::cout << " X ";
std::cout << temp.size[i];
}
std::cout << "] temp.channels = " << temp.channels() << std::endl;
temp.dims = 3 temp.size = [10 x 10 x 9] temp.channels = 1
OpenCV 2.4.9 deals with multi-dimensional sizes just fine. The struct
cv::Mat::MSize
can stores and return multiple dimensions. The data member cv::Mat::size
is of the type cv::Mat::MSize
. This code will enumerate the dimensions for you:
const int sz[] = {3, 4, 3, 6};
cv::Mat bigm(4, sz, CV_8UC1);
cout << bigm.dims << '\t';
for (int i=0; i<bigm.dims; ++i)
cout << bigm.size[i] << ',';
cout << endl;
The output is:
4 3,4,3,6,
std::vector<size_t> getMatDims(const cv::Mat& m)
{
std::vector<size_t> dims(m.dims);
std::partial_sum(&m.step[0],&m.step[0]+m.dims,dims.begin(),[](size_t a,size_t b){ return a/b; });
return dims;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With