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
Converting a row of cv::Mat to std::vector
提问by penelope
I have a fairly simple question: how to take one row of cv::Mat
and get all the data in std::vector
? The cv::Mat
contains 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 OpenCV
that 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 m
is cv::Mat
having CV_64F
depth and v
is std::vector<double>
凡m
被cv::Mat
其CV_64F
深度和v
是std::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::begin
and 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_matrix
from matrix
whose upper left corner is (x0,y0)
and size is (len_x, len_y)
. (row,col)
意味着你会得到sub_matrix
从matrix
它的左上角是(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));