将一行 cv::Mat 转换为 std::vector
Posted
技术标签:
【中文标题】将一行 cv::Mat 转换为 std::vector【英文标题】:Converting a row of cv::Mat to std::vector 【发布时间】:2012-03-20 15:47:06 【问题描述】:我有一个相当简单的问题:如何取出cv::Mat
的一行并获取std::vector
中的所有数据? cv::Mat
包含 doubles
(就问题而言,它可以是任何简单的数据类型)。
浏览 OpenCV 文档非常令人困惑,除非我将页面添加为书签
我找到了cv::Mat::at(..)
来访问 Matrix 元素,但我记得 C OpenCV
至少有 3 种不同的方式来访问元素,它们都用于不同的目的......不记得是什么用于哪个:/
因此,虽然逐个元素复制 Matrix 肯定会奏效,但我正在寻找一种更高效并且如果可能的话更优雅的方法> 而不是每行的 for 循环。
【问题讨论】:
我认为这是一个重复的问题:***.com/questions/5405070/… @piokuc 我看到了那个,但那是特定于平台的(Visual Studio),对于 OpenCV 2.0(比今天更旧的版本)和涉及特定的cv::Mat
包装器@ 987654329@
【参考方案1】:
应该很简单:
m.row(row_idx).copyTo(v);
其中m
是cv::Mat
,具有CV_64F
深度,v
是std::vector<double>
【讨论】:
哇,这太棒了。但是,因为我实际上需要创建一个新向量并用数据填充它,所以我认为在这种情况下,只提供指向向量构造函数的指针会更好。 这应该是答案。如此简单!【参考方案2】: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()
返回的迭代器要快,因为它们需要额外的计算来支持行之间的间隙。
【讨论】:
【参考方案3】:从here 的文档中,您可以通过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>());
请注意,我不知道任何 OpenCV,但谷歌搜索“OpenCV mat”直接导致基本类型文档,据此,这应该可以正常工作。
矩阵迭代器是随机访问迭代器,因此它们可以传递给任何 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);
要访问第一行以外的内容,我建议使用第一个 sn-p,因为这样会更干净,而且似乎没有任何繁重的复制,因为数据类型似乎是引用 -计数。
【讨论】:
您在第二个示例中是指m.size().width
吗?请注意,OpenCV 矩阵以行为主存储,并且您正在添加 rows 的数量,而您可能应该添加 columns 的数量。
@Ferdinand:糟糕,是的,这确实是我的本意。感谢您的提示。
可以直接用m.cols
代替m.size().width
。【参考方案4】:
你也可以使用cv::Rect
m(cv::Rect(0, 0, 1, m.cols))
会给你第一行。
matrix(cv::Rect(x0, y0, len_x, len_y);
表示你会从matrix
得到sub_matrix
,它的左上角是(x0,y0)
,大小是(len_x, len_y)
。 (row,col)
【讨论】:
应该是m(cv::Rect(0, 0, m.cols, 1))
,而不是1, m.cols
。【参考方案5】:
我认为这可行,
一个例子:
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));
【讨论】:
以上是关于将一行 cv::Mat 转换为 std::vector的主要内容,如果未能解决你的问题,请参考以下文章