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

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(使用前将#替换为@)

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

  • 部署 MVC4 项目时出错:找不到文件或程序集

    过去 我只需使用 Visual Studio 2012 发布到 AWS 菜单项即可部署我的 MVC4 网站 到 AWS Elastic Beanstalk 现在 程序可以在本地编译并运行 但无法部署 从消息来看 它似乎正在寻找不在当前部署的
  • ROWNUM 的 OracleType 是什么

    我试图参数化所有现有的 sql 但以下代码给了我一个问题 command CommandText String Format SELECT FROM 0 WHERE ROWNUM lt maxRecords command CommandT
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • SSH 主机密钥指纹与模式 C# WinSCP 不匹配

    我尝试通过 WinSCP 使用 C 连接到 FTPS 服务器 但收到此错误 SSH 主机密钥指纹 与模式不匹配 经过大量研究 我相信这与密钥的长度有关 当使用 服务器和协议信息 下的界面进行连接时 我从 WinSCP 获得的密钥是xx xx
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 如何在我的应用程序中使用 Windows Key

    Like Windows Key E Opens a new Explorer Window And Windows Key R Displays the Run command 如何在应用程序的 KeyDown 事件中使用 Windows
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • AccessViolationException 未处理

    我正在尝试使用史蒂夫 桑德森的博客文章 http blog stevensanderson com 2010 01 28 editing a variable length list aspnet mvc 2 style 为了在我的 ASP
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • EPPlus Excel 更改单元格颜色

    我正在尝试将给定单元格的颜色设置为另一个单元格的颜色 该单元格已在模板中着色 但worksheet Cells row col Style Fill BackgroundColor似乎没有get财产 是否可以做到这一点 或者我是否必须在互联
  • 在 ASP.NET 中将事件冒泡为父级

    我已经说过 ASP NET 中的层次结构 page user control 1 user control 2 control 3 我想要做的是 当控件 3 它可以是任何类型的控件 我一般都想这样做 让用户用它做一些触发回发的事情时 它会向
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • C++ 成员函数中的“if (!this)”有多糟糕?

    如果我遇到旧代码if this return 在应用程序中 这种风险有多严重 它是一个危险的定时炸弹 需要立即在应用程序范围内进行搜索和销毁工作 还是更像是一种可以悄悄留在原处的代码气味 我不打算writing当然 执行此操作的代码 相反

随机推荐

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

    假设我想获取每个国家 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 实现 我找到了