【计算机视觉】--路径规划

12 篇文章 0 订阅
3 篇文章 0 订阅

简介

OpenCV实现路径规划算法时,通常会使用图像/图形来表示环境,然后在该该图像/图形上进行路径搜索。

1、加载地图

imread函数加载地图图像,确保每个像素代表地图的一个单元。白色像素表示可通过区域,黑色像素表示障碍物或不可通过区域。

2、定义起点和目标

在地图图像上选择起点和目标位置。

3、创建数据结构

为路径规划算法创建必要的数据结构。我们需要定义一个节点(Node)类,该类包含节点的位置、代价值和父节点等信息。还需要创建一个开放集(Open Set)和一个关闭集(Closed Set),用于存储待探索和已探索的节点。

4、算法实现

	· 将起点添加到开放集中,并初始化起点的代价值和启发式值(通常使用欧几里得距离或曼哈顿距离)。
	· 循环执行以下步骤,直到找到目标节点或开放集为空:
		· 从开放集中选择具有最低总代价值的节点作为当前节点。
		· 如果当前节点是目标节点,则表示路径已找到,停止搜索。
		· 否则,将当前节点从开放集中移除,并将其添加到关闭集中。
		·生成当前节点的邻居节点(上、下、左、右、斜对角等方向)。
		·对于每个邻居节点,计算代价值和启发式值,并更新节点的代价值和父节点。
		· 如果邻居节点已在开放集或关闭集中,则比较新的代价值与已有的代价值,保留较小的代价值。
		· 如果邻居节点不在开放集中,则将其添加到开放集中。

5、生成路径

当搜索结束后,如果找到了目标节点,则可以通过回溯父节点的方式生成路径。从目标节点开始,依次跟踪父节点指针,回溯到起点节点,形成完整的路径。

6、可视化路径

绘图函数(如line函数)将生成的路径在地图上可视化。

C++实现

struct Node {
    cv::Point position;
    double cost;
    double heuristic;
    Node* parent;

    Node(cv::Point pos, double cost, double heuristic, Node* parent = nullptr)
        : position(pos), cost(cost), heuristic(heuristic), parent(parent) {}

    double getTotalCost() const { return cost + heuristic; }
};

bool isValidCell(const cv::Mat& map, int x, int y) {
    if (x >= 0 && x < map.rows && y >= 0 && y < map.cols) {
        return map.at<uchar>(x, y) != 0;
    }
    return false;
}

double computeHeuristic(const cv::Point& p1, const cv::Point& p2) {
    // 曼哈顿距离
    return std::abs(p1.x - p2.x) + std::abs(p1.y - p2.y);
}

std::vector<cv::Point> findPath(const cv::Mat& map, const cv::Point& start, const cv::Point& goal) {
    std::vector<cv::Point> path;
    std::vector<Node*> openSet;
    std::vector<Node*> closedSet;

    Node* startNode = new Node(start, 0.0, computeHeuristic(start, goal));
    openSet.push_back(startNode);

    while (!openSet.empty()) {
        Node* current = openSet[0];
        int currentIndex = 0;
        for (int i = 1; i < openSet.size(); ++i) {
            if (openSet[i]->getTotalCost() < current->getTotalCost()) {
                current = openSet[i];
                currentIndex = i;
            }
        }

        openSet.erase(openSet.begin() + currentIndex);

        closedSet.push_back(current);
        
        if (current->position == goal) {
            Node* node = current;
            while (node != nullptr) {
                path.push_back(node->position);
                node = node->parent;
            }

            for (Node* node : openSet) {
                delete node;
            }
            for (Node* node : closedSet) {
                delete node;
            }

            return path;
        }

        std::vector<cv::Point> offsets = {
            cv::Point(-1, 0), cv::Point(1, 0), cv::Point(0, -1), cv::Point(0, 1),
            cv::Point(-1, -1), cv::Point(-1, 1), cv::Point(1, -1), cv::Point(1, 1)
        };
        for (const cv::Point& offset : offsets) {
            int x = current->position.x + offset.x;
            int y = current->position.y + offset.y;

            if (isValidCell(map, x, y)) {
                double cost = current->cost + 1.0;  // Assuming constant cost for each movement
                double heuristic = computeHeuristic(cv::Point(x, y), goal);
                Node* successor = new Node(cv::Point(x, y), cost, heuristic, current);
                bool skip = false;

                for (const Node* closedNode : closedSet) {
                    if (successor->position == closedNode->position && successor->getTotalCost() >= closedNode->getTotalCost()) {
                        skip = true;
                        break;
                    }
                }

                if (skip) {
                    delete successor;
                    continue;
                }

                for (Node* openNode : openSet) {
                    if (successor->position == openNode->position && successor->getTotalCost() >= openNode->getTotalCost()) {
                        skip = true;
                        break;
                    }
                }

                if (skip) {
                    delete successor;
                    continue;
                }

                // Add successor to the open set
                openSet.push_back(successor);
            }
        }
    }

    for (Node* node : openSet) {
        delete node;
    }
    for (Node* node : closedSet) {
        delete node;
    }

    return path;  
}

int main() {
    cv::Mat map = cv::imread("map.png", cv::IMREAD_GRAYSCALE);
    if (map.empty()) {
        std::cout << "Failed to load map image!" << std::endl;
        return 1;
    }

    cv::Point start(10, 10);
    cv::Point goal(200, 200);

    std::vector<cv::Point> path = findPath(map, start, goal);

    // Visualize the path on the map
    cv::cvtColor(map, map, cv::COLOR_GRAY2BGR);
    for (int i = 1; i < path.size(); ++i) {
        cv::line(map, path[i - 1], path[i], cv::Scalar(0, 0, 255), 2);
    }
}

这是一个简单的路径规划算法实现,可以根据实际需求进行扩展和优化。路径规划是一个广泛的领域,有很多更复杂和高级的算法可以用于不同的应用场景。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 非常好的问题!以下是我为您提供的计算机类大学四年路径规划: 第一年: 1. 计算机基础课程:计算机组成原理、数据结构、算法设计与分析、操作系统等 2. 编程语言:C++或Python等 3. 数学基础课程:高等数学、线性代数、概率论与数理统计等 第二年: 1. 计算机网络:网络协议、网络编程等 2. 数据库:数据库理论、SQL语言、数据库应用等 3. 离散数学:图论、组合数学等 第三年: 1. 人工智能:机器学习、深度学习、自然语言处理等 2. 计算机安全:密码学、网络安全、信息安全等 3. 软件工程:软件设计、软件测试、软件项目管理等 第四年: 1. 大数据技术:Hadoop、Spark、NoSQL等 2. 分布式系统:分布式计算、分布式数据库等 3. 计算机图形学:图像处理、计算机视觉、虚拟现实等 以上仅是一个大致的规划,每个学校和专业都可能略有不同,因此建议您在选择课程时咨询您的导师或相关专业教授。另外,您还可以自主学习一些与计算机相关的课程,例如Web开发、移动应用开发等,以丰富您的技能和经验。 ### 回答2: 计算机类大学四年路径规划是一个重要的决策过程,考虑到计算机领域的不断更新和发展,学生需要在四年时间内获得广泛的计算机知识和技能。 第一年,学生应该重点学习计算机科学的基础知识。这包括编程语言、数据结构和算法等方面的基本概念。同时,学生可以参加一些相关的实习或项目,加强对计算机科学的实践理解。 第二年,学生可以选择深入学习特定领域的课程。这可以是人工智能、网络安全、数据分析、软件工程等等。学生应该根据自己的兴趣和未来发展方向选择相应的课程。此外,学生也可以参加一些学术研究项目,提升自己的科研能力。 第三年,学生可以继续深化对特定领域的学习,并开始思考自己的职业规划。这可以包括参加实习,与企业合作进行项目开发,或者通过参加竞赛等方式展示自己的专业能力。此外,学生也应该关注最新的技术和趋势,保持对计算机领域的更新。 第四年,学生可以选择专注于自己感兴趣的领域进行研究和深造。这可以是硕士课程、独立研究项目或者参与创业项目。此外,学生还需要加强实践能力,积累项目经验,拓宽自己的职业网络。 路径规划还需要考虑学生的个人兴趣和能力。在四年的学习过程中,学生可以根据自己的情况适时调整学习计划,选择适合自己发展的方向。重要的是,学生需要保持学习的热情和持续的自我学习能力,以应对不断变化的计算机行业。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肖吉楠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值