18

I'm using OpenCV with cv::Mat objects, and I need to know the number of bytes that my matrix occupies in order to pass it to a low-level C API. It seems that OpenCV's API doesn't have a method that returns the number of bytes a matrix uses, and I only have a raw uchar *data public member with no member that contains its actual size.

How can one find a cv::Mat size in bytes?

StatusReport
  • 3,397
  • 1
  • 23
  • 31

1 Answers1

51

The common answer is to calculate the total number of elements in the matrix and multiply it by the size of each element, like this:

// Given cv::Mat named mat.
size_t sizeInBytes = mat.total() * mat.elemSize();

This will work in conventional scenarios, where the matrix was allocated as a contiguous chunk in memory.

But consider the case where the system has an alignment constraint on the number of bytes per row in the matrix. In that case, if mat.cols * mat.elemSize() is not properly aligned, mat.isContinuous() is false, and the previous size calculation is wrong, since mat.elemSize() will have the same number of elements, although the buffer is larger!

The correct answer, then, is to find the size of each matrix row in bytes, and multiply it with the number of rows:

size_t sizeInBytes = mat.step[0] * mat.rows;

Read more about step here.

Jan Rüegg
  • 9,587
  • 8
  • 63
  • 105
StatusReport
  • 3,397
  • 1
  • 23
  • 31
  • Well explained! The step*rows scenario will work in continuous scenario, too, doesn't it? But it's the question whether your low-level API can handle images that are not continuous. – Micka Oct 18 '14 at 17:27
  • It will work in continuous scenario as well, since then `mat.step[0] == mat.cols * mat.elemsize()`. And yes, it can handle non-continuous buffers (I'm working with ImageIO on iOS to compress images directly to disk). – StatusReport Oct 18 '14 at 17:41
  • 1
    Just to clarify or restate @StatusReport answer: `mat.step[0] == mat.cols * mat.elemsize()` only when the image is continuous, but is not true when the image is not continuous. The safest way is to always use `sizeInBytes = mat.step[0] * mat.rows`. – Richard Whitehead May 11 '22 at 12:44