34

在我的应用程序中,我想创建一个具有一些值的 OpenCV Mat A(二维),然后使用 A 作为输入将其传递给另一个 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 中解决这个问题?

4

5 回答 5

35

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

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

但我不明白该文件的含义是什么size_t step=AUTO_STEP。这意味着我可以省略stepOpenCV 将自动选择的参数AUTO_STEP

我试过了,这有效:

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

对于从数组初始化的 2D Mat

于 2012-08-27T09:41:03.953 回答
27

虽然您的答案对您的情况是正确的,但最好知道什么stepAUTO_STEP意思

通常,图像存储在连续的内存块中。每一行都在前一行之后,因此您可以使用简单的指针访问数据

data = dataPtr[currentCol + width * currentRow];

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

但情况并非总是如此 - 有时您访问一个子矩阵,并且数据在每一行上都是连续的,但要进入下一行,您必须跳转一个字节序列。

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

data = dataPtr[currentCol + step * currentRow];

这适用于各种图像。

最后但并非最不重要的一点是,不要忘记 step 是以字节而不是像素来衡量的。所以如果你有一个 3 通道的 uchar RGB 图像, step 将是3*number of pixels,如果你有一个 3 通道的 int 图像,step = 3(channels)*(4=sizeof(int))*(number rows)

于 2012-08-27T10:01:20.117 回答
23

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

对于较小的数据,我更喜欢以下内容:

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

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

于 2015-06-24T10:25:45.853 回答
11

因为data是 2D 数组 - 所有data, &data, *data, data[0], &data[0], 和&data[0][0]指向数组的基数。可以选择上述任何表示来正确构造Matin 代替Xin

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

放心,因为 OpenCV 接受数据,并且 OpenCV 的数据void*访问是 in line。我更喜欢从单维或多维数组构造 Mat 的相同语法。

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

回到查询 - 请注意,您Mat从一维数组构建的偶数是不正确的。step 参数被提到为 2。它只是碰巧起作用,因为如果行数为 1, OpenCV会覆盖提供的 step 参数。对于更高维数组,OpenCV 会为您得到的不正确的 step 参数抛出调试断言

于 2014-05-18T13:57:33.417 回答
1

此合并拉取请求中的 C++11 解决方案:

// Mat(sizes, list)
cv::Mat A({2, 5}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
于 2021-09-08T17:21:56.247 回答