2016-02-13 110 views
3

我想写一个AI迷宫解算器程序。为此,我将在GIMP中绘制2色迷宫,其中红色是墙壁,蓝色是背景或地板。然后,我将从GIMP以PNG格式输出,并使用ImageIO.read()来获得迷宫的一个对象BufferedImage。最后,我会将Rectangle点击框分配到墙上并将它们存储在ArrayList中,因此我可以使用.intersect()来检查与墙壁的精灵接触。我可以从这里使用它。如何检测图像中的彩色矩形?

但是,我想为我的程序做一件事情,但我不知道该怎么做:一旦我将图像保存为BufferedImage,如何检测红色部分(全部完全相同的RGB红色阴影)并创建匹配Rectangle s?

注:

  • 迷宫将始终是固定的尺寸(1000×1000像素)的。
  • 每个迷宫都有固定的起点
  • 红色区域将始终形成直线矩形。我创建的Rectangle对象仅用作点击框,因此我可以使用.intersect(),从未绘制或任何类似的东西。
  • Rectangle创建的数据将被存储在ArrayList中。

例迷宫:(简单的) enter image description here

我希望能够做的:(绿地作为java.awt.Rectangles创建并存储到ArrayList在哪里)

enter image description here

+0

jpg是这个问题的错误编码! jpg的目的是用于照相机拍摄的照片,因为它会导致两种颜色混合在一起的很多丑陋的噪音!请考虑使用PNG为您的问题! –

+0

@神秘哦确定会做。谢谢!我不知道我对摄影和东西没什么兴趣。修正了问题主体也。 –

+0

当然。看看这个关于维基百科的部分,看看当你使用jpg时发生了什么,你不应该使用它:https://en.wikipedia.org/wiki/Wikipedia:Preparing_images_for_upload#Do_not_save_diagrams_as_JPEG这将成为一个严重的问题, ) –

回答

2

我会提供一个相当天真的方式来解决问题(不完全实现特德,只是让你明白) 有一个所有矩形的列表List<Rectangle> mazeRectangles。所有矩形将被存储在这里..当然,图像BufferedImage image; 现在我们将遍历所有图片,直到找到一个具有正确颜色的图片 每当我们找到一个矩形时,我们将跳过矩形宽度的所有x值..

//iterate over every pixel.. 
for (int y = 0; y < image.getHeight(); y++) { 
    for (int x = 0; x < image.getWidth(); x++) { 
     //check if current pixel has maze colour 
     if(isMazeColour(image.getRGB(x, y))){ 
      Rectangle rect = findRectangle(x, y); 
      x+=rect.width; 
     } 
    } 
} 

您的检查色法:

public boolean isMazeColour(int colour){ 
    // here you should actually check for a range of colours, since you can 
    // never expect to get a nicely encoded image.. 
    return colour == Color.RED.getRGB(); 
} 

有趣的部分是findRectangle方法.. 我们看看是否已经有一个Rectangle包含我们的坐标。如果是,返回它,否则创建一个新的Rectangle,将其添加到列表并返回它。 如果我们必须创建一个新的Rectangle,我们将首先检查它的宽度。关于这个恼人的部分是,你仍然必须检查每个像素为矩形的休息,因为你可能有一个这样的配置:

+++++++ 
+++++++ 
### 
### 

其中#+是单独的盒子。因此,我们首先找到宽度:

public Rectangle findRectangle(int x, int y){ 
    // this could be optimized. You could keep a separate collection where 
    // you remove rectangles from, once your cursor is below that rectangle 
    for(Rectangle rectangle : mazeRectangles){ 
     if(!rectangle.contains(x, y)){ 
      return rectangle; 
     } 
    } 
    //find the width of the `Rectangle` 
    int xD = 0; 
    while(x+xD < width && isMazeColour(image.getRGB(x+xD+1, y))){ 
     xD++; 
    } 

    int yD = 0; //todo: find height of rect.. 

    Rectangle toReturn = new Rectangle(x, y, xD, yD); 
    mazeRectangles.add(toReturn); 
    return toReturn; 
} 

我没有落实yD的一部分,因为它是一个有点乱,我有点懒,但你需要遍历y和检查每一行(所以两个嵌套循环)

请注意,此算法可能导致重叠Rectangle s。如果您不想要,那么在找到xD时,检查每个像素是否已包含在Rectangle中。只要您不在另一个Rectangle内,就只需展开xD即可。

另一件事:由于红色和蓝色之间的颜色插值,最终可能会在矩形边界出现奇怪的人为现象。也许你想检查矩形是小(像只有1像素宽),并摆脱它们。

+0

谢谢神经元!如果你不介意,我会稍等一会儿,看看是否有其他人有不同的解决方案,所以我可以看到我的选择。然后我会接受一个答案。 –

+0

当然。我可以想象有一个图书馆为你解决问题。但是,如果你无论如何欣赏答案,你仍然可以upvote它;) –

+0

Woops耶我打算这样做。抱歉。现在照顾。你提出的解决方案@Benjamin Lowry的实现实际上比我计划的要好得多。逐行扫描会使作业完成得更快。我是按y = x逐像素的。或者右键 - >下键。 –

1

去年,有人问一个更一般的案件解决迷宫。他们还有一个额外的复杂因素,那就是有多条路径,但通过一条路口的“正确”路径是直的。

Python: solve "n-to-n" maze

提供的解决方案解决了由光线投射迷宫。从路径的开始处开始,它会沿着路径向各个方向投射线条。然后它对列表进行排序并选择最长的行,并使用它来计算下一个起点。现在,它沿所有方向重复投影线,除了朝着它的方向 - 回溯可能比向前发展更长。那只会在迷宫最长的一段时间内解决问题。

如果您确定您的角度始终为90度,则可以相应地修改代码。

+0

Intresting,我将不得不稍后再看看。我没有考虑像这样映射路径。我有另外一个涉及“雷达”结构的想法,但这个结论与我在机体和雷达中描述的结构不同。 –