我知道,opencv矩阵中包含的数据不保证是连续的.为了清楚起见,这是Opencv文档中的一段:
Opencv提供了一个名为isContinuous()的函数来测试给定矩阵的数据是否是连续的.我的问题是
(1)如果我按如下方式创建新矩阵
Mat img = cv::imread(img_name)
Run Code Online (Sandbox Code Playgroud)
img中的数据是否保证是连续的?
(2)我知道通过从现有矩阵借用数据来创建新矩阵将导致不连续的数据
cv::Mat small_mat = large_mat.col(0);
Run Code Online (Sandbox Code Playgroud)
上面的代码通过借用large_mat的第0列来创建一个新的矩阵small_mat,从而导致small_mat中的连续数据.所以问题是,如果我在不借用现有矩阵的数据的情况下创建一个全新的矩阵,那么全新的矩阵是否会有不间断的数据?
(3)以下代码是否保证创建具有连续数据的矩阵?
cv::Mat mat(nRows, nCols, CV_32FC1);
Run Code Online (Sandbox Code Playgroud)
Mik*_*iki 20
您可以在OpenCV doc中看到isContinuous:
如果矩阵元素在每行的末尾连续存储而没有间隙,则该方法返回true.否则,它返回false.显然,1x1或1xN矩阵始终是连续的.使用Mat :: create()创建的矩阵始终是连续的.但是,如果使用Mat :: col(),Mat :: diag()等提取矩阵的一部分,或者为外部分配的数据构造矩阵头,则此类矩阵可能不再具有此属性.
因此,只要您创建一个新矩阵(即您正在调用create),您的矩阵将是连续的.
create 的作用如下:
这意味着当您(隐式)调用create时,矩阵将是连续的(步骤3).
你的问题
如果我创建一个新矩阵,
imread则数据保证是连续的
是的,因为imread内部通话create.
我知道通过从现有矩阵借用数据来创建新矩阵将导致不连续的数据.
正确,数据将是不连续的.要使新矩阵连续,您可以调用clone(),调用create以创建新矩阵.
如果我在不借用现有矩阵的数据的情况下创建一个全新的矩阵,那么全新的矩阵是否会有不间断的数据?
是的,构造函数内部调用create.
Matrix构造函数可以保证创建一个包含连续数据的矩阵吗?
是的,构造函数内部调用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;
}
Run Code Online (Sandbox Code Playgroud)
OpenCV 中存储的数据cv::Mat在内存中并不总是连续的,这可以通过 API 进行验证Mat::isContinuous()。相反,它遵循以下规则:
imread()、clone()或构造函数创建的矩阵将始终是连续的。我博客中的以下代码以更好的方式演示了这一点(请参阅内联注释以获取进一步的解释)。
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);
Run Code Online (Sandbox Code Playgroud)