【问题标题】:How can I get the average colour of an image如何获得图像的平均颜色
【发布时间】:2012-09-06 16:03:26
【问题描述】:

我希望能够拍摄图像并找出平均颜色。意思是如果图像是半黑半白,我会在两者之间得到一些东西......一些灰色阴影。它可能是最常见的单一颜色或中值。任何平均值都可以。

我如何在 android 中做到这一点。

【问题讨论】:

  • 听起来很简单……你试过什么?
  • 循环所有颜色 - 并存储平均值......还不错
  • 除非您采用 NDK 或 RenderScript 路线,后者使这项任务变得相当简单快捷,Bitmap.getPixelBitmap.getPixels 是您的朋友。
  • @bdares 我不知道从哪里开始。我需要一些图像处理库还是可以直接在android平台上做?
  • @randy :唯一的问题是使用智能平均方法,因为大图像总和(像素值)可能超过 MAX_INT

标签: java android


【解决方案1】:

您可以使用来自AndroidX 或来自v7-support libraryPalete 类。

它提供了从位图中提取颜色的其他方法,例如获取:

  • 最主要的颜色
  • 鲜艳的色彩
  • 柔和的颜色
  • 更多

【讨论】:

【解决方案2】:
【解决方案3】:

以 Dan O 的解决方案为基础,这是一种自动考虑 Alpha 通道并在 getPixelsgetPixel 之间进行优化/权衡的方法。

成本是内存,但好处是性能,在可能运行数百万次的循环中调用虚拟方法 [即8MP 图像有 3,456x2,304 = 7,962,624 像素])。我什至通过删除循环的android.graphics.Color 方法调用更进一步。

public static int getDominantColor(Bitmap bitmap) {
   if (null == bitmap) return Color.TRANSPARENT;

   int redBucket = 0;
   int greenBucket = 0;
   int blueBucket = 0;
   int alphaBucket = 0;

   boolean hasAlpha = bitmap.hasAlpha();
   int pixelCount = bitmap.getWidth() * bitmap.getHeight();
   int[] pixels = new int[pixelCount];
   bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());

   for (int y = 0, h = bitmap.getHeight(); y < h; y++)
   {
       for (int x = 0, w = bitmap.getWidth(); x < w; x++)
       {
           int color = pixels[x + y * w]; // x + y * width
           redBucket += (color >> 16) & 0xFF; // Color.red
           greenBucket += (color >> 8) & 0xFF; // Color.greed
           blueBucket += (color & 0xFF); // Color.blue
           if (hasAlpha) alphaBucket += (color >>> 24); // Color.alpha
       }
   }

   return Color.argb(
           (hasAlpha) ? (alphaBucket / pixelCount) : 255,
           redBucket / pixelCount,
           greenBucket / pixelCount,
           blueBucket / pixelCount);
}

【讨论】:

  • 有趣的是,您计算了一张 8 百万像素 图像中的像素数,顾名思义就是 800 万像素。但是感谢您的解决方案。
  • 8 兆像素不精确,7,962,624 像素是精确的。
【解决方案4】:

我认为你必须自己做。

只需创建一个包含所有颜色的 int 数组:

    Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);  
    bmp = bmp.copy(Bitmap.Config.ARGB_8888, true);    
    int intArray[] = new int[bmp.getWidth()*bmp.getHeight()];  
    bmp.getPixels(intArray, 0, bmp.getWidth(), 0, 0, bmp.getWidth(), bmp.getHeight());  

然后你可以用intArray[0]得到颜色,红色的值可以是0xFFFF0000(最后6个数字是RGB颜色值)。

编辑: 简单的解决方案:

Get you full-size image in a bitmap.

Create a scaled bitmap of 1*1px.

Get this bitmap color.

【讨论】:

  • 第二种解决方案得到最常见的颜色而不是平均值。
  • 我只是在考虑第二种缩放方法,因为其他方法工作不快!!
  • 我发现 1x1 px 的第二个解决方案给出了 100% 准确的结果。甚至比 Palette 库更准确。
【解决方案5】:
Bitmap bitmap = someFunctionReturningABitmap();
long redBucket = 0;
long greenBucket = 0;
long blueBucket = 0;
long pixelCount = 0;

for (int y = 0; y < bitmap.getHeight(); y++)
{
    for (int x = 0; x < bitmap.getWidth(); x++)
    {
        Color c = bitmap.getPixel(x, y);

        pixelCount++;
        redBucket += Color.red(c);
        greenBucket += Color.green(c);
        blueBucket += Color.blue(c);
        // does alpha matter?
    }
}

Color averageColor = Color.rgb(redBucket / pixelCount,
                                greenBucket / pixelCount,
                                blueBucket / pixelCount);

【讨论】:

  • 在循环中使用getPixel 单独获取每个像素既浪费又缓慢。您应该在 for 循环之前通过一次调用 getPixels 来获取所有像素。
  • 慢?可能是。浪费?也许,取决于位图的大小和可用内存量(我相信getPixels() 创建了位图数据的副本)。
  • Color c = bitmap.getPixel() 应该是 int c = bitmap.getPixel() 因为 getPixel() 返回一个 int,而不是 Color
  • @Stardust 是正确的。这个函数不会返回一个 Color 对象,而是一个 int。否则这工作得很好。要提高较大图像的速度,请尝试缩小位图。 CIF (352x240) 对我来说效果很好。
  • Color.rgb(redBucket / pixelCount, greenBucket / pixelCount, blueBucket / pixelCount);调用需要 api 26
【解决方案6】:

使用Bitmap.getPixels() 方法获取颜色值。然后要计算平均值,您必须确定您的意思。在灰度图像中它很简单,但是对于颜色,没有平均值这样的东西。您可以分成组件(例如 RGBA),并取每个组件的平均值。另一种方法是搜索最常用的颜色,我敢肯定还有其他几种选择。玩它:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-28
    • 2011-07-06
    • 1970-01-01
    • 2015-06-05
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    相关资源
    最近更新 更多