【问题标题】:Find color with tolerance in bufferedimage在缓冲图像中查找具有容差的颜色
【发布时间】:2023-12-23 11:50:01
【问题描述】:

我正在编写一个尝试在缓冲图像中查找颜色的方法。目前,该方法的工作原理是截屏,然后扫描图像以获取特定颜色。现在我想添加一些 RGB 容差,所以如果用户试图查找容差为 1 的颜色 (1, 3, 5),任何颜色 +-1 R、B 或 G 都会返回 true。

我可以通过首先生成一个有效的 RGB 值的 arrayList 来解决这个问题,然后对于每个像素,我可以遍历该数组并检查每个值。问题是对于大图像的高容差可能会变得非常慢。

有没有更有效或可能内置的方法可以做到这一点?这是我现在的方法。谢谢!

public static Point findColor(Box searchArea, int color){
    System.out.println("Test");
    BufferedImage image = generateScreenCap(searchArea);
    for (int i = 0; i < image.getWidth(); i++) {
        for (int j = 0; j < image.getHeight(); j++) {
            if((image.getRGB(i, j)*-1)==color){
                return new Point(i + searchArea.x1, j + searchArea.y1);
            }
        }
    }
    return new Point(-1, -1);
}

编辑:我使用 int RGB 值进行所有比较,因此我使用 Color.getRGB() 代替 Color[1, 1, 1],它返回一个负 int,为了最终用户简单,我将其转换为正.

【问题讨论】:

  • 为什么大图像的高容差会变慢?
  • @ForguesR 在 800x600 图像中,需要检查 480 000 个像素。在每个像素中检查一种颜色是可以的,速度很好,但想象一下在 480 000 个像素中检查 100 种不同的颜色,突然之间它慢了 100 倍。效率是这个项目的重中之重,所以如果有一种方法可以更快地做到这一点,那就太棒了
  • 您正在将您的 RGB 值作为一个“整体”与一个 int 进行比较,我猜这是您正在寻找的颜色。为什么不比较 RGB 值呢?
  • @ForguesR 是的,我想这就是我正在寻找的东西,就像一种快速查找任何颜色的方法,其中 [R, G, B] 为 [x+-tolerance, y+-公差,z+-公差]。我最好的选择是使用 for 循环来比较 Colors?

标签: java colors awt rgb awtrobot


【解决方案1】:

如果您想要自定义容差,则需要比较 RGB 值而不是“整体”颜色。这是代码,它没有经过测试,但你明白了:

public static Point findColor(Box searchArea, int r, int g, int b, int tolerance){
    System.out.println("Test");

    // Pre-calc RGB "tolerance" values out of the loop (min is 0 and max is 255)
    int minR = Math.max(r - tolerance, 0);
    int minG = Math.max(g - tolerance, 0);
    int minB = Math.max(b - tolerance, 0);
    int maxR = Math.min(r + tolerance, 255);
    int maxG = Math.min(g + tolerance, 255);
    int maxB = Math.min(b + tolerance, 255);

    BufferedImage image = generateScreenCap(searchArea);
    for (int i = 0; i < image.getWidth(); i++) {
        for (int j = 0; j < image.getHeight(); j++) {
            // get single RGB pixel
            int color = image.getRGB(i, j);

            // get individual RGB values of that pixel
            // (could use Java's Color class but this is probably a little faster)
            int red = (color >> 16) & 0x000000FF;
            int green = (color >>8 ) & 0x000000FF;
            int blue = (color) & 0x000000FF;  

            if ( (red >= minR && red <= maxR) &&
                 (green >= minG && green <= maxG) &&
                 (blue >= minB && blue <= maxB) ) 
                return new Point(i + searchArea.x1, j + searchArea.y1);
        }
    }
    return new Point(-1, -1);
}

【讨论】:

  • 它不起作用,但我明白了,我应该能够塑造和塑造方法来让它做我想做的事。谢谢你!
  • 很高兴我能帮上忙。你能告诉我什么不起作用吗?
  • 现在在搜索我的样本中不存在的颜色时,我得到 0 返回,所以即使我搜索的颜色不存在,第一次检查也通过了
  • 我现在正在对其进行故障排除,希望这是一个小问题
  • Math.min 应该是 .max 的,而 Math.max 则相反,我相信,让我检查一下