如何检测图像中的彩色矩形?

How to detect a colored rectangles in an image?

我正在尝试编写一个 AI 迷宫求解器程序。为此,我将在 GIMP 中绘制 2 色迷宫,红色为墙壁,蓝色为背景或地板。然后我将从 GIMP 导出为 png 并使用 ImageIO.read() 获得迷宫的 BufferedImage 对象。最后,我会将 Rectangle 个碰撞框分配给墙壁并将它们存储在 ArrayList 中,这样我就可以使用 .intersect() 检查精灵与墙壁的接触。我可以在这里使用它。

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

备注:

迷宫示例:(一个简单的)

我希望能够做的事情:(绿色区域是 java.awt.Rectangles 创建并存储到 ArrayList 的地方)

我会提供一个非常简单的方法来解决这个问题(没有完全实现,只是让你明白).. 有一个包含所有矩形的列表 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 包含我们的坐标。如果是return它,否则创建一个新的Rectangle,将它添加到列表并return它。 如果我们必须创建一个新的 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 重叠。如果您不想这样,在查找 xD 时检查每个像素是否已包含在 Rectangle 中。只要您不在另一个 Rectangle.

中,就只展开 xD

另一件事:由于红色和蓝色之间的颜色插值,您最终可能会在矩形的边界处出现奇怪的人工制品。也许您想检查 Rectangles 是否太小(例如只有 1 像素宽)并删除它们..

去年,有人询问了解决迷宫的更一般情况。他们有一个额外的复杂性,因为有多条路径,但 "correct" 通过十字路口的路径是直的。

Python: solve "n-to-n" maze

提供的解决方案通过光线投射解决了迷宫问题。从路径的起点开始,它会向各个方向投射线条。然后它对列表进行排序并选择最长的线并使用它来计算下一个起点。现在,它在它来的方向 除了 之外的所有方向重复投射线 - 回溯可能比前进的进度更长。那只会在迷宫最长的一条腿上反弹解决方案。

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