在图像中计算“红色/蓝色/绿色…”颜色的数量

4
我正在处理一个能够计算图像中蓝/红/黄/...像素数量的项目。 目前我已经用以下代码进行了测试:
public class Main {

    /*
   Black: 0,0,0
   White: 255, 255, 255
   Red: 255, 0, 0
   Orange: 255, 127, 0
   Yellow: 255, 255, 0
   Green: 0, 255, 0
   Blue: 0, 0, 255
   Indigo: 111, 0, 255
   Violet: 143, 0, 255
    */

    static int blackCount = 0;
    static int whiteCount = 0;
    static int redCount = 0;
    static int orangeCount = 0;
    static int yellowCount = 0;
    static int greenCount = 0;
    static int blueCount = 0;
    static int indigoCount = 0;
    static int violetCount = 0;
    static int otherCount = 0;

    static int totalCount = 0;

    public static void main(String[] args) {
        try {

            String path = "src/colors.jpg";
            BufferedImage image = ImageIO.read(new File(path));
            int w = image.getWidth();
            int h = image.getHeight();
            for (int y = 0; y < h; y++) {
                for (int x = 0; x < w; x++) {
                    Color c = new Color(image.getRGB(x, y));
                    int red = c.getRed();
                    int green = c.getGreen();
                    int blue = c.getBlue();
                    countColor(red, green, blue);
                    totalCount++;
                }
            }

            printColors();

        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }

    private static void countColor(int red, int green, int blue) {
        if (red == 0 && green == 0 && blue == 0) blackCount++;
        else if (red == 255 && green == 255 && blue == 255) whiteCount++;
        else if (red == 255 && green == 0 && blue == 0) redCount++;
        else if (red == 255 && green == 127 && blue == 0) orangeCount++;
        else if (red == 255 && green == 255 && blue == 0) yellowCount++;
        else if (red == 0 && green == 255 && blue == 0) greenCount++;
        else if (red == 0 && green == 0 && blue == 255) blueCount++;
        else if (red == 111 && green == 0 && blue == 255) indigoCount++;
        else if (red == 143 && green == 0 && blue == 255) violetCount++;
        else otherCount++;
    }

    private static void printColors() {
        System.out.println("Black: " + blackCount);
        System.out.println("White: " + whiteCount);
        System.out.println("Red: " + redCount);
        System.out.println("Orange: " + orangeCount);
        System.out.println("Yellow: " + yellowCount);
        System.out.println("Green: " + greenCount);
        System.out.println("Blue: " + blueCount);
        System.out.println("Indigo: " + indigoCount);
        System.out.println("Violet: " + violetCount);
        System.out.println("Other: " + otherCount);
        System.out.println("Total: " + totalCount);
    }

但你可能会注意到一个问题... 在RGB中,“红色”被定义为(255,0,0)。因此,包含大量红色的图像可能会返回“0”,因为图像中使用的颜色是(254,0,0),而不是(255,0,0)。
所以我实际上想要计算的不仅是纯红色像素,还包括所有“略带红色”的像素。我认为有一种更简单的方法来解决这个问题,而不需要编写一长串的if (red = 255),if (red = 254),...的结构?
5个回答

4
我建议您尝试确定您的颜色中哪个常数更大。如果红色量大于蓝色和绿色量,则您的颜色可能是“红色的”。蓝色和绿色也是如此。然而,您可能需要考虑一些特殊情况:
- 当颜色是“灰色”的时候,即所有三个常数都相同时,该怎么办? - 如果您考虑颜色(155、154、154)呢?红色常数最大,但颜色仍然是灰色的。也许只有当相关常数大于所有其他常数加上某个特定值时,才应该说颜色是某种颜色。 xkcd就颜色问题进行了一项非常有趣的调查。我建议您查看它以获取有关颜色工作方式的更多详细信息,并且它可能会给您一些提示,哪些值使颜色“红色的”,“绿色的”和“蓝色的”。结果非常有趣,但显示出许多有趣的情况,其中颜色检测是非平凡的。颜色可以受到不同人的不同感知,受性别,色盲和许多其他因素的影响。
此外,该调查包括了许多RGB常量所对应的颜色名称,并且还提供了一个颜色名称映射表!我真的相信颜色是一个非常有趣的主题,但它确实很复杂,因此在决定如何编写代码之前,您应该尽可能多地了解这个主题。

啊,没错,xkcd的颜色调查。这确实可能会很有用,谢谢。 - Matthias

4
你可以将正在处理的像素转换为更方便的颜色模型,即HSL或HSV。然后,定义属于特定组(红色/蓝色等)的组件值范围就变得更加简单了。

确实更容易。谢谢。 - Matthias

3
您需要定义红色、蓝色和绿色。很明显,[254,0,0]应该被视为红色。那么[254,5,5]呢?[200, 10, 10]呢?
最好的方法是检查与所选颜色的距离(例如,对于纯红色:(255-r)^2 + (0-b)^2 (0-g)^2),并将其与您认为是“有效的红色”的阈值进行比较。
然后对其他颜色执行相同的操作。
这种方式也让您非常容易地扩展到其他颜色(因为您可以只检查您的颜色与其他颜色的距离)。
编辑:在发现这个问题之后:有没有一种简单的方法来比较两种颜色彼此的接近程度,我建议转换为HSL(色调、饱和度、亮度)并根据某个阈值按顺序比较其值。查看该问题,里面有很多有用的信息。

1

我之前看到一个非常相关的问题,关于如何从RGB值获取颜色名称。当颜色可以从RGB转换为HSV时,解决方案会更容易,因为 hue 就是颜色。在这样做之后,您可以定义一些色调范围,并将它们用作颜色。

例如,0到30度(或任何其他度量)之间的色调将是红色,从30到60度将是橙色,然后是黄色....

例如,请查看{{link1:如何获取#xxxxxx颜色的色调?}}或{{link2:将彩虹颜色映射到RGB}}。

要从色调中获取颜色名称,{{link3:维基百科}}可以提供帮助...


0

与其检查红色、绿色或蓝色的特定值,不如检查范围(你需要调整语法和计算 - 我不是Java编码人员)

private static void countColor(int red, int green, int blue) {
    if (red == 0 && green == 0 && blue == 0) blackCount++;
    else if (red != 0 && green == red && blue == red) whiteCount++;
    else if (red != 0 && green == 0 && blue == 0) redCount++;
    else if (red != 0 && green == (red/2) && blue == 0) orangeCount++;
    else if (red != 0 && green == red && blue == 0) yellowCount++;
    else if (red == 0 && green != 0 && blue == 0) greenCount++;
    else if (red == 0 && green == 0 && blue != 0) blueCount++;
    else if (red == (blue/3) && green == 0 && blue != 0) indigoCount++;
    else if (red == (blue/0.66) && green == 0 && blue != 0) violetCount++;
    else otherCount++;
}

如果这样做可以实现,它将检查与红色、绿色、蓝色、白色、黑色等相匹配的颜色。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接