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

pen*_*ope 9 c++ opencv copy vector

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

浏览OpenCV文档非常令人困惑,除非我将页面标记为Googling两次找不到文档页面,其中大部分内容并不容易导航.

我发现cv::Mat::at(..)要访问Matrix元素,但我记得C OpenCV至少有3种不同的方式来访问元素,所有这些方法都用于不同的目的...不记得用于哪些:/

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

And*_*aev 29

应该这么简单:

m.row(row_idx).copyTo(v);
Run Code Online (Sandbox Code Playgroud)

mcv::MatCV_64F深度和vstd::vector<double>


Fer*_*yer 17

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

// 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.);
}
Run Code Online (Sandbox Code Playgroud)

因此,最有效的方法是将普通指针传递给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);
Run Code Online (Sandbox Code Playgroud)

这当然是比使用迭代器由归国更快begin()end(),因为这些涉及额外的计算以行之间的差距支持.


Xeo*_*Xeo 6

这里的文档中,您可以获得一个特定的行cv::Mat::row,它将返回一个新的cv::Mat,您可以使用cv::Mat::begin和迭代它cv::Mat::end.因此,以下应该有效:

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>());
Run Code Online (Sandbox Code Playgroud)

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

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

这也来自文档化,因此您实际上可以在没有副本的情况下执行此操作:

cv::Mat m/*= initialize */;
// ... do whatever...
// first row          begin              end
std::vector<double> v(m.begin<double>(), m.begin<double>() + m.size().width);
Run Code Online (Sandbox Code Playgroud)

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

  • 而不是`m.size().width`,你可以直接使用`m.cols`. (2认同)