2017-08-25 168 views
0

有一些方法,以产生以下形式的2D矩阵:生成坐标网格

(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

为什么需要这样的电网?这些东西通常用在MATLAB或Python中以避免循环。我的C++循环工作得很快,不需要这种格子这种情况。如果你真的需要它,那么你在CPP中展示的方式是可以的。 –

+0

@AndreySmorodov我需要这个网格的原因是对每个点应用仿射变换来查看它的结束位置。粗略地说,'transform.dot(grid.reshape(width * height,2).transpose())'会为我提供一个每个点在变换下最终位置的列表。 –

+1

如果我没有误会,你缺少用于内循环的{}。没有'{}'只有第一个下面的语句会从嵌套循环中执行 –

回答

2

C++循环可能与硬件所允许的一样快。我假设隐式的static_cast<float>(j)被优化器移到内部循环之外。

C++确实有std::iota但它只适用于一维容器。

OpenCV的方法是cv::Mat::forEach,它会调用你的函数为每个像素传递一个int position[2]。 OpenCV文档有一个3D example,但它几乎与你想要做的一样。

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