Как получить размер многомерного cv:: Mat? (Mat или MatND)

Я создаю многомерный объект MAT и хотел бы получить размер объекта - например,

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;

Я считаю, что в результате MAT будет 10x10x9, и я бы хотел подтвердить, но оператор COUT дает:

temp.dims = 3 temp.size = [10 x 10] temp.channels = 1

Я надеялся увидеть:

temp.dims = 3 temp.size = [10 x 10 x 9] temp.channels = 1

Или:

temp.dims = 3 temp.size = [10 x 10] temp.channels = 9

Как я могу получить размерность этого объекта Mat? Я не видел никаких методов в Mat:: Mat или MatND

Ответы

Ответ 1

Вы только что обнаружили один из многих недостатков API OpenCV С++.

Если вы посмотрите на исходный код OpenCV, версия 2.4.6.1, вы поймете, что cv::Mat::size - это объект-член типа cv::Mat::MSize, который определяется как

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;
};

Таким образом, cv::Mat::size() фактически ссылается на cv::Mat::MSize::operator ()(), тип возврата которого Size определяется как

typedef Size_<int> Size2i;
typedef Size2i Size;

Цитата из руководство OpenCV, Size является

"Класс шаблона для задания размера изображения или прямоугольника. Класс включает в себя два члена, называемых шириной и высотой.

Другими словами, Size подходит только для 2D-матриц.

К счастью, вся надежда не потеряна как вы можете использовать cv::Mat::MSize::operator [](int i), чтобы получить размер матрицы по ее i-му измерению.

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

Ответ 2

OpenCV 2.4.9 имеет дело с многомерными размерами. struct cv::Mat::MSize может сохранять и возвращать несколько измерений. Элемент данных cv::Mat::size имеет тип cv::Mat::MSize. Этот код будет перечислять размеры для вас:

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;

Вывод:

4       3,4,3,6,

Ответ 3

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;
}