二值图像中骨架上两点之间的最短路径

2024-05-18

我有一个二进制图像,其中包含图像的一个像素宽度骨架。您可能基本上知道,在这个二值图像中,我在骨架上有 1,在其他地方有 0。 如何找到骨架上两个非零元素之间的最短距离?路径也应该在骨架本身上。 我想使用 A-star 算法的 C++ 实现。我找到了下面的代码,我需要修改它来解决我的问题。

我将非常感谢任何帮助。谢谢。

/** {{{ http://code.activestate.com/recipes/577457/ (r4) */
// Astar.cpp
// http://en.wikipedia.org/wiki/A*
// Compiler: Dev-C++ 4.9.9.2
// FB - 201012256
#include <iostream>
#include <iomanip>
#include <queue>
#include <string>
#include <math.h>
#include <ctime>
using namespace std;

const int n=60; // horizontal size of the map
const int m=60; // vertical size size of the map
static int map[n][m];
static int closed_nodes_map[n][m]; // map of closed (tried-out) nodes
static int open_nodes_map[n][m]; // map of open (not-yet-tried) nodes
static int dir_map[n][m]; // map of directions
const int dir=8; // number of possible directions to go at any position
// if dir==4
//static int dx[dir]={1, 0, -1, 0};
//static int dy[dir]={0, 1, 0, -1};
// if dir==8
static int dx[dir]={1, 1, 0, -1, -1, -1, 0, 1};
static int dy[dir]={0, 1, 1, 1, 0, -1, -1, -1};

class node
{
// current position
int xPos;
int yPos;
// total distance already travelled to reach the node
int level;
// priority=level+remaining distance estimate
int priority;  // smaller: higher priority

public:
    node(int xp, int yp, int d, int p) 
        {xPos=xp; yPos=yp; level=d; priority=p;}

    int getxPos() const {return xPos;}
    int getyPos() const {return yPos;}
    int getLevel() const {return level;}
    int getPriority() const {return priority;}

    void updatePriority(const int & xDest, const int & yDest)
    {
         priority=level+estimate(xDest, yDest)*10; //A*
    }

    // give better priority to going strait instead of diagonally
    void nextLevel(const int & i) // i: direction
    {
         level+=(dir==8?(i%2==0?10:14):10);
    }

    // Estimation function for the remaining distance to the goal.
    const int & estimate(const int & xDest, const int & yDest) const
    {
        static int xd, yd, d;
        xd=xDest-xPos;
        yd=yDest-yPos;         

        // Euclidian Distance
        d=static_cast<int>(sqrt(xd*xd+yd*yd));

        // Manhattan distance
        //d=abs(xd)+abs(yd);

        // Chebyshev distance
        //d=max(abs(xd), abs(yd));

        return(d);
    }
};

// Determine priority (in the priority queue)
bool operator<(const node & a, const node & b)
{
 return a.getPriority() > b.getPriority();
}

// A-star algorithm.
// The route returned is a string of direction digits.
string pathFind( const int & xStart, const int & yStart, 
             const int & xFinish, const int & yFinish )
{
static priority_queue<node> pq[2]; // list of open (not-yet-tried) nodes
static int pqi; // pq index
static node* n0;
static node* m0;
static int i, j, x, y, xdx, ydy;
static char c;
pqi=0;

// reset the node maps
for(y=0;y<m;y++)
{
    for(x=0;x<n;x++)
    {
        closed_nodes_map[x][y]=0;
        open_nodes_map[x][y]=0;
    }
}

// create the start node and push into list of open nodes
n0=new node(xStart, yStart, 0, 0);
n0->updatePriority(xFinish, yFinish);
pq[pqi].push(*n0);
open_nodes_map[x][y]=n0->getPriority(); // mark it on the open nodes map

// A* search
while(!pq[pqi].empty())
{
    // get the current node w/ the highest priority
    // from the list of open nodes
    n0=new node( pq[pqi].top().getxPos(), pq[pqi].top().getyPos(), 
                 pq[pqi].top().getLevel(), pq[pqi].top().getPriority());

    x=n0->getxPos(); y=n0->getyPos();

    pq[pqi].pop(); // remove the node from the open list
    open_nodes_map[x][y]=0;
    // mark it on the closed nodes map
    closed_nodes_map[x][y]=1;

    // quit searching when the goal state is reached
    //if((*n0).estimate(xFinish, yFinish) == 0)
    if(x==xFinish && y==yFinish) 
    {
        // generate the path from finish to start
        // by following the directions
        string path="";
        while(!(x==xStart && y==yStart))
        {
            j=dir_map[x][y];
            c='0'+(j+dir/2)%dir;
            path=c+path;
            x+=dx[j];
            y+=dy[j];
        }

        // garbage collection
        delete n0;
        // empty the leftover nodes
        while(!pq[pqi].empty()) pq[pqi].pop();           
        return path;
    }

    // generate moves (child nodes) in all possible directions
    for(i=0;i<dir;i++)
    {
        xdx=x+dx[i]; ydy=y+dy[i];

        if(!(xdx<0 || xdx>n-1 || ydy<0 || ydy>m-1 || map[xdx][ydy]==1 
            || closed_nodes_map[xdx][ydy]==1))
        {
            // generate a child node
            m0=new node( xdx, ydy, n0->getLevel(), 
                         n0->getPriority());
            m0->nextLevel(i);
            m0->updatePriority(xFinish, yFinish);

            // if it is not in the open list then add into that
            if(open_nodes_map[xdx][ydy]==0)
            {
                open_nodes_map[xdx][ydy]=m0->getPriority();
                pq[pqi].push(*m0);
                // mark its parent node direction
                dir_map[xdx][ydy]=(i+dir/2)%dir;
            }
            else if(open_nodes_map[xdx][ydy]>m0->getPriority())
            {
                // update the priority info
                open_nodes_map[xdx][ydy]=m0->getPriority();
                // update the parent direction info
                dir_map[xdx][ydy]=(i+dir/2)%dir;

                // replace the node
                // by emptying one pq to the other one
                // except the node to be replaced will be ignored
                // and the new node will be pushed in instead
                while(!(pq[pqi].top().getxPos()==xdx && 
                       pq[pqi].top().getyPos()==ydy))
                {                
                    pq[1-pqi].push(pq[pqi].top());
                    pq[pqi].pop();       
                }
                pq[pqi].pop(); // remove the wanted node

                // empty the larger size pq to the smaller one
                if(pq[pqi].size()>pq[1-pqi].size()) pqi=1-pqi;
                while(!pq[pqi].empty())
                {                
                    pq[1-pqi].push(pq[pqi].top());
                    pq[pqi].pop();       
                }
                pqi=1-pqi;
                pq[pqi].push(*m0); // add the better node instead
            }
            else delete m0; // garbage collection
        }
    }
    delete n0; // garbage collection
}
return ""; // no route found
}

int main()
{
srand(time(NULL));

// create empty map
for(int y=0;y<m;y++)
{
    for(int x=0;x<n;x++) map[x][y]=0;
}

// fillout the map matrix with a '+' pattern
for(int x=n/8;x<n*7/8;x++)
{
    map[x][m/2]=1;
}
for(int y=m/8;y<m*7/8;y++)
{
    map[n/2][y]=1;
}

// randomly select start and finish locations
int xA, yA, xB, yB;
switch(rand()%8)
{
    case 0: xA=0;yA=0;xB=n-1;yB=m-1; break;
    case 1: xA=0;yA=m-1;xB=n-1;yB=0; break;
    case 2: xA=n/2-1;yA=m/2-1;xB=n/2+1;yB=m/2+1; break;
    case 3: xA=n/2-1;yA=m/2+1;xB=n/2+1;yB=m/2-1; break;
    case 4: xA=n/2-1;yA=0;xB=n/2+1;yB=m-1; break;
    case 5: xA=n/2+1;yA=m-1;xB=n/2-1;yB=0; break;
    case 6: xA=0;yA=m/2-1;xB=n-1;yB=m/2+1; break;
    case 7: xA=n-1;yA=m/2+1;xB=0;yB=m/2-1; break;
}

cout<<"Map Size (X,Y): "<<n<<","<<m<<endl;
cout<<"Start: "<<xA<<","<<yA<<endl;
cout<<"Finish: "<<xB<<","<<yB<<endl;
// get the route
clock_t start = clock();
string route=pathFind(xA, yA, xB, yB);
if(route=="") cout<<"An empty route generated!"<<endl;
clock_t end = clock();
double time_elapsed = double(end - start);
cout<<"Time to calculate the route (ms): "<<time_elapsed<<endl;
cout<<"Route:"<<endl;
cout<<route<<endl<<endl;

// follow the route on the map and display it 
if(route.length()>0)
{
    int j; char c;
    int x=xA;
    int y=yA;
    map[x][y]=2;
    for(int i=0;i<route.length();i++)
    {
        c =route.at(i);
        j=atoi(&c); 
        x=x+dx[j];
        y=y+dy[j];
        map[x][y]=3;
    }
    map[x][y]=4;

    // display the map with the route
    for(int y=0;y<m;y++)
    {
        for(int x=0;x<n;x++)
            if(map[x][y]==0)
                cout<<".";
            else if(map[x][y]==1)
                cout<<"O"; //obstacle
            else if(map[x][y]==2)
                cout<<"S"; //start
            else if(map[x][y]==3)
                cout<<"R"; //route
            else if(map[x][y]==4)
                cout<<"F"; //finish
        cout<<endl;
    }
}
getchar(); // wait for a (Enter) keypress  
return(0);
}
/** end of http://code.activestate.com/recipes/577457/ }}} */

None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二值图像中骨架上两点之间的最短路径 的相关文章

  • Poco c++Net:Http 从响应中获取标头

    我使用 POCO C Net 库进行 http 我想尝试制定持久缓存策略 首先 我认为我需要从缓存标头中获取过期时间 并与缓存值进行交叉检查 如果我错了 请告诉我 那么我如何从中提取缓存头httpResponse 我已经看到你可以用 Jav
  • 单元测试验证失败

    我正在运行我的单元测试PostMyModel路线 然而 在PostMyModel 我用的是线Validate
  • 如何在另一个应用程序中挂钩 api 调用

    我正在尝试挂钩另一个应用程序的 ExtTextOut 和 DrawTextExt GDI 方法调用 我知道我需要使用 GetProcAddress 来查找 gdi32 dll 中那些方法的地址 并用我的函数的地址覆盖我想要挂钩的进程中的地址
  • 删除是如何工作的? [复制]

    这个问题在这里已经有答案了 可能的重复 C 编程 free 如何知道要释放多少 https stackoverflow com questions 1518711 c programming how does free know how m
  • 在现代 C++ 中,临时生命周期延长何时有用?

    在 C 中 您可以将函数的返回值 返回值 而不是引用 绑定到 const 引用 并且代码仍然有效 因为该临时对象的生命周期将延长到作用域末尾 例如 std string get string return abc void f const
  • 从代码中,如何创建对存储在附加属性中的对象的属性的绑定?

    我们有一个继承的附加属性来存储一个对象 在可视化树的更下方 我们希望从代码绑定到该对象的属性 通常我们像这样构建绑定的路径部分 var someBinding new Binding Path new PropertyPath Attach
  • 在 C# 中调用 C++ 库 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有很多用 C 编写的库 我想从 C 调用这些库 但是 我遇到了很多问题 我想知道是否有书籍或指南告诉我如何做到这一点 Dll导入 htt
  • 运行需要 MySql.Data 的内置 .NET 应用程序

    我在运行我编写的内置 NET 应用程序时遇到问题 我的应用程序使用最新的 MySql 连接器 该连接器安装在我的系统上 当我尝试将其添加为引用时 该连接器显示为 NET 4 Framwork 组件 当我在环境中以调试模式运行应用程序时 一切
  • 在开关中使用“goto”?

    我看到了一个建议的编码标准 内容如下Never use goto unless in a switch statement fall through 我不跟 这个 例外 案例到底是什么样的 这证明了goto 此构造在 C 中是非法的 swi
  • 为什么'enable_if'不能用于禁用这里声明

    include
  • 在 omp 并行 for 循环中使用 unique_ptr 会导致 SEG.FAULT

    采取以下代码 include
  • 获取 boost Spirit 语法中的当前行

    我正在尝试使用 boostspirit 获取正在解析的文件的当前行 我创建了一个语法类和结构来解析我的命令 我还想跟踪在哪一行找到命令并将其解析到我的结构中 我将 istream 文件迭代器包装在 multi pass 迭代器中 然后将其包
  • 使用具有抗锯齿功能的 C# 更改抗锯齿图像的背景颜色

    我有一个图像需要更改背景颜色 例如 将下面示例图像的背景更改为蓝色 然而 图像是抗锯齿的 所以我不能简单地用不同的颜色替换背景颜色 我尝试过的一种方法是创建第二个图像 仅作为背景 并更改其颜色并将两个图像合并为一个图像 但是这不起作用 因为
  • 英文日期差异

    接近重复 如何计算相对时间 https stackoverflow com questions 11 how do i calculate relative time 如何在 C 中计算某人的年龄 https stackoverflow c
  • 选择查询不适用于使用Parameters.AddWithValue 的参数

    C 中的以下查询不起作用 但我看不出问题所在 string Getquery select from user tbl where emp id emp id and birthdate birthdate cmdR Parameters
  • 如何停止无限循环?

    我正在编写一个程序 该程序将计算三角形或正方形的面积 然后提示用户是否希望计算另一个 我的代码已经运行到可以计算任一形状的面积的程度 但随后不再继续执行代码的其余部分 例如 如果选择了正方形 则计算面积 然后返回到正方形边长的提示 我假设这
  • C++ 中 void(*)() 和 void(&)() 之间的区别[重复]

    这个问题在这里已经有答案了 在此示例代码中 func1是类型void int double and funky是类型void int double include
  • INotifyPropertyChanged 和 propertyName

    我一直不确定它的含义propertyName实施时INotifyPropertyChanged 所以一般来说你实现INotifyPropertyChanged as public class Data INotifyPropertyChan
  • 如何将 SQL“LIKE”与 LINQ to Entities 结合使用?

    我有一个文本框 允许用户指定搜索字符串 包括通配符 例如 Joh Johnson mit ack on 在使用 LINQ to Entities 之前 我有一个存储过程 该存储过程将该字符串作为参数并执行以下操作 SELECT FROM T
  • 使用未分配的局部变量

    我遇到了一个错误 尽管声明了变量 failturetext 和 userName 错误仍然出现 谁能帮帮我吗 Use of Unassigned local variable FailureText Use of Unassigned lo

随机推荐

  • 如何从维基数据属性中获取最新值?

    假设我想获取每个国家 Q6256 及其最近记录的人类发展指数 P1081 值的列表 该国家 地区的人类发展指数属性包含在不同时间点获取的数据点列表 但我只关心最新的数据 此查询不起作用 因为它会为每个国家 地区获取多个结果 每个人类发展指数
  • git 日志历史记录图,每次提交一行,彩色,带有日期

    我需要的格式如下 git log decorate graph oneline date order 但我也需要它 包含日期 短 具有相同的颜色 I tried git log decorate graph oneline date ord
  • clang 是否提供类似于 GCC 6.x 的函数多版本控制 (target_clones) 的功能?

    我读了这篇 LWN 文章 https lwn net Articles 691932 饶有兴趣 执行摘要 GCC 6 x 支持所谓的函数多版本控制 它可以构建同一函数的多个版本 并针对不同的指令集进行优化 假设您有一台支持 AVX2 的机器
  • 使用 Denon 时如何避免权限问题

    我正在运行 denon 它就像节点中的 nodemon 但即使我手动指定了相关标志 特别是 allow net flag 如何使用 Denon 运行我的应用程序 这样我就不必不断重新启动 如果不知道确切的错误 很难给你正确的答案 但是den
  • PHP - 扩展 __construct

    我想知道你是否可以帮助我 我有两个类 一个扩展了另一个 B 类将由各种不同的对象扩展 并用于常见的数据库交互 现在我希望 B 类能够处理其连接和断开连接 而无需来自 A 类或任何外部输入的指示 据我了解 问题是扩展类不会自动运行其 cons
  • 找出所有程序 dynpro 屏幕?

    我是ABAP新手 我想制作一个具有多个屏幕和一个初始主屏幕的程序 可以在其中看到所有程序屏幕的列表 我知道我可以对它们进行硬编码 但应该有更好的方法 如果有任何类型的字段 区域 我需要使该列表可点击 以转到屏幕 到目前为止 我已经制作了一个
  • 使用 Azure AD 通过 OAuth2 对 Azure API 管理进行身份验证

    我正在尝试通过 AzureAD 使用 OAuth2 来保护 APIM API 方法是阅读以下文章 通过 Azure AD 使用 OAuth 2 0 授权来保护 Azure API 管理中的 Web API 后端 https learn mi
  • 如何向 CSS 形状添加偏移轮廓?

    我在创建带有斜角边缘的块时遇到了一些问题 此外我需要一个斜角的边框并稍微偏离主块 问题是这个块可以根据屏幕响应 不知道具体的方法 希望大家帮忙 这就是我现在所做的 box display flex padding 20px height 2
  • 我该如何实现这个折叠功能呢?

    给出了两种数据类型 颜色 和 植物 data Color Red Pink White Blue Purple Green Yellow deriving Show Eq data Plant Leaf Blossom Color Stal
  • 为什么我的“While Loop”不打印查找平均“分数”的计算结果?

    我正在编写一个程序来读取用户输入的正整数序列 用户一次只能输入一个整数 然后它将计算这些整数的平均值 当用户输入0时程序结束 0不计入平均值 程序结束后程序将打印出平均值 问题 当我进入 while 循环时 我的代码停止工作 因此它不会计算
  • Package.json 表示 firebase-functions 的版本已过时

    我有云功能项目 并将该项目从旧笔记本电脑移至新笔记本电脑 我已经安装了所有必要的东西 我的问题是当我尝试时firebase deploy它给了我这个错误 函数 package json 表示 firebase functions 的过时版本
  • JSF 命名 Bean,Eager 应用程序范围(又名 @ManagedBean(eager=true) )

    有没有办法初始化带有注释的命名Beanjavax inject Named javax enterprise context ApplicationScoped like ManagedBean eager true from javax
  • 我应该在 Prolog 和一般情况下避免尾递归吗?

    我正在阅读 立即学习 Prolog 在线书籍 以获取乐趣 我正在尝试编写一个谓词 该谓词遍历列表的每个成员并向其添加一个 使用累加器 我已经在没有尾递归的情况下轻松完成了 addone addone X Xs Y Ys Y is X 1 a
  • 使用 LINQ 和 ASP.NET MVC 更新多个表

    只是简单地说一下 我只是想寻求一些澄清 我希望通过一个 创建 操作来更新多个表 在尝试之前 我只是想知道是否可以简单地执行以下操作 db hdCalls InsertOnSubmit a db hdCustomers InsertOnSub
  • 如何将窗口注入到服务中?

    我正在用 TypeScript 编写一个 Angular 2 服务 它将利用localstorage 我想注入对浏览器的引用window对象到我的服务中 因为我不想引用任何全局变量 例如 Angular 1 x window 我怎么做 这目
  • 有队列实现吗?

    任何人都可以建议使用 Go 容器来实现简单快速的 FIF 队列 Go 有 3 种不同的容器 heap list and vector 哪一种更适合实现队列 事实上 如果您想要的是一个基本且易于使用的 fifo 队列 slice 可以满足您所
  • 调用 free() 时损坏的未排序块

    glibc detected a out free corrupted unsorted chunks 0x00000000007646b0 glibc detected a out malloc memory corruption 0x0
  • iOS - 当 UIView 移动时将 UITextField 移动到不同的位置

    我有一个主 UIView 它通过开关向上移动 我有这个工作 那里没有问题 现在 UIView 当向下时 占据屏幕的大约一半 当它向上推时 它会显示底部 40px 在 UIView 中 当它处于向下状态时 它有一个 UITextField 并
  • RegularExpressionAttribute - 如何使其客户端验证不区分大小写?

    我有一个用于客户端验证的字符串 private const String regex b d 5 s s d 5 A Z 2 d 3 s s 1 d 3 s 我在我的中使用这个字符串 RegularExpression regex Erro
  • 二值图像中骨架上两点之间的最短路径

    我有一个二进制图像 其中包含图像的一个像素宽度骨架 您可能基本上知道 在这个二值图像中 我在骨架上有 1 在其他地方有 0 如何找到骨架上两个非零元素之间的最短距离 路径也应该在骨架本身上 我想使用 A star 算法的 C 实现 我找到了