简体   繁体   English

根据图像修改背景色(主题)

[英]Modification of Back Ground color(theme) According to an image

I am trying to find the color that most suits a loaded image and apply it in the background. 我试图找到最适合加载的图像的颜色,并将其应用到背景中。 To adapt to the image and make the UI feel more natural. 适应图像并使UI感觉更自然。 i have so far found 2 schemes : 到目前为止,我发现了2个方案:

1> averaging the pixels(Code Below) : 1>平均像素(以下代码):

final Color acclimatizeAverage(BufferedImage img) {
        long avgr = 0, avgb = 0, avgg = 0;
        for (int i = 0; i < img.getWidth(); i++) {
            for (int j = 0; j < img.getHeight(); j++) {
               Color c = new Color(img.getRGB(i, j));
               avgr += c.getRed(); avgb += c.getBlue(); avgg += c.getGreen();
            }
        }
        avgr = (avgr/(img.getHeight()*img.getWidth()));
        avgg = (avgg/(img.getHeight()*img.getWidth()));
        avgb = (avgb/(img.getHeight()*img.getWidth()));
        Color c = new Color((int)avgr, (int)avgg, (int)avgb);
        return c;
    }

2> Grouping the pixels into fixed bins of Colors(Code Below) : 2>将像素分组到Colors的固定容器中(以下代码):

 Map<Color, Integer> createBins() {
        Map<Color, Integer> bins = new HashMap<>();
        bins.put(Color.red, 0);
        bins.put(Color.magenta, 0);
        bins.put(Color.orange, 0);
        bins.put(Color.PINK, 0);
        bins.put(Color.yellow, 0);
        bins.put(Color.LIGHT_GRAY, 0);
        bins.put(Color.GREEN, 0);
        bins.put(Color.GRAY, 0);
        bins.put(Color.DARK_GRAY, 0);
        bins.put(Color.CYAN, 0);
        bins.put(Color.BLUE, 0);
        bins.put(Color.BLACK, 0);
        return bins;
    }

    int compare(Color a, Color b) {
        return (int)Math.sqrt((a.getRed() - b.getRed())*(a.getRed() - b.getRed()) 
                + (a.getBlue() - b.getBlue())*(a.getBlue() - b.getBlue()) 
                + (a.getGreen()- b.getGreen())*(a.getGreen()- b.getGreen()));
    }

    BufferedImage acclimatizeGrouping(BufferedImage img) {
        Map<Color, Integer> bins = createBins();
        for (int i = 0; i < img.getWidth(); i++) {
            int min = Integer.MAX_VALUE; Color minC = null;
            for (int j = 0; j < img.getHeight(); j++) {
               Color c = new Color(img.getRGB(i, j));
                for (Map.Entry<Color, Integer> entry : bins.entrySet()) {
                    Integer integer = compare(entry.getKey(), c);
                    if(integer < min) {
                        min = integer;
                        minC = entry.getKey();
                    }
                }
                bins.put(minC, bins.get(minC)+1);
            }
        }
        int max = -1, n = 1; Color c = null;
        for (Map.Entry<Color, Integer> entry : bins.entrySet()) {
            Integer integer = entry.getValue();
            if(integer > max) {
                max = integer;
                c = entry.getKey();
            }
        }
        return c;
    }

But the grouping is producing weird results.... 但是分组产生了奇怪的结果。
left side is the Color produced as a result of grouping and right side is image 左侧是分组产生的颜色,右侧是图像
Why is it producing such results ??? 为什么会产生这样的结果? 左侧是分组产生的颜色,右侧是图像

averaing is producing more correct results : 平均产生更正确的结果: 在此处输入图片说明

I think the problem is that RGB is not human euclidean space. 我认为问题在于RGB不是人类的欧式空间。 You use euclidean distance to compare colors, but it is not good for human color sense. 您可以使用欧几里得距离来比较颜色,但是这对人的色彩感觉不利。 See this link for more information. 有关更多信息,请参见此链接

EDIT: More precise, you should use this algorithm: 编辑:更精确,您应该使用此算法:

typedef struct {
   unsigned char r, g, b;
} RGB;

double ColourDistance(RGB e1, RGB e2)
{
  long rmean = ( (long)e1.r + (long)e2.r ) / 2;
  long r = (long)e1.r - (long)e2.r;
  long g = (long)e1.g - (long)e2.g;
  long b = (long)e1.b - (long)e2.b;
  return sqrt((((512+rmean)*r*r)>>8) + 4*g*g + (((767-rmean)*b*b)>>8));
}

This issue is, your compare(Color a, Color b) method is not implemented correctly and can use some basic refactoring using the Math.pow() method. 问题是,您的compare(Color a, Color b)方法未正确实现,可以使用Math.pow()方法进行一些基本的重构。

The basic formula to find similar colors programatically is 以编程方式查找相似颜色的基本公式是

((r2 - r1) 2 + (g2 - g1) 2 + (b2 - b1) 2 ) 1/2 ((r2-r1) 2 +(g2-g1) 2 +(b2-b1) 21/2

Applied to Java, that results in the modified compare(Color a, Color b) 应用于Java,导致修改后的compare(Color a, Color b)

int compare(Color a, Color b){
  return Math.sqrt(( Math.pow( b.getRed() - a.getRed() ) 
                   + ( Math.pow( b.getGreen() - a.getGreen() )
                   + ( Math.pow( b.getBlue() - a.getBlue() ));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM