如何通过另一个具有位置的垫子访问opencv中的矩阵数据(索引)
How to access matrix data in opencv by another mat with locations (indexing)
假设我有一个名为 B 的索引(位置)矩阵,我们可以说这个矩阵具有 1 x 100
的维度并且我们假设有另一个矩阵,称为 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 中做到这一点。
为此目的,此操作被称为 remapping. In OpenCV, you can use function cv::remap。
下面我展示了重映射算法如何工作的非常基本的例子;请注意,在这个例子中我不处理边界条件,但 cv::remap
处理 - 它允许您使用镜像、夹紧等来指定如果索引超过图像的尺寸会发生什么。我也没有说明插值是如何完成的;查看我上面链接的 cv::remap
文档。
如果您要使用重新映射,您可能必须将索引转换为浮点数;如果您的图像是 one-dimensional,您还必须引入另一个索引数组,这些索引应该是微不足道的(全部等于 0)。如果这开始代表性能问题,我建议您自己实现等效的 1-D 重映射。当然,在优化之前先进行基准测试。
有关所有详细信息,请查看文档,其中涵盖了使用算法所需了解的所有内容。
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;
}
一种快速的方法是对 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/
假设我有一个名为 B 的索引(位置)矩阵,我们可以说这个矩阵具有 1 x 100
的维度并且我们假设有另一个矩阵,称为 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 中做到这一点。
为此目的,此操作被称为 remapping. In OpenCV, you can use function cv::remap。
下面我展示了重映射算法如何工作的非常基本的例子;请注意,在这个例子中我不处理边界条件,但 cv::remap
处理 - 它允许您使用镜像、夹紧等来指定如果索引超过图像的尺寸会发生什么。我也没有说明插值是如何完成的;查看我上面链接的 cv::remap
文档。
如果您要使用重新映射,您可能必须将索引转换为浮点数;如果您的图像是 one-dimensional,您还必须引入另一个索引数组,这些索引应该是微不足道的(全部等于 0)。如果这开始代表性能问题,我建议您自己实现等效的 1-D 重映射。当然,在优化之前先进行基准测试。
有关所有详细信息,请查看文档,其中涵盖了使用算法所需了解的所有内容。
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;
}
一种快速的方法是对 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/