Подсчет "красноватого / голубоватого / зеленоватого ..." цветов на изображении - PullRequest
4 голосов
/ 16 августа 2011

Я работаю над тем, что может подсчитать количество синих / красных / желтых / ... пикселей на изображении.Пока у меня есть этот код в качестве теста:

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 голосов
/ 16 августа 2011

Вы можете конвертировать обрабатываемые пиксели в более удобную цветовую модель, а именно HSL или HSV .

Тогда было бы проще определить диапазоны значений компонентов, которые относятся к определенным группам (красноватый / голубоватый / и т. Д.).

4 голосов
/ 16 августа 2011

Я хотел бы попытаться определить, какая из трех констант больше в вашем цвете.Если количество красного больше, чем количество синего и количество зеленого, вы можете предположить, что ваш цвет "красноватый".То же самое касается синего и зеленого.

Тем не менее, вы можете принять во внимание некоторые угловые случаи:

  • Что вы делаете, когда цвет "сероватый", т.е.все три константы одинаковы
  • Что должно произойти, если учитывать цвет (155, 154, 154)?Красная константа самая большая, но цвет по-прежнему серый.Может быть, вы должны сказать, что цвет является определенной цветовой гаммой тогда и только тогда, когда связанная константа больше, чем все остальные плюс определенное значение?цветов .Я рекомендую вам ознакомиться с ним для получения более подробной информации о том, как работают цвета, и он может дать вам несколько советов о том, какие значения делают цвет "красноватым", "зеленоватым" и "голубоватым".Результаты очень интересные, но показывают много интересных случаев, когда определение цвета не является тривиальным.Разные люди могут по-разному воспринимать цвета под влиянием пола, дальтонизма и множества других факторов.

    Кроме того, в опросе приводится множество названий цветов для множества констант RGB, которые вы можете использовать.И это также идет с картой названий цветов!

    Я искренне верю, что цвета - очень интересная тема, однако это действительно сложно, и вы должны получить как можно больше информации по этому вопросу, прежде чем на самом деле решить, как написать свойкод.

3 голосов
/ 16 августа 2011

Вам нужно определить красноватый, голубоватый и зеленоватый.Очевидно, [254,0,0] должно сойти за красный.Как насчет [254,5,5]?Как насчет [200, 10, 10]?

Лучше всего проверить расстояние от отмеченного цвета (например, с чистым красным: (255-r)^2 + (0-b)^2 (0-g)^2) и сравнить его с пороговым значением, которое вы считаетебыть "эффективно красным".

И затем сделать то же самое для других цветов.

Этот способ также позволит вам очень легко расширяться до дополнительных цветов (так как вы можете просто проверить расстояние от вашегоцвет против другого цвета).

Редактировать: Найдя этот вопрос: Существует ли простой способ сравнить, насколько близки два цвета друг к другу , я бы порекомендовал преобразовать в HSL (оттенок).(насыщенность, яркость) и сравнение значений по порядку на основе некоторого порога.Проверьте этот вопрос, там много полезной информации.

1 голос
/ 16 августа 2011

Некоторое время назад я видел очень связанный вопрос о получении имени цвета из значения RGB. Решение было проще, когда цвет можно преобразовать, например, из RGB в HSV, поскольку hue - это цвет. После этого вы можете определить некоторые диапазоны для оттенка и использовать их в качестве цвета.

Так, например, оттенок от 0 до 30 градусов (или любая другая мера) будет красным, от 30 до 60 будет оранжевым, а затем желтым ....

Взгляните на Как вы получаете оттенок цвета #xxxxxx? или Отображение цветов радуги в RGB , например

А чтобы получить названия цветов из оттенка, Википедия может помочь ...

0 голосов
/ 16 августа 2011

Вместо проверки конкретного значения для красного, зеленого или синего, проверьте диапазон

(вам придется настроить это для синтаксиса и вычислений - я не 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 == !=) violetCount++;
            else otherCount++;
        }

Если это работает, он проверит наличие цветов, соответствующих оттенкам красного, зеленого, синего, белого, черного и т. Д.

...