如何通过另一个具有位置(索引)的垫子访问opencv中的矩阵数据
Posted
技术标签:
【中文标题】如何通过另一个具有位置(索引)的垫子访问opencv中的矩阵数据【英文标题】:How to access matrix data in opencv by another mat with locations (indexing) 【发布时间】:2018-03-11 11:40:31 【问题描述】:假设我有一个名为 B 的索引(位置)Mat,我们可以说这个 Mat 的维度为 1 x 100
并且我们假设有另一个 Mat,称为 A,充满了与 B 相同维度的数据。
现在,我将使用 B 访问 A 的数据。通常我会创建一个 for 循环,并且我会获取 B 的每个元素,A 的正确元素。对于最挑剔的网站,这是我的代码会写:
for(int i=0; i < B.cols; i++)
int index = B.at<int>(0, i);
std::cout<<A.at<int>(0, index)<<std:endl;
好的,现在我已经向您展示了我可以做什么,请问您是否有一种方法可以更智能、更快速地访问矩阵 A,始终使用 B 索引。由于numpy.take()
函数,有人可以在 python 中执行此操作。
【问题讨论】:
【参考方案1】:此操作称为remapping。在 OpenCV 中,您可以为此目的使用函数 cv::remap。
下面我将介绍重映射算法如何工作的非常基本的示例;请注意,在此示例中我不处理边界条件,但 cv::remap
处理 - 它允许您使用镜像、钳制等来指定如果索引超过图像尺寸会发生什么。我也没有展示插值是如何完成的;检查我上面链接到的cv::remap
文档。
如果您要使用重映射,您可能必须将索引转换为浮点数;如果您的图像是一维的,您还必须引入另一个索引数组,该数组应该是微不足道的(都等于 0)。如果这开始代表性能问题,我建议您自己实现一维重映射等效项。当然,在优化之前先进行基准测试。
有关所有详细信息,请查看文档,其中涵盖了使用 te 算法所需了解的所有内容。
cv::Mat<float> remap_example(cv::Mat<float> image,
cv::Mat<float> positions_x,
cv::Mat<float> positions_y)
// sizes of positions arrays must be the same
int size_x = positions_x.cols;
int size_y = positions_x.rows;
auto out = cv::Mat<float>(size_y, size_x);
for(int y = 0; y < size_y; ++y)
for(int x = 0; x < size_x; ++x)
float ps_x = positions_x(x, y);
float ps_y = positions_y(x, y);
// use interpolation to determine intensity at image(ps_x, ps_y),
// at this point also handle border conditions
// float interpolated = bilinear_interpolation(image, ps_x, ps_y);
out(x, y) = interpolated;
return out;
【讨论】:
【参考方案2】:一种快速的方法是对 A(数据)和 B(索引)都使用指针。
const int* pA = A.ptr<int>(0);
const int* pIndexB = B.ptr<int>(0);
int sum = 0;
for(int i = 0; i < Bi.cols; ++i)
sum += pA[*pIndexB++];
注意:注意像素类型,在这种情况下(如您在代码中所写)是 int!
注意2:对每个点访问使用cout会使优化无用!
注意3:在本文中 Satya 比较了四种像素访问方法,最快的似乎是“foreach”:https://www.learnopencv.com/parallel-pixel-access-in-opencv-using-foreach/
【讨论】:
以上是关于如何通过另一个具有位置(索引)的垫子访问opencv中的矩阵数据的主要内容,如果未能解决你的问题,请参考以下文章
如何使用另一个日期时间索引获取具有日期时间索引的 Pandas 数据框中的行?