我想知道在 OpenCV 中访问 Mat 中数据的方式。如您所知,我们可以通过多种方式访问以获取数据。我想在 Mat 中存储图像(宽度 x 高度 x 1 深度)并循环访问图像中的每个像素。使用 ptr<>(irow) 获取行像素然后访问行中的每一列是最好的方法吗?还是使用 at<>(irow,jcol) 是最好的?还是使用 index = irow*Width + jrow 直接计算索引是最好的?任何人都知道原因。
提前致谢
我想知道在 OpenCV 中访问 Mat 中数据的方式。如您所知,我们可以通过多种方式访问以获取数据。我想在 Mat 中存储图像(宽度 x 高度 x 1 深度)并循环访问图像中的每个像素。使用 ptr<>(irow) 获取行像素然后访问行中的每一列是最好的方法吗?还是使用 at<>(irow,jcol) 是最好的?还是使用 index = irow*Width + jrow 直接计算索引是最好的?任何人都知道原因。
提前致谢
如果您没有 OpenCV 或 C 语言类型的经验,我建议您使用at
( here ) 进行练习。但最快的方法是ptr
Nolwenn的回答,因为您避免了类型检查。
我意识到这是一个老问题,但我认为当前的答案在某种程度上具有误导性。
同时调用at<T>(...)
和ptr<T>(...)
将在调试模式下检查边界。如果_DEBUG
未定义宏,它们基本上会计算y * width + x
并为您提供指向数据的指针或数据本身。所以at<T>(...)
在释放模式下使用相当于自己计算指针,但更安全,因为计算指针不仅仅是y * width + x
如果矩阵只是另一个矩阵的子视图。在调试模式下,您将获得安全检查。
我认为最好的方法是逐行处理图像,使用获取行指针ptr<T>(y)
,然后使用p[x]
. 这样做的好处是您不必计算各种数据布局并且仍然是内部循环的普通指针。
您可以一直使用普通指针,这将是最有效的,因为您避免了每行乘法之一,但是您需要使用step1(i)
来推进指针。我认为使用ptr<T>(y)
是一个很好的权衡。
at<T>
每次调用时都会进行范围检查,从而使其比 慢ptr<T>
,但更安全。
因此,如果您确信您的范围计算是正确的并且您想要尽可能快的速度,请使用ptr<T>
.
根据官方文档,他们建议最有效的方法是先获取指向行的指针,然后使用普通的 C 运算符 []。它还为每次迭代保存了一个乘法。
// compute sum of positive matrix elements
// (assuming that M isa 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.);
}