c++ - 将opencv Mat创建为二维网格

标签 c++ opencv path-finding a-star

我正在使用 OpenCV Mat 构建一个搜索算法,我将 Mat 转换为灰度图像,然后检查像素以使用其坐标将其标记为可步行或不可步行。我使用 vector > 网格。当我尝试从网格中打印 nodeID 时,程序突然关闭(例如 grid.grid[10][10]->NodeID)。

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

谢谢。

最佳答案

首先,去掉using namespace std; .虽然它看起来很方便,但您正在为一些令人讨厌的惊喜做好准备(请参阅 this 问题)。

Grid 的构造函数使用 Grid::grid 的默认构造函数,它创建一个空 vector 。

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) {
    //...
    }
//...
};

关于c++ - 将opencv Mat创建为二维网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43265085/

相关文章:

C++ - 在寻路中对 std::vector 进行排序

c# - 使用 NavMesh 寻找距离较近的玩家

c++ - 如何使用std::find查找具有struct成员值的set元素?

c++ - 等效于 Linux 上的 SetThreadPriority (pthreads)

python - 如下应用 SLIC 后如何检测云的百分比?

django - Python opencv等待相机空闲

opencv - GPU中的Opencv特征检测

c++ - doxygen 与 IDL/ODL

c++ - GCC 生成了未对齐的 "ldrd"指令

r - 如何在迷宫中找到最短路线?