2017-08-25 123 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); 
    } 
}