Как я могу найти доминирующий цвет изображения?

Можно ли определить, какой цвет является доминирующим в изображении с использованием java, imagemagick или jmagick?

Ответ 1

в java итерации по каждому пикселю и определения цвета

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;


public class ImageTester {


    public static void main(String args[]) throws Exception {
        File file = new File("C:\\Users\\Andrew\\Desktop\\myImage.gif");
        ImageInputStream is = ImageIO.createImageInputStream(file);
        Iterator iter = ImageIO.getImageReaders(is);

        if (!iter.hasNext())
        {
            System.out.println("Cannot load the specified file "+ file);
            System.exit(1);
        }
        ImageReader imageReader = (ImageReader)iter.next();
        imageReader.setInput(is);

        BufferedImage image = imageReader.read(0);

        int height = image.getHeight();
        int width = image.getWidth();

        Map m = new HashMap();
        for(int i=0; i < width ; i++)
        {
            for(int j=0; j < height ; j++)
            {
                int rgb = image.getRGB(i, j);
                int[] rgbArr = getRGBArr(rgb);                
                // Filter out grays....                
                if (!isGray(rgbArr)) {                
                        Integer counter = (Integer) m.get(rgb);   
                        if (counter == null)
                            counter = 0;
                        counter++;                                
                        m.put(rgb, counter);                
                }                
            }
        }        
        String colourHex = getMostCommonColour(m);
        System.out.println(colourHex);
    }


    public static String getMostCommonColour(Map map) {
        List list = new LinkedList(map.entrySet());
        Collections.sort(list, new Comparator() {
              public int compare(Object o1, Object o2) {
                return ((Comparable) ((Map.Entry) (o1)).getValue())
                  .compareTo(((Map.Entry) (o2)).getValue());
              }
        });    
        Map.Entry me = (Map.Entry )list.get(list.size()-1);
        int[] rgb= getRGBArr((Integer)me.getKey());
        return Integer.toHexString(rgb[0])+" "+Integer.toHexString(rgb[1])+" "+Integer.toHexString(rgb[2]);        
    }    

    public static int[] getRGBArr(int pixel) {
        int alpha = (pixel >> 24) & 0xff;
        int red = (pixel >> 16) & 0xff;
        int green = (pixel >> 8) & 0xff;
        int blue = (pixel) & 0xff;
        return new int[]{red,green,blue};

  }
    public static boolean isGray(int[] rgbArr) {
        int rgDiff = rgbArr[0] - rgbArr[1];
        int rbDiff = rgbArr[0] - rgbArr[2];
        // Filter out black, white and grays...... (tolerance within 10 pixels)
        int tolerance = 10;
        if (rgDiff > tolerance || rgDiff < -tolerance) 
            if (rbDiff > tolerance || rbDiff < -tolerance) { 
                return false;
            }                 
        return true;
    }
}

Ответ 2

Я только что выпустил очень простой алгоритм, который можно транслировать в Java тривиально. Он называется color-finder и работает в JavaScript.

Предлагаемые решения в этом потоке могут быть отброшены несколькими белыми символами на изображении, тогда как мой действительно пытается найти наиболее заметный цвет, даже если все пиксели не совсем точно одного цвета.

Вот живая демонстрация.

Сообщите мне, если вы найдете это полезным.

Ответ 3

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

Этот раздел подробно обсуждается на сервере дискурса ImageMagick, например: http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=12878

См. также Быстрый способ получения доминирующего цвета изображения

Ответ 4

С помощью простой java вы можете просто перебирать каждый пиксель и подсчитывать, как часто каждый цвет содержится...

псевдокода:

Map<Color, Integer> color2counter;
for (x : width) {
   for (y : height) {
      color = image.getPixel(x, y)
      occurrences = color2counter.get(color)
      color2counter.put(color, occurrences + 1)
   }
}

Ответ 5

В противном случае мы можем выполнить эту работу с помощью библиотеки Color Thief. Более подробную информацию можно найти здесь здесь и здесь.

Кредит @svenwoltmann и @lokeshdhakar.

Ответ 6

Предполагая, что вы используете аддитивную цветовую схему, где (0,0,0) является черным и (255, 255, 255) является белым (исправьте меня, если я ошибаюсь). Кроме того, если вы просто хотите найти доминирующий цвет из RGB:

Одна из моих идей, которую любой из вас может свободно анализировать, состоит в том, чтобы иметь 3 переменные, каждая из которых хранит одно из значений RGB и добавляет каждому из них соответствующее значение каждого пикселя в изображении, а затем делится на (255 * numOfPixels), чтобы получить соотношение цвета. Затем сравните 3 отношения:.60 для красного и .5 для зеленого означает, что красный цвет является более доминирующим.

Это просто идея, и может потребоваться настройка...