将一行cv :: Mat转换为std :: vector

时间:2012-03-20 15:47:07

标签: c++ opencv vector copy

我有一个相当简单的问题:如何获取一行cv::Mat并获取std::vector中的所有数据? cv::Mat包含doubles(出于问题的目的,它可以是任何简单的数据类型。)

浏览OpenCV文档非常令人困惑,除非我将页面标记为Googling两次找不到文档页面,只有很多内容并且不易导航。

我找到cv::Mat::at(..)来访问Matrix元素,但我记得C OpenCV至少有3种不同的方式来访问元素,所有这些方法都用于不同的目的......可以不记得使用了什么:/

因此,虽然逐个元素复制Matrix肯定会有效,但我正在寻找一种更高效的方式,如果可能的话,更优雅比每行的for循环。

5 个答案:

答案 0 :(得分:29)

应该如此简单:

m.row(row_idx).copyTo(v);

m cv::Mat CV_64F v深度为std::vector<double>且{{1}}为{{1}}

答案 1 :(得分:17)

OpenCV矩阵中的数据按行主顺序排列,因此保证每一行都是连续的。这意味着您可以将行中的数据解释为普通C数组。以下示例直接来自the documentation

// compute sum of positive matrix elements
// (assuming that M is double-precision matrix)
double sum=0;
for(int i = 0; i < M.rows; i++)
{
    const double* Mi = M.ptr<double>(i);
    for(int j = 0; j < M.cols; j++)
        sum += std::max(Mi[j], 0.);
}

因此,最有效的方法是将普通指针传递给std::vector

// Pointer to the i-th row
const double* p = mat.ptr<double>(i);

// Copy data to a vector.  Note that (p + mat.cols) points to the
// end of the row.
std::vector<double> vec(p, p + mat.cols);

这肯定比使用begin()end()返回的迭代器更快,因为那些涉及额外的计算以支持行之间的间隙。

答案 2 :(得分:6)

here处的文档中,您可以通过cv::Mat::row获得一个特定的行,该行将返回一个新的cv::Mat,您可以使用cv::Mat::begin和{{{}}进行迭代。 {1}}。因此,以下内容应该有效:

cv::Mat::end

请注意,我不知道任何OpenCV,但谷歌搜索“OpenCV垫”直接导致基本类型文档,并据此,这应该工作正常。

  

矩阵迭代器是随机访问迭代器,因此它们可以传递给任何STL算法,包括std :: sort()。

这也来自文档化,所以你可以在没有副本的情况下实际做到这一点:

cv::Mat m/*= initialize */;
// ... do whatever...
cv::Mat first_row(m.row(0));
std::vector<double> v(first_row.begin<double>(), first_row.end<double>());

要访问第一行以上,我建议使用第一个代码段,因为它会更加清晰,因为数据类型似乎是引用计数,所以似乎没有任何繁重的复制。

答案 3 :(得分:2)

您也可以使用cv::Rect

m(cv::Rect(0, 0, 1, m.cols)) 

会给你第一行。

matrix(cv::Rect(x0, y0, len_x, len_y);

表示您将从sub_matrix获取matrix,其左上角为(x0,y0),尺寸为(len_x, len_y)(row,col)

答案 4 :(得分:0)

我认为这很有效,

一个例子:

Mat Input(480, 720, CV_64F, Scalar(100));

裁剪矩阵的第一行:

Rect roi(Point(0, 0), Size(720, 1));

然后:

std::vector<std::vector<double> > vector_of_rows;

vector_of_rows.push_back(Input(roi));