How can i find dominant color of an image?

和自甴很熟 提交于 2019-11-28 19:39:57

in java iterate on each pixel and determine color

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;
    }
}

I just released a very simple algorithm that can be translated in Java trivially. It is called color-finder and works in JavaScript.

The proposed solutions in this thread can be thrown off by a few white characters in the image, whereas mine really tries to find the most prominent color, even if all the pixels aren't really exactly of the same color.

Here is a live demo.

Let me know if you find that useful.

Martin Wilson

This is a tricky problem. For example, if you have a small area of exactly the same colour and a large area of slightly different shades of a different colour then simply looking for the colour that is used the most is unlikely to give you result you want. You would get a better result by defining a set of colours and, for each, the ranges of RGB values that you consider to 'be' that colour.

This topic is discussed at length on the ImageMagick discourse server, for example: http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=12878

See also Fast way of getting the dominant color of an image

Using plain java you can just iterate over each pixel and count how often each color is contained...

pseudo-code:

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

assuming your using additive color scheme, where (0,0,0) is black and (255, 255, 255) is white (correct me if i'm mistaken). Also, if you just want to find the dominant color out of RGB:

One idea I have, which any of you are free to scrutinize is to have 3 variables that each store one of the RGB values and add to each of them the appropriate value of every pixel in the image and then divide by (255*numOfPixels) to get a ratio of color. Then compare the 3 ratios: .60 for red and .5 for green would mean red is more dominant.

This is just an idea, and might need tweaking...

In other way, we can done this job with Color Thief library. More information can be found here and here.

Credit to @svenwoltmann and @lokeshdhakar.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!