我知道,opencv矩阵中包含的数据不保证是连续的。为了清楚起见,这里有一段Opencv documentation:
Opencv提供了一个名为 isContinuous() 的函数来测试给定矩阵的数据是否是连续的。我的问题是
(1)如果我按如下方式创建新矩阵
Mat img = cv::imread(img_name)
img 中的数据是否保证是连续的?
(2)我知道通过从现有矩阵借用数据来创建新矩阵会导致不连续的数据
cv::Mat small_mat = large_mat.col(0);
上面的代码通过借用 large_mat 的第0列创建了一个新矩阵 small_mat ,导致 small_mat 中的不连续数据。所以问题是,如果我在不借用现有矩阵的数据的情况下创建一个全新的矩阵,那么全新的矩阵是否会有不间断的数据?
(3)以下代码是否可以保证创建具有连续数据的矩阵?
cv::Mat mat(nRows, nCols, CV_32FC1);
答案 0 :(得分:17)
您可以在OpenCV文档中看到isContinuous:
如果矩阵元素连续存储,并且每行末尾没有间隙,则该方法返回true。否则,它返回false。显然,1x1或1xN矩阵始终是连续的。 使用Mat :: create()创建的矩阵始终是连续的。但是如果使用Mat :: col(),Mat :: diag()等提取矩阵的一部分,或者构造外部分配数据的矩阵标头,这样的矩阵可能不再具有此属性。
因此,只要您创建一个新矩阵(即您正在调用create),您的矩阵将是连续的。
create
的作用类似于:
这意味着当您(隐式)调用create时,矩阵将是连续的(步骤3)。
您的问题
如果我使用
imread
创建一个新矩阵,则数据保证是连续的
是,因为imread
内部调用了create
。
我知道通过从现有矩阵借用数据来创建新矩阵会导致数据不连续。
正确,数据将非连续。要使新矩阵连续,您可以调用clone()
,调用create
来创建新矩阵。
如果我在不借用现有矩阵的数据的情况下创建一个全新的矩阵,那么全新的矩阵是否会有不间断的数据?
是,构造函数在内部调用create
。
矩阵构造函数可以保证创建一个包含连续数据的矩阵吗?
是,构造函数在内部调用create
。
这是一个总结的小例子:
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
// Read image
Mat img = imread("path_to_image");
cout << "img is continuous? " << img.isContinuous() << endl;
// Yes, calls create internally
// Constructed a matrix header for externally allocated data
Mat small_mat = img.col(0);
cout << "small_mat is continuous? " << small_mat.isContinuous() << endl;
// No, you're just creating a new header.
// Matrix (self) expression
small_mat = small_mat + 2;
cout << "small_mat is continuous? " << small_mat.isContinuous() << endl;
// No, you're not even creating a new header
// Matrix expression
Mat expr = small_mat + 2;
cout << "expr is continuous? " << expr.isContinuous() << endl;
// Yes, you're creating a new matrix
// Clone
Mat small_mat_cloned = img.col(0).clone();
cout << "small_mat_cloned is continuous? " << small_mat_cloned.isContinuous() << endl;
// Yes, you're creating a new matrix
// Create
Mat mat(10, 10, CV_32FC1);
cout << "mat is continuous? " << mat.isContinuous() << endl;
// Yes, you're creating a new matrix
return 0;
}
答案 1 :(得分:2)
使用Mat
创建Mat::create
时,它是连续的。此类操作类似于Mat::create
,或隐式Mat::clone
,Mat::Mat(...)
。
答案 2 :(得分:2)
OpenCV cv::Mat
中存储的数据在内存中并不总是连续的,可以通过API Mat::isContinuous()
进行验证。而是遵循以下规则:
imread()
, clone()
或构造函数创建的矩阵将始终是连续的。来自my blog的以下代码以更好的方式对此进行了演示(有关更多说明,请参见内联注释)。
std::vector<cv::Mat> mats(7);
// continuous as created using constructor
mats[0] = cv::Mat::ones(1000, 800, CV_32FC3);
// NOT continuous as borrowed data is not continuous (multiple rows and not full original width)
mats[1] = mats[0](cv::Rect(100, 100, 300, 200));
// continuous as created using clone()
mats[2] = mats[1].clone();
// continuous for single row always
mats[3] = mats[2].row(10);
// NOT continuous as borrowed data is not continuous (multiple rows and not full original width)
mats[4] = mats[2](cv::Rect(5, 5, 100, 2));
// continuous as borrowed data is continuous (multiple rows with full original width)
mats[5] = mats[2](cv::Rect(0, 5, mats[2].cols, 2));
// NOT continuous as borrowed data is not continuous (multiple rows and not full original width)
mats[6] = mats[2].col(10);