是否有某种方法可以生成以下形式的二维矩阵:
(0, 0) (1, 0) (2, 0) (3, 0)
(0, 1) (1, 1) (2, 1) (3, 1)
(0, 2) (1, 2) (2, 2) (3, 2)
(0, 3) (1, 3) (2, 3) (3, 3)
在索引表示法中,此矩阵可表示为grid[j, i] = (i, j)
。
生成此网格的一个简单方法是:
auto grid = cv::Mat(height, width, CV_32FC2);
for (auto j = 0; j < height; j++) {
for (auto i = 0; i < width; i++) {
grid.at<cv::Vec2f>(j, i) = cv::Point2f(i, j);
}
}
但这很慢,“手动”,有点难看。
在Python中,可以这样做:
grid = np.dstack(np.meshgrid(np.arange(width), np.arange(height)))
在C ++中生成cv::Mat
类型网格的好方法是什么?
答案 0 :(得分:2)
C ++循环可能与硬件允许的速度一样快。我假设优化器将隐式static_cast<float>(j)
移出内部循环。
C ++确实有std::iota
但它只适用于1D容器。
OpenCV方法为cv::Mat::forEach
,它会调用您的函数为每个像素传递int position[2]
。 OpenCV文档有3D example,但它与您尝试做的几乎相同。
答案 1 :(得分:1)
如果您不使用at()
方法,它会更快,因为这是访问单个值的最慢方式(请参阅docs for Mat)。请改用ptr()
:
for (auto j = 0; j < height; j++) {
cv::Vec2f* row = grid.ptr<cv::Vec2f>(j);
for (auto i = 0; i < width; i++) {
row[i] = cv::Point2f(i, j);
}
}
或指向data
成员的指针:
cv::Vec2f* arr = (cv::Vec2f*) grid.data;
for (auto j = 0; j < width; j++) {
for (auto i = 0; i < height; i++) {
arr[grid.cols*i + j] = cv::Point2f(i, j);
}
}