A*算法走迷宫

不多说了先上代码

hpp

#include <stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<opencv2/highgui.hpp>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
//池化,用于图像降维
Mat pool_max(Mat image_source, int size);
Mat pool_min(Mat image_source, int size);
int f(int x1,int x2,int z1,int z2);

class A
{
    private:
    int rate=6;
    int map[300][300];
    Mat m;
    //open,close表的栈顶
    int tag_open=0,tag_close=0;
    //用来存每一点的父节点
    int map_root[300][300][2];
    //入口
    int x1;
    int x2;
    //出口
    int z1;
    int z2;
    //路径
    int way[1000][2];
    //表的第三个参数是代价
    //倒放,从大到小,tag_close是最小close[x][2]的x,3,4,父节点坐标
    int close[24400][3];
    //倒放,从大到小,tag_open是最小open[x][2]的x
    int open[24400][4];
    public:
    //用于存放读入原图
    Mat image_source;
    //图片降维
    void deal_image();
    //找到出入口
    void find_ori();
    //a*算法核心
    void deal_A();
    //输出路径
    void draw_road();

};
void A::draw_road()
{
    Mat rgb;
    rgb=imread("3.png",1);
    VideoWriter witer = VideoWriter("m3.avi",CV_FOURCC('M','P','4','2'),40,Size(image_source.cols,image_source.cols),1);//保存视频
    int mm=0;
    //每次循环画一个点
    while(1)
    {
        mm++;
        //为了画大点,所以下面写了九个像素
        for(int tag_a=4;tag_a<7;tag_a++)
        for(int tag_b=4;tag_b<7;tag_b++)
        for(int tag_c=0;tag_c<2;tag_c++)
        rgb.at<Vec3b>((map_root[z1][z2][0]*rate+tag_a),(map_root[z1][z2][1]*rate+tag_b))[tag_c%3]=0;
        imshow("a",rgb);
        waitKey(1);
    z1=map_root[z1][z2][0];
    z2=map_root[z1][z2][1];
    //输出位置坐标
    witer<<rgb;
    printf("%d %d \n",z1,z2);
    //如果点数超过1000或者到达终点结束画路径
    if(((z1==x1)&&(z2==x2))||mm>1000)break;
    }
    //最后一帧停止,按键继续
    imshow("a",rgb);

    witer.release();
}
void A::find_ori()
{
    Mat image_b;
        GaussianBlur(image_source,image_b,Size(3,3),5);
    //图片二值化
    for(int tag_a=0;tag_a<image_b.rows;tag_a++)
    {
    for(int tag_b=0;tag_b<image_b.cols;tag_b++)
    if(image_b.at<uchar>(tag_a,tag_b)>100)image_b.at<uchar>(tag_a,tag_b)=255;
    else image_b.at<uchar>(tag_a,tag_b)=0;
    }
    //最左侧和最右侧的白像素为出入口
    for(int tag_b=0;tag_b<image_b.cols;tag_b++)
    if(image_b.at<uchar>(tag_b,0)==255)
    {
        x1=tag_b/rate-1;
        x2=0;
    }

    for(int tag_b=0;tag_b<image_b.cols;tag_b++)
    if(image_b.at<uchar>(tag_b,image_b.rows-1)==255)
    {
        z1=tag_b/rate-1;
        z2=(image_b.rows)/rate-1;
    }

}
void A::deal_image()
{   //读图
    image_source = imread("3.png",0);
    //初始化图片b
    Mat b;
    //图片高斯降噪
    GaussianBlur(image_source,b,Size(3,3),5);
    //图片二值化
    for(int tag_a=0;tag_a<b.rows;tag_a++)
    {
    for(int tag_b=0;tag_b<b.cols;tag_b++)
    if(b.at<uchar>(tag_a,tag_b)>100)b.at<uchar>(tag_a,tag_b)=255;
    else b.at<uchar>(tag_a,tag_b)=0;
    }
    //图片池化3*3(缩小三倍)(处理两次,九倍)
    //m=pool_min(pool_max(b,3),3);
    m=pool_min(b,6);
    //再次二值化
    for(int tag_a=0;tag_a<m.rows;tag_a++)
    {
    for(int tag_b=0;tag_b<m.cols;tag_b++)
    if(m.at<uchar>(tag_a,tag_b)>100)m.at<uchar>(tag_a,tag_b)=255;
    else m.at<uchar>(tag_a,tag_b)=0;
    }
    //展示图片
    imshow("c",m);
    //将图片信息载入数组map
    for(int tag_a=0;tag_a<m.rows;tag_a++)
    for(int tag_b=0;tag_b<m.cols;tag_b++)
    map[tag_a][tag_b]=m.at<uchar>(tag_a,tag_b);
}
void A::deal_A()
{
    int keyy1=0,keyy2=0,keyy3=0,keyy4=0;
    map_root[z1][z2][0]=5;
    //入口放入close表
    close[0][0]=x1;
    close[0][1]=x2;
    tag_close++;
    //com用来对比找出open表代价最小的
    int com[2]={10000,0};
while(1)
{
//上下左右寻找合法,而且是白色的像素
if(map[close[tag_close-1][0]][close[tag_close-1][1]+1]==255&&close[tag_close-1][0]>=0&&(close[tag_close-1][1]+1)>=0)
{   //close栈顶充当新点(open表内)的父节点

        for(int tag_a=0;tag_a<tag_open;tag_a++)
    {
        //如果open表里已经有这个点了
        if((close[tag_close-1][0])==open[tag_a][0]&&(close[tag_close-1][1]+1)==open[tag_a][1])
    {   //更新代价
        //open[tag_a][2]=close[tag_close-1][2]+1;
        keyy1=1;
        break;
    }
        if(keyy1==0)
    {
        map_root[close[tag_close-1][0]][close[tag_close-1][1]+1][0]=close[tag_close-1][0];
        map_root[close[tag_close-1][0]][close[tag_close-1][1]+1][1]=close[tag_close-1][1];
    }
    keyy1=0;
    
    }
    //com记录了open表最小的序号,而且这个已经进入close了,所以这里可以放个新的open点
    if(open[com[1]][3]==100000)
    {
        open[com[1]][0]=close[tag_close-1][0];
        open[com[1]][1]=close[tag_close-1][1]+1;
        open[com[1]][2]=close[tag_close-1][2]+1;
        open[com[1]][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);

    }
    else
    {
    //只能放在open顶了
        open[tag_open][0]=close[tag_close-1][0];
        open[tag_open][1]=close[tag_close-1][1]+1;
        open[tag_open][2]=close[tag_close-1][2]+1;
        open[tag_open][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);
        tag_open++;
    }
    

}
if(map[close[tag_close-1][0]][close[tag_close-1][1]-1]==255&&close[tag_close-1][0]>=0&&(close[tag_close-1][1]-1)>=0)
{

        for(int tag_a=0;tag_a<tag_open;tag_a++)
    {
        if((close[tag_close-1][0])==open[tag_a][0]&&(close[tag_close-1][1]-1)==open[tag_a][1])
    {
        //open[tag_a][2]=close[tag_close-1][2]+1;
        keyy2=1;
        break;
    }
        if(keyy2==0)
    {
        map_root[close[tag_close-1][0]][close[tag_close-1][1]-1][0]=close[tag_close-1][0];
        map_root[close[tag_close-1][0]][close[tag_close-1][1]-1][1]=close[tag_close-1][1];
    }
    keyy2=0;
    
    }
        if(open[com[1]][3]==100000)
    {
        open[com[1]][0]=close[tag_close-1][0];
        open[com[1]][1]=close[tag_close-1][1]-1;
        open[com[1]][2]=close[tag_close-1][2]+1;
        open[com[1]][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);

    }
    else
    {
        open[tag_open][0]=close[tag_close-1][0];
        open[tag_open][1]=close[tag_close-1][1]-1;
        open[tag_open][2]=close[tag_close-1][2]+1;
        open[tag_open][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);
        tag_open++;
        

    }
    

}
if(map[close[tag_close-1][0]+1][close[tag_close-1][1]]==255&&(close[tag_close-1][0]+1)>=0&&(close[tag_close-1][1])>=0)
{

    for(int tag_a=0;tag_a<tag_open;tag_a++)
    {
        if((close[tag_close-1][0]+1)==open[tag_a][0]&&(close[tag_close-1][1])==open[tag_a][1])
    {
        //open[tag_a][2]=close[tag_close-1][2]+1;
        keyy3=1;
        break;
    }
        if(keyy3==0)
        {
        map_root[close[tag_close-1][0]+1][close[tag_close-1][1]][0]=close[tag_close-1][0];
        map_root[close[tag_close-1][0]+1][close[tag_close-1][1]][1]=close[tag_close-1][1];
        }
    keyy3=0;
    
    }
            if(open[com[1]][3]==100000)
    {
        open[com[1]][0]=close[tag_close-1][0]+1;
        open[com[1]][1]=close[tag_close-1][1];
        open[com[1]][2]=close[tag_close-1][2]+1;
        open[com[1]][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);

    }
    else
    {
            open[tag_open][0]=close[tag_close-1][0]+1;
            open[tag_open][1]=close[tag_close-1][1];
            open[tag_open][2]=close[tag_close-1][2]+1;
            open[tag_open][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);
            tag_open++;
        

    }
    

}
if(map[close[tag_close-1][0]-1][close[tag_close-1][1]]==255&&(close[tag_close-1][0]-1)>=0&&(close[tag_close-1][1])>=0)
{

    
    for(int tag_a=0;tag_a<tag_open;tag_a++)
    {
        if((close[tag_close-1][0]-1)==open[tag_a][0]&&(close[tag_close-1][1])==open[tag_a][1])
    {
        //open[tag_a][2]=close[tag_close-1][2]+1;
        keyy4=1;
        break;
    }
        if(keyy4==0)
        {
        map_root[close[tag_close-1][0]-1][close[tag_close-1][1]][0]=close[tag_close-1][0];
        map_root[close[tag_close-1][0]-1][close[tag_close-1][1]][1]=close[tag_close-1][1];
        }
    keyy4=0;
    }

            if(open[com[1]][3]==100000)
    {
        open[com[1]][0]=close[tag_close-1][0]-1;
        open[com[1]][1]=close[tag_close-1][1];
        open[com[1]][2]=close[tag_close-1][2]+1;
        open[com[1]][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);

    }
    else
    {
    open[tag_open][0]=close[tag_close-1][0]-1;
    open[tag_open][1]=close[tag_close-1][1];
    open[tag_open][2]=close[tag_close-1][2]+1;
    open[tag_open][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);
    tag_open++;

    }

}
com[0]=10000;
com[1]=0;
//找出代价最小的open点
for(int tag_a=0;tag_a<tag_open;tag_a++)
{
if((open[tag_a][2]+open[tag_a][3])<com[0])
{
    com[1]=tag_a;
    com[0]=open[tag_a][2]+open[tag_a][3];
}

}
//放到close表
close[tag_close][0]=open[com[1]][0];
close[tag_close][1]=open[com[1]][1];
//map_root[close[tag_close][0]][close[tag_close][1]][0]=close[tag_close-1][0];
//map_root[close[tag_close][0]][close[tag_close][1]][1]=close[tag_close-1][1];
//close走过的点涂黑
map[close[tag_close-1][0]][close[tag_close-1][1]]=0;
//重置比较位
open[com[1]][3]=100000;
tag_close++;
    //printf("\n %d %d\n",close[tag_close-1][0],close[tag_close-1][1]);
//waitKey(5);
if(map[z1][z2]==0)break;
}


}


int f(int x1,int x2,int z1,int z2)
{

return abs(x1-z1)+abs(x2-z2);
}
Mat pool_max(Mat image_source, int size)
{
    int rows = image_source.rows;
    int cols = image_source.cols;
    int tag_x=0,tag_y=0,tag1=0,tag2=0;
    int tag3[3]={0,0,0};
    Mat image_new(image_source.rows/size,image_source.cols/size,CV_8UC1);
    while(tag_x>=0&&tag_x<=rows-size)//欠调
    {
        while(tag_y>=0&&tag_y<=cols-size)
        {
            while(tag1>=0&&tag1<=size)
            {
                while(tag2>=0&&tag2<=size)
                {
                    if(image_source.at<uchar>(tag_x+tag1,tag_y+tag2)>tag3[1])(tag3[1]=image_source.at<uchar>(tag_x+tag1,tag_y+tag2));
                    tag2++;
                }
                tag1++;
                tag2=0; 
            }
            image_new.at<uchar>(tag_x/size,tag_y/size)=tag3[1];
            tag3[1]=0;
            tag_y+=size;tag1=0;tag2=0;
        }
        tag_x+=size;
        tag_y=0;tag1=0;tag2=0;
    }
    return image_new;

}
Mat pool_min(Mat image_source, int size)
{
    int rows = image_source.rows;
    int cols = image_source.cols;
    int tag_x=0,tag_y=0,tag1=0,tag2=0;
    int tag3[3]={0,0,0};
    Mat image_new(image_source.rows/size,image_source.cols/size,CV_8UC1);
    while(tag_x>=0&&tag_x<=rows-size)//欠调
    {
        while(tag_y>=0&&tag_y<=cols-size-1)
        {
            while(tag1>=0&&tag1<=size)
            {
                while(tag2>=0&&tag2<=size)
                {
                    if(image_source.at<uchar>(tag_x+tag1,tag_y+tag2)<tag3[1])(tag3[1]=image_source.at<uchar>(tag_x+tag1,tag_y+tag2));
                    tag2++;
                }
                tag1++;
                tag2=0; 
            }
            image_new.at<uchar>(tag_x/size,tag_y/size)=tag3[1];
            tag3[1]=255;
            tag_y+=size;tag1=0;tag2=0;
        }
        tag_x+=size;
        tag_y=0;tag1=0;tag2=0;
    }
    return image_new;

}

cpp

#include"map.hpp"


int main()
{
    A a;
    a.deal_image();
    a.find_ori();
    a.deal_A();
    a.draw_road();


}

备注

本文旨在展示A*效果,所以在鲁棒性方面没有做太多研究,图片数据来源http://mazegenerator.net/
参数如下
在这里插入图片描述
效果:
在这里插入图片描述
代码中可以自动保存视频,这里放了一张最后的截图
这边opencv出现越界情况不报错,其他设备运行可能会碰到越界之类的问题,欢迎评论指正

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值