opencv 矩阵数据是否保证连续? [英] Is opencv matrix data guaranteed to be continuous?

查看:39
本文介绍了opencv 矩阵数据是否保证连续?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道,opencv 矩阵中包含的数据不能保证是连续的.为了让自己清楚,这里有一段来自

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

解决方案

您可以在 OpenCV 文档中看到 isContinuous:

<块引用>

如果矩阵元素在每行末尾连续存储而没有间隙,则该方法返回 true.否则,它返回 false.显然,1x1 或 1xN 矩阵总是连续的.使用 Mat::create() 创建的矩阵总是连续的. 但是如果您使用 Mat::col()、Mat::diag() 等提取矩阵的一部分,或者构造外部分配数据的矩阵头,此类矩阵可能不再具有此属性.

因此,只要您正在创建一个新矩阵(即您正在调用 创建),您的矩阵将是连续的.

create 的工作原理如下:

  1. 如果当前数组的形状和类型与新的匹配,则立即返回.否则,通过调用 Mat::release() 取消引用之前的数据.
  2. 初始化新标头.
  3. 分配total()*elemSize()字节的新数据.
  4. 分配新的、与数据关联的引用计数器并将其设置为 1.

这意味着当您(隐式)调用 create 时,矩阵将是连续的(步骤 3).

<小时>

您的问题

<块引用>

如果我用 imread 创建一个新矩阵,保证数据是连续的

,因为imread在内部调用了create.

<块引用>

我知道通过从现有矩阵中借用数据来创建新矩阵会导致数据不连续.

正确,数据将不连续.为了使新矩阵连续,您可以调用 clone(),它调用 create 来创建新矩阵.

<块引用>

如果我创建一个全新的矩阵而不从现有矩阵中借用数据,那么这个全新的矩阵是否会有不连续的数据?

,构造函数内部调用了create.

<块引用>

矩阵构造函数是否保证创建一个具有连续数据的矩阵?

,构造函数内部调用了create.

这是一个总结的小例子:

#include #include 使用命名空间标准;使用命名空间 cv;int main(){//读取图像Mat img = imread("path_to_image");cout<<img是连续的吗?" <<img.isContinuous() <<结束;//是的,调用内部创建//为外部分配的数据构造一个矩阵头Mat small_mat = img.col(0);cout<<small_mat 是连续的吗?" <<small_mat.isContinuous() <<结束;//不,你只是在创建一个新的标题.//矩阵(自)表达式small_mat = small_mat + 2;cout<<small_mat 是连续的吗?" <<small_mat.isContinuous() <<结束;//不,你甚至没有创建一个新的标题//矩阵表达式垫 expr = small_mat + 2;cout<<expr 是连续的?" <<expr.isContinuous() <<结束;//是的,您正在创建一个新矩阵//克隆Mat small_mat_cloned = img.col(0).clone();cout<<small_mat_cloned 是连续的?" <<small_mat_cloned.isContinuous() <<结束;//是的,您正在创建一个新矩阵//创建Mat mat(10, 10, CV_32FC1);cout<<垫子是连续的吗?" <<mat.isContinuous() <<结束;//是的,您正在创建一个新矩阵返回0;}

I know that, the data contained in an opencv matrix is not guaranteed to be continuous. To make myself clear, here is a paragraph from Opencv documentation:

Opencv provides a function called isContinuous() to test if the data of a given matrix is continuous. My questions are

(1) If I create a new matrix as follows

Mat img = cv::imread(img_name)

Is the data in img guaranteed to be continuous?

(2) I know that creating a new matrix by borrowing data from existing matrix would result in incontinuous data

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

The above code creates a new matrix, small_mat, by borrowing the 0-th column of large_mat, leading to incontinuous data in small_mat. So the question is, if I create a brand new matrix without borrowing data from existing matrix, will the brand new matrix have incontinuous data?

(3) Is the following code guaranteed to create a matrix with continuous data?

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

解决方案

You can see in the OpenCV doc for isContinuous:

The method returns true if the matrix elements are stored continuously without gaps at the end of each row. Otherwise, it returns false. Obviously, 1x1 or 1xN matrices are always continuous. Matrices created with Mat::create() are always continuous. But if you extract a part of the matrix using Mat::col(), Mat::diag() , and so on, or constructed a matrix header for externally allocated data, such matrices may no longer have this property.

So, as long as you are creating a new matrix (i.e. you're calling create), your matrix will be continuous.

create works like:

  1. If the current array shape and the type match the new ones, return immediately. Otherwise, de-reference the previous data by calling Mat::release().
  2. Initialize the new header.
  3. Allocate the new data of total()*elemSize() bytes.
  4. Allocate the new, associated with the data, reference counter and set it to 1.

This means that when you (implicitly) call create, the matrix will be continuous (step 3).


Your questions

If I create a new matrix with imread is the data guaranteed to be continuous

Yes, because imread internally calls create.

I know that creating a new matrix by borrowing data from existing matrix would result in incontinuous data.

Correct, data will be non continuous. To make the new matrix continuous, you can call clone(), which calls create to create the new matrix.

if I create a brand new matrix without borrowing data from existing matrix, will the brand new matrix have incontinuous data?

Yes, the constructor internally calls create.

Matrix constructor is guaranteed to create a matrix with continuous data?

Yes, the constructor internally calls create.

This is a small example to summarize:

#include <opencv2opencv.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;
}

这篇关于opencv 矩阵数据是否保证连续?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆