2017-04-06 10 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

こんにちは@トニーJ、あなたの返信に感謝します。私はintの代わりにucharを使いました。グリッド内のノードの値を入力しようとすると、問題が始まります。 'grid.grid [10] [10] .NodeID' – Ahmohamed

答えて

0

まず、using namespace std;を取り除いてください。便利に見えるかもしれませんが、厄介な驚きのために自分自身を設定しています(this質問を参照)。

コンストラクタGridは、デフォルトのコンストラクタGrid::gridを使用して、空のベクトルを作成します。

PrintGridでは、未定義の動作が発生します。あなたはそれを呼び出すことはありませんので、方法CreateGridがあることが

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. 

は、ここでは関係ありません。しかし、あなたがそれを呼び出したと仮定しよう。その後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 :: 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():walkable(false){}'か、自動生成された 'Node()= default;'を使用してください。同じことが、コピーコンストラクタ 'Node(const&Node)'にも必要です。 – mars

+0

@marsありがとう、私の問題を解決しました。私はどんなエラーもなくスムーズに動くことができます。そして、私はポインタを使わずに実行して、進歩をより簡単にします。ありがとうございました – Ahmohamed

関連する問題