当前位置: 首页 > 知识库问答 >
问题:

给定图像的迷宫的表示和求解

富锦
2023-03-14

给出一个图像,表示和解决迷宫的最佳方法是什么?

给定一个JPEG图像(如上图所示),什么是最好的方法来读取它,将它解析成某种数据结构,并解决迷宫?我的第一个本能是逐像素读取图像,并将其存储在布尔值列表(数组)中:true表示白色像素,而false表示非白色像素(颜色可以丢弃)。这种方法的问题是,图像可能不是“像素完美”的。我的意思是,如果墙上的某个地方有一个白色像素,它可能会产生一条意想不到的路径。

另一种方法(经过思考后我想到的)是将图像转换为SVG文件--这是画布上绘制的路径列表。这样,路径可以被读入相同类型的列表(布尔值)中,其中true表示路径或墙,false表示可旅行空间。如果转换不是100%准确,并且没有完全连接所有的墙,从而产生空隙,那么这种方法就会出现问题。

转换到SVG的另一个问题是线条不是“完全”直的。这导致路径为三次bezier曲线。使用由整数索引的布尔值的列表(数组),曲线将不容易传输,并且必须计算曲线上的所有点,但不会与列表索引完全匹配。

我假设这些方法中的一种可能起作用(尽管可能不起作用),但是对于如此大的图像,它们的效率非常低,并且存在一种更好的方法。如何做到最好(最有效和/或最不复杂)?有没有最好的办法?

然后是迷宫的解开。如果我使用前两种方法中的任何一种,我基本上会得到一个矩阵。根据这个答案,表示迷宫的好方法是使用树,解决迷宫的好方法是使用a*算法。如何从图像中创建一棵树?有什么想法吗?

lt;tl;dr
解析的最佳方法?转换成什么数据结构?所说的结构如何帮助/阻碍解决问题?

更新
按照@Thomas的建议,我尝试使用numpy实现@mikhail用Python编写的内容。我觉得这个算法是正确的,但它并没有像希望的那样工作。(代码如下。)PNG库是PYPNG。

import png, numpy, Queue, operator, itertools

def is_white(coord, image):
  """ Returns whether (x, y) is approx. a white pixel."""
  a = True
  for i in xrange(3):
    if not a: break
    a = image[coord[1]][coord[0] * 3 + i] > 240
  return a

def bfs(s, e, i, visited):
  """ Perform a breadth-first search. """
  frontier = Queue.Queue()
  while s != e:
    for d in [(-1, 0), (0, -1), (1, 0), (0, 1)]:
      np = tuple(map(operator.add, s, d))
      if is_white(np, i) and np not in visited:
        frontier.put(np)
    visited.append(s)
    s = frontier.get()
  return visited

def main():
  r = png.Reader(filename = "thescope-134.png")
  rows, cols, pixels, meta = r.asDirect()
  assert meta['planes'] == 3 # ensure the file is RGB
  image2d = numpy.vstack(itertools.imap(numpy.uint8, pixels))
  start, end = (402, 985), (398, 27)
  print bfs(start, end, image2d, [])

共有1个答案

弘承运
2023-03-14

这里有一个解决方案。

  1. 将图像转换为灰度(还不是二进制),调整颜色的权重,使最终的灰度图像大致均匀。您可以简单地在Photoshop中控制图像->调整->黑白
  2. 中的滑块
  3. 通过在图像->调整->阈值中的Photoshop中设置适当的阈值将图像转换为二进制。
  4. 确保阈值选择正确。使用0公差的魔棒工具,点样,连片,无抗锯齿。检查选择中断处的边缘是否为错误阈值引入的假边缘。事实上,这个迷宫的所有内部点从一开始就可以访问。
  5. 在迷宫上添加人工边界,以确保虚拟旅行者不会在迷宫周围行走:)
  6. 用您喜欢的语言实现广度优先搜索(BFS),并从一开始就运行它。我更喜欢MATLAB来完成这个任务。正如@Thomas已经提到的,没有必要在图的常规表示上搞乱。您可以直接使用二值化图像。

下面是BFS的MATLAB代码:

function path = solve_maze(img_file)
  %% Init data
  img = imread(img_file);
  img = rgb2gray(img);
  maze = img > 0;
  start = [985 398];
  finish = [26 399];

  %% Init BFS
  n = numel(maze);
  Q = zeros(n, 2);
  M = zeros([size(maze) 2]);
  front = 0;
  back = 1;

  function push(p, d)
    q = p + d;
    if maze(q(1), q(2)) && M(q(1), q(2), 1) == 0
      front = front + 1;
      Q(front, :) = q;
      M(q(1), q(2), :) = reshape(p, [1 1 2]);
    end
  end

  push(start, [0 0]);

  d = [0 1; 0 -1; 1 0; -1 0];

  %% Run BFS
  while back <= front
    p = Q(back, :);
    back = back + 1;
    for i = 1:4
      push(p, d(i, :));
    end
  end

  %% Extracting path
  path = finish;
  while true
    q = path(end, :);
    p = reshape(M(q(1), q(2), :), 1, 2);
    path(end + 1, :) = p;
    if isequal(p, start) 
      break;
    end
  end
end

它真的是非常简单和标准的,在Python中实现它应该不会有什么困难。

答案如下:

 类似资料:
  • 我得到了一些构建迷宫的代码,以及任何其他需要的东西,抽象迷宫类包含一个抽象方法“makeMove(int row,int col)”。这是我试图编写的解决迷宫的方法,向左、向右、向上、向下移动。 我刚刚开始做这件事,下面是我到目前为止的全部资料。 好的,我让代码运行到不再出现错误的地方。 感谢所有的帮助。

  • 我在一门课上学习序言。我有一个练习,我需要读取一个文件,从中生成一个迷宫,获得从源到目标的路径,然后将其写入一个文件。 我读了文件,对我拥有的每个单元格断言,对连接的每两个单元格断言。 ,,,都是整数坐标,所以我知道起点和终点。 我的工作原理是,如果当前节点连接到目标,完成并返回。否则,找到当前节点所连接的节点,并用新节点调用递归

  • 我正在尝试寻找到EndPotion的路径。这是一个递归函数。请帮助,我要自杀了。 这是给定的地图 我想递归地使用GetPath来到达上面地图中的EndPotion。参数是当前位置、结束位置和地图。对于这个例子,起始位置是(0,0)和结束,EndPotionis是(0,3),右上角。0代表墙壁,1代表路径。 我需要返回一个包含有效点的arraylist到结束位置。虽然我的数组大小始终为0,并且基本大

  • 我正在为迷宫[30][30]编写查找路径解决方案,我在路径查找函数中使用了回溯;以下是伪代码: 找到起始点然后运行该点的函数 将房间标记为已参观 终止条件1:如果,在路径上标记,然后返回true 递归部分:搜索8个邻居:西部、西北部、北部、东北部、东部、东南部、南部、西南部。检查房间是否可访问,然后调用find_path函数,如果返回true,则在find path上标记 终止条件2:返回fals

  • 主要内容:回溯算法解决迷宫问题迷宫问题指的是:在给定区域内,找到一条甚至所有从某个位置到另一个位置的移动路线。举个简单的例子,如图 1 所示,在白色区域内找到一条(甚至所有)从起点到终点的路线。 图 1 迷宫问题 迷宫问题就可以采用 回溯算法解决,即从起点开始,采用不断“回溯”的方式逐一试探所有的移动路线,最终找到可以到达终点的路线。 回溯算法解决迷宫问题 以图 1 所示的迷宫为例,回溯算法解决此问题的具体思路是: 从当前位置

  • 问题内容: 为了编写一个解决C程序的蛮力迷宫,我首先编写了这个Java程序来测试一个想法。我对C还是很陌生,打算在Java中正确处理后将其转换。结果,我试图远离arraylist,fancy库等,以便更轻松地转换为C。该程序需要生成最短步骤的单个宽度路径来解决迷宫问题。我认为我的问题可能在于将通过每个递归传递的路径存储数组碎片化。感谢您的关注。-乔 代码中解释了数字符号 问题答案: 这本来不是要作