获得最常见的图像颜色

我想从图像中获得最常见的颜色。 我使用Java,我希望拥有最主要的颜色。 有没有任何cbir java库来做这个?

谢谢

你想要的准确度如何? 您可以使用Bozhos的方法并在整个图像上循环,但对于大图像来说这可能会很慢。 有16777216个可能的RGB值,并且在Map中为它们保留计数器效率不高。

另一种方法是使用getScaledInstance重新采样图像,将其缩小为较小的版本,例如1×1图像,然后使用getRGB获取该像素的颜色。 您可以尝试使用不同的重采样算法,例如SCALE_REPLICATE和SCALE_AREA_AVERAGING,以查看最适合您的方法。

谢谢你的回答。 这是Bozho方法的一个实际例子。 它还过滤掉白色/灰色/黑色。

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

如果您将图像视为一个大的线性像素arrays,那么您需要做的就是排序它? 如果对其进行排序,则可以计算相同值的最长部分。

根据您需要的颜色值的精确程度,您可能需要考虑收集类似颜色的“颜色桶”以避免内存问题。 这意味着将颜色空间划分为颜色的“间隔”,其中所有相似(即靠近在一起)的颜色被计为相同的颜色。 通过改变间隔大小,您可以直接操作精度和内存消耗之间的权衡。


编辑:你想要的基本上是一个直方图(去看看)。 有可能很好地建立标准解决方案来有效地计算其中之一。

你可以循环BufferedImage (两个循环 – 一个从0到宽度,一个从0到高),并获得调用getRgb(x, y) 。 然后计算每个不同的值。 您可以使用Map (key = color,value =出现次数)。

我会计算每个像素的色调,然后计算每个色调的基数(创建直方图)。 也许饱和度加权。 然后,应用低通滤波器,找到最大值。 最后从色调转换回RGB。

这假设如果你只有一个图像的红色平面,你会希望结果是“红色”,而不是一些粉红色。

Andrew Dyster代码工作正常,在android中快速响应

 import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import android.graphics.Bitmap; public class ImageTester { public interface ImageColor { void onImageColor(int r, int g, int b); } @SuppressWarnings({ "unchecked", "rawtypes" }) public static void getMostCommonColour(final Bitmap image, final ImageColor heColor) { new Thread(new Runnable() { private int rgb; @Override public void run() { int height = image.getHeight(); int width = image.getWidth(); Map m = new HashMap(); int boderWid = width / 4; int borderHeigh = height / 4; for (int i = boderWid; i < width - boderWid;) { for (int j = borderHeigh; j < height - borderHeigh;) { try { rgb = image.getPixel(i, j); } catch (Exception e) { continue; }finally{ i += 20; j += 20; } 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); } } } List list = new LinkedList(m.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()); heColor.onImageColor(rgb[0], rgb[1], rgb[2]); } }).start(); } public static int[] getRGBArr(int pixel) { 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]; int tolerance = 10; if (rgDiff > tolerance || rgDiff < -tolerance) if (rbDiff > tolerance || rbDiff < -tolerance) { return false; } return true; } } 
Interesting Posts