Data continuity of OpenCV Mat

Data stored in OpenCV cv::Mats are not always continuous in memory, which can be verified via API Mat::isContinuous(). Instead, it follows the following rules:

  1. Matrices created by imread(), clone(), or a constructor will always be continuous.
  2. The only time a matrix will not be continuous is when it borrows data from an existing matrix (i.e. created out of an ROI of a big mat), with the exception that the data borrowed is continuous in the big matrix, including
    • borrow a single row;
    • borrow multiple rows but with full original width.

The following code demonstrates this in a better way (see the inline comments for further explanation).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <opencv2/opencv.hpp>

int main()
{
std::vector<cv::Mat> mats(7);

mats[0] = cv::Mat::ones(1000, 800, CV_32FC3); // continuous as created using constructor
mats[1] = mats[0](cv::Rect(100, 100, 300, 200)); // NOT continuous as borrowed data is not continuous (multiple rows and not full original width)
mats[2] = mats[1].clone(); // continuous as created using clone()
mats[3] = mats[2].row(10); // continuous for single row always
mats[4] = mats[2](cv::Rect(5, 5, 100, 2)); // NOT continuous as borrowed data is not continuous (multiple rows and not full original width)
mats[5] = mats[2](cv::Rect(0, 5, mats[2].cols, 2)); // continuous as borrowed data is continuous (multiple rows with full original width)
mats[6] = mats[2].col(10); // NOT continuous as borrowed data is not continuous (multiple rows and not full original width)

for (size_t i = 0; i < mats.size(); ++i) {
if (mats[i].isContinuous()) {
std::cout << "Data of mats[" << int(i) << "] is continuous with size =" << mats[i].size() << std::endl;
} else {
std::cout << "Data of mats[" << int(i) << "] is NOT continuous with size =" << mats[i].size() << std::endl;
}
}

system("pause");
return 0;
}