2017-04-06 85 views
1

我正在構建一個使用OpenCV Mat的搜索算法,在這裏我將Mat轉換爲灰色圖像,然後檢查像素以便將其簽名爲可走或不可走及其座標。我使用矢量>網格。當我嘗試從網格中打印節點ID時,程序突然關閉(例如grid.grid[10][10]->NodeID)。創建opencv Mat到2d網格

using namespace std; 
int gridZise; 
class location{ 
public: 
    int x; 
    int y; 

}; 

class Node{ 
public: 
    int gridX; 
    int gridY; 
    bool walkable; 
    location worldPosition; 
    int NodeID; 


    int gCost; 
    int hCost; 
    Node *parent; 

    Node(bool _walkable, int _gridX, int _gridY) 
     { 
      walkable = _walkable; 
      gridX = _gridX; 
      gridY = _gridY; 
      NodeID = gridY * gridZise + gridX; 
     } 
    Node(int _gridX, int _gridY){ 
     gridX = _gridX; 
     gridY = _gridY; 
     NodeID = gridY * gridZise + gridX; 
    } 

    int fCost(){ 
     return gCost + hCost; 
    } 

}; 

class Grid{ 

public: 
    cv::Mat map; 
    vector<vector<Node*> > grid; 
    int gridx; 
    int gridy; 


    Grid(cv::Mat _map){ 
     map = _map; 
     gridx = map.cols; 
     gridy = map.cols; 
     gridZise = map.cols; 
    } 

    void CreateGrid(){ 
     // Set up sizes. (HEIGHT x WIDTH) 
      grid.resize(gridy); 
      for (int i = 0; i < gridy; ++i) 
      grid[i].resize(gridx); 

      // build up the grid 
      for(int i=0; i <gridx;i++){ 
       for(int j=0; j < gridy;j++){ 
        int pixel_val = map.at<int>(i,j); 
        bool _walkable = false; 
        if(pixel_val > 120){//if the value of the pixel is bigger than 120 is walkable 
         _walkable = true; 
        } 
        grid[i][j]->walkable = _walkable; 
        grid[i][j]->gridX = i; 
        grid[i][j]->gridY = j; 
       } 
      } 
    } 

    void PrintGrid(){ 
     for(int i=0; i <gridx;i++){ 
      for(int j=0; j < gridy;j++){ 
       cout << grid[i][j]->NodeID <<endl; 
      } 
     } 
    } 

    vector<Node> GetNeighbours(Node node) 
     { 
      vector<Node> neighbours; 

      for (int x = -1; x <=1; x++) 
      { 
       for (int y = -1; y <= 1; y++) 
       { 
        if (x == 0 && y == 0) 
         continue; 

        int checkX = node.gridX + x; 
        int checkY = node.gridY + y; 

        if(checkX >=0 && checkX < gridx && checkY >=0 && checkY < gridy) 
        { 
         Node neighbour(checkX,checkY); 
         neighbours.push_back(neighbour); 
        } 
       } 
      } 
      return neighbours; 
     } 

    Node nodeFromLocation(location _node){ 
     Node currentNode = *grid[_node.x][_node.y]; 
     return currentNode; 
    } 

}; 


using namespace cv; 
int main() 
{ 
    cv::Mat img; 
    img = imread("C:\\Users\\abdulla\\Pictures\\maze.jpg"); 

    if(img.empty()){ 
     cout<<"image not load "<<endl; 
     return -1; 
    } 
    cvtColor(img,img,CV_BGR2GRAY); 
    imshow("image",img); 
    waitKey(); 
    Grid grid(img); 

    grid.PrintGrid(); 

    return 0; 
} 

謝謝。

+0

灰色圖像CV_8UC,所以你需要UCHAR,'UCHAR pixel_val = map.at (I,J讀取每個像素);'。你也可以用'img = imread(path,CV_LOAD_IMAGE_GRAYSCALE)'加載圖像,所以你不必再次將它轉換爲灰色。 –

+0

嗨@Tony J,謝謝你的回覆。我確實使用了uchar而不是int。當我嘗試在網格中輸入節點的值時,問題就開始了。 'grid.grid [10] [10] .NodeID' – Ahmohamed

回答

0

首先,擺脫using namespace std;。雖然它看起來很方便,但你正在爲自己設定一些令人討厭的驚喜(參見this問題)。

Grid的構造函數使用Grid::grid的默認構造函數,該構造函數創建一個空向量。

PrintGrid你會得到未定義的行爲。

grid; // ok, grid is a member of Grid 
grid[0]; // Returns a reference. No bounds checking is performed. 
grid[0][0]; // undefined behaviour. grid[0] is outside of bounds. 

那有一個方法CreateGrid是不是與此有關,因爲你永遠不調用它。但讓我們假設你已經調用了它。然後PrintGrid會這樣工作:

grid; // ok, grid is a member of Grid 
grid[0]; // ok 
grid[0][0]; // ok, return a pointer to a Node. Which you never initialized. 
grid[0][0]->NodeID; // Undefined behaviour. You're trying to access a random memory location. 

您是否真的需要將節點存儲爲指針?你也可以使用vector<vector<Node>>。這樣,有人(std::vector<...)將負責分配和刪除節點。你仍然可以使用指針指向父母,只要指針用作參考而不是所有權即可。

如果你確實需要存儲指針,make use of smart pointers。這樣,有人會負責刪除節點。

最後,類Grid負責維護正確的狀態。總是。所以構造函數應該已經做了CreateGrid。問題在於你不能從構造函數中調用CreateGrid,因爲那樣你就會調用一個終身尚未開始的對象的方法(如果我在那個問題上有錯,有人會糾正我)。 如果你想保持它作爲一個獨立的功能,你可以讓CreateGrid靜:

class Grid { 
    Grid(cv::Mat _map): 
      map(_map), 
      gridx(_map.cols), 
      gridy(_map.cols), 
      gridZise(_map.cols), 
    { 
     GreateGrid(grid, map, gridx, gridy); 
    } 

//... 
    static void CreateGrid(std::vector<std::vector<Node>> & grid, cv::Mat map, int gridx, int grid y) { 
    //... 
    } 
//... 
}; 
+0

謝謝@mars,這對你的建議非常有用。正如你所說,我重新組織了我的代碼。然而,我使用節點作爲點的原因,因爲當我沒有指針使用它時,我得到這個錯誤'錯誤:沒有匹配函數調用'Node :: Node()' {:: new(static_cast (__p))_T1 (std :: forward <_Args>(__args)...); }'這甚至不在我的代碼文件中。 – Ahmohamed

+0

這個問題可以解決。編譯器抱怨說它不能默認構建Node,但是如果你調整了矢量的大小,它必須要這樣做。無論何時您創建任何自定義構造函數,C++都不會提供自動生成的構造函數。可能的解決方案是:1)使用reserve和push_back,2)指定在調整大小期間使用的Node的值(例如'.resize(10,Node(false,0,0));'),3) 'Node'。可以自己提供'Node():walkable(false){}'或者使用自動生成的'Node()= default;'。如果你也需要拷貝構造函數'Node(const&Node)',也是一樣的。 – mars

+0

謝謝@mars,解決了我的問題。我設法順利運行,沒有任何錯誤,我設法運行它沒有指針,使進展更容易。再次感謝你 – Ahmohamed