生成坐标网格

时间:2017-08-25 08:06:43

标签: c++ opencv

是否有某种方法可以生成以下形式的二维矩阵:

(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类型网格的好方法是什么?

2 个答案:

答案 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);
    }
}