用一个二维数组初始化OpenCV的Mat对象

36
在我的应用程序中,我希望创建一个具有一些值的OpenCV Mat A(2维),然后将其作为输入传递给另一个OpenCV函数。目前,我正在尝试:
// float data[2][5] = {{1,2,3,4,5},{7,8,9,10,11}}; 
// OR
float data[10] = {1,2,3,4,5,7,8,9,10,11};

// and then
//  A = Mat(1, 5, CV_32FC1, &data, 2);   // init from float 1D - array
// OR 
    A = Mat(2, 5, CV_32FC1, &data, 2);  

对于一维数组,值传递是可以的。但对于二维数组则不行,而这种情况更为常见。如何在OpenCV中解决这个问题?

5个回答

35

最初,我使用了OpenCV在线指南中的助记符:

Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)

但我不理解文档中的size_t step=AUTO_STEP是什么意思。这意味着我可以省略step参数,OpenCV会自动选择AUTO_STEP

我尝试了一下,它有效:

A = Mat(2, 5, CV_32FC1, &data);

对于从数组初始化的二维Mat


28
虽然您的答案对于您的情况是正确的,但了解什么是“step”和“AUTO_STEP”是很好的。
通常,图像存储在连续的内存块中。每一行都跟随在前一行之后,因此您可以通过简单的指针访问数据。
data = dataPtr[currentCol + width * currentRow];

其中,width是以字节为单位的行宽(而不是像素)。

但这并不总是正确的 - 有时您会访问子矩阵,而数据在每行上都是连续的,但是要跳转到下一行,您必须“跳过”一系列字节。

这就是步长(也称为stride)的作用。它表示两个相邻行之间的距离(以字节为单位)。在连续的矩阵中,其值为sizeof(pixel)*rowWidth,但在特殊情况下可能具有自定义值。当您将AUTO_STEP传递给Mat构造函数时,它知道数据是连续的,并使用上述公式计算步长。因此,现在读取像素值的更正确方法是

data = dataPtr[currentCol + step * currentRow];

适用于各种类型的图像。

最后但同样重要的是,请不要忘记步长是以字节而不是像素来衡量的。因此,如果您有一个3通道的uchar RGB图像,则步长将为3*像素数,如果您有一个3通道的int图像,则step = 3(通道)*sizeof(int)(4)*(行数)


24

除了上面的答案,还有另一种选择

对于较小的数据,我更喜欢以下方式:

Mat A = (Mat_<float>(2, 5) << 1, 2, 3, 4, 5, 7, 8, 9, 10, 11);

您可以轻松地获得所需的结果,无需定义额外变量“data”。


11

由于data是一个二维数组,所以所有指向数组基址的表示方式data&data*datadata[0]&data[0]&data[0][0]都可以正确地选择构建Mat来替换X

A = Mat(2, 5, CV_32FC1, X );

由于OpenCV将数据视为void*类型并进行访问,因此可以放心使用accepted的数据。而且,OpenCV对数据的访问方式如line所示。我更喜欢使用相同的语法从单维或多维数组中构建Mat。

A = Mat(1, 10, CV_32FC1, data ); //for 1D array
A = Mat(2, 5, CV_32FC1, data ); //for 2D array

回到查询 - 请注意,即使从1D数组构造Mat也是不正确的。 步骤参数被提及为2。 它只是偶然有效,因为如果行数为1,则OpenCVoverrides所提供的步骤参数。 对于更高维度的数组,OpenCV会抛出调试assertion以进行错误的步骤参数,这就是你遇到的问题。


4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接