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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9790124/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:17:29  来源:igfitidea点击:

Converting a row of cv::Mat to std::vector

c++opencvvectorcopy

提问by penelope

I have a fairly simple question: how to take one row of cv::Matand get all the data in std::vector? The cv::Matcontains doubles(it can be any simple datatype for the purpose of the question).

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

Going through OpenCV documentation is just very confusing, unless I bookmark the page I can not find a documentation page twice by Googling, there's just to much of it and not easy to navigate.

浏览 OpenCV 文档非常令人困惑,除非我将页面添加为书签,否则我无法通过谷歌搜索两次找到文档页面,其中太多并且不容易导航。

I have found the cv::Mat::at(..)to access the Matrix element, but I remember from C OpenCVthat there were at least 3 different ways to access elements, all of them used for different purposes... Can't remember what was used for which :/

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

So, while copying the Matrix element-by-element will surely work, I am looking for a way that is more efficientand, if possible, a bit more elegantthan a for loop for each row.

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

回答by Andrey Kamaev

It should be as simple as:

它应该很简单:

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

Where mis cv::Mathaving CV_64Fdepth and vis std::vector<double>

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

回答by Ferdinand Beyer

Data in OpenCV matrices is laid out in row-major order, so that each row is guaranteed to be contiguous. That means that you can interpret the data in a row as a plain C array. The following example comes directly from the documentation:

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

Therefore the most efficient way is to pass the plain pointer to std::vector:

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

This is certainly faster than using the iterators returned by begin()and end(), since those involve extra computation to support gaps between rows.

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

回答by Xeo

From the documentation at here, you can get a specific row through cv::Mat::row, which will return a new cv::Mat, over which you can iterator with cv::Mat::beginand cv::Mat::end. As such, the following should work:

此处的文档中,您可以获得一个特定的行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>());

Note that I don't know any OpenCV, but googling "OpenCV mat" led directly to the basic types documentation and according to that, this should work fine.

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

The matrix iterators are random-access iterators, so they can be passed to any STL algorithm, including std::sort() .

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

This is also from the documentiation, so you could actually do this without a copy:

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

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

To access more than the first row, I'd recommend the first snippet, since it will be a lot cleaner that way and there doesn't seem to be any heavy copying since the data types seem to be reference-counted.

要访问比第一行更多的内容,我建议使用第一个片段,因为这样会更清晰,而且似乎没有任何大量复制,因为数据类型似乎是引用计数的。

回答by smttsp

You can also use cv::Rect

你也可以使用 cv::Rect

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

will give you first row.

会给你第一排。

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

means that you will get sub_matrixfrom matrixwhose upper left corner is (x0,y0)and size is (len_x, len_y). (row,col)

意味着你会得到sub_matrixmatrix它的左上角是(x0,y0)和大小(len_x, len_y)(row,col)

回答by user3102903

I think this works,

我认为这有效,

an example :

一个例子 :

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

cropping the 1st row of the matrix:

裁剪矩阵的第一行:

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

then:

然后:

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

vector_of_rows.push_back(Input(roi));