opencv矩阵数据是否保证连续?

roejwanj  于 2022-11-15  发布在  其他
关注(0)|答案(3)|浏览(345)

我知道OpenCV矩阵中包含的数据并不保证是连续的。为了让我自己清楚,这里有一段来自OpenCV文档的内容:

OpenCV提供了一个名为isContinuous()的函数来测试给定矩阵的数据是否连续。
1.如果我创建一个新矩阵,如下所示

cv::Mat img = cv::imread(img_name)

img中的数据是否保证连续?
1.我知道通过借用现有矩阵中的数据来创建新矩阵会导致数据不连续

cv::Mat small_mat = large_mat.col(0);

上面的代码通过借用large_mat的第0列创建了一个新的矩阵small_mat,导致small_mat中的数据不连续。因此问题是,如果我创建一个全新的矩阵,而不借用现有矩阵中的数据,那么这个全新的矩阵将具有连续数据还是不连续数据?
1.下面的代码能保证用连续数据创建一个矩阵吗?

cv::Mat mat(nRows, nCols, CV_32FC1);
llew8vvj

llew8vvj1#

您可以在OpenCV文档中看到isContinuous:
如果矩阵元素是连续储存,且每一列的结尾没有间隔,则此方法会传回true。否则,它会传回false。显然,1x1或1xN矩阵永远是连续的。**使用Mat::create()建立的矩阵永远是连续的。**但是,如果您使用Mat::col()、Mat::diag()等撷取矩阵的一部分,或为外部配置的数据建构矩阵信头,则此类矩阵可能不再具有此属性。
因此,只要你创建了一个新的矩阵(也就是说,你调用了create),你的矩阵就会是连续的。
create的工作原理如下:
1.如果当前数组的形状和类型与新的匹配,则立即返回。否则,通过调用Mat::release()取消引用先前的数据。
1.初始化新标头。
1.*分配total()elemSize()字节的新数据。
1.分配与数据关联的新引用计数器并将其设置为1。
这意味着当您(隐式)调用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;
}
kgqe7b3p

kgqe7b3p2#

当你用Mat::create创建一个Mat时,它是连续的。这样的操作就像显式地Mat::create,或者隐式地Mat::cloneMat::Mat(...)

eit6fx6z

eit6fx6z3#

存储在OpenCV cv::Mat s中的数据在内存中并不总是连续的,这可以通过API Mat::isContinuous()来验证。相反,它遵循以下规则:
1.由**imread()clone()构造函数**创建的矩阵始终是连续的。

  • 矩阵不连续的唯一情况是从现有矩阵借用数据(即从大矩阵的ROI中创建),但借用的数据在大矩阵中是连续的除外,包括
  • 借用单行;
  • 借用多个行,但使用完整原始宽度。

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

相关问题