2011-03-02 87 views
13

当我将它上传到我的Ruby on Rails应用程序时,我需要知道图像的平均颜色。是否有可能以十六进制或RGB的平均颜色值在将要显示该图像的视图中稍后使用此颜色?使用RMagick可以获得平均图像颜色吗?

喜欢的东西:

img = Magick::Image.read(path).first 
hexVal = img.getHexValue 
+0

正如我问你的[相关问题使用JavaScript](http://stackoverflow.com/questions/ 5162828 /如何获得平均或主要颜色从图像与JavaScript):“你想只精确的像素颜色,或在一个特定的HSV范围?(我想建议后者会更好地为您服务。)“ – Phrogz 2011-03-02 05:24:08

回答

19

我不认为你可以要求它的平均颜色直接在RMagick图像,但计算这样的事情并不难。

我认为最简单的方法是提取color histogram然后用它来计算你的平均值。你可能会想quantize像一个内核,计算直方图有很多颜色的图像并不便宜,可能毫无意义的繁忙的工作,如果你在一个平均只是感兴趣:

total = 0 
avg = { :r => 0.0, :g => 0.0, :b => 0.0 } 
img.quantize.color_histogram.each { |c, n| 
    avg[:r] += n * c.red 
    avg[:g] += n * c.green 
    avg[:b] += n * c.blue 
    total += n 
} 
[:r, :g, :b].each { |comp| avg[comp] /= total } 

那我会给你avg的平均颜色。但是,颜色会在ImageMagick的内部格式(即组件将范围从零到Magick::QuantumRange),所以你必须要规模下来,0-255:

[:r, :g, :b].each { |comp| avg[comp] = (avg[comp]/Magick::QuantumRange * 255).to_i } 

最后,必须在RGB分量avg作为0到255之间的整数,并获得十六进制格式的平均颜色应该是微不足道的。如果需要,您可以轻松地将其合并到平均步骤中。

我大概可以用迭代器更聪明,但.each是很好,清晰和清晰比聪明更重要。

您还可以尝试使用和不使用量化步骤,并使用最适合您使用的图像的效果。

+7

@zarazan:该博客的日期为2011年7月5日,我的回复发布于2011年3月2日。 – 2013-02-13 22:19:16

+1

@ muistooshort如果所有的量化函数所做的都是通过取像素颜色的平均值(假设)来减少图像的复杂度 - 如果您只是将图像量化为像下面这样的颜色,那么将不会更简单: – sfkaos 2013-04-29 03:39:01

+0

@sfkaos:我猜您评论的缺失部分是关于将图像量化为一种颜色。这可能会起作用,我猜测它会和[stef's](http://stackoverflow.com/a/5164917/479863)“缩小到一个像素”的方法一样。我不确定底层算法会对调色板做些什么,但我想运行一些测试以查看真实图像会发生什么。干净的想法。 – 2013-04-29 04:40:36

21

将图像调整为一个像素并获取其颜色?

img = Magick::Image.read(path).first 
pix = img.scale(1, 1) 
averageColor = pix.pixel_color(0,0) 
+1

(非常)快速测试表明,这比使用'color_histogram'快得多。 – joost 2014-07-23 09:35:36

+1

真的很聪明的解决方案! +1 – bodacious 2015-04-09 17:09:22

+0

我们得到一个“Magick :: Pixel”对象,但是如果我们想要十六进制格式的rgb“像css的用法(例如#f0a1b2)”,我们该怎么做?这是由下面的tingel2k回答 – Aleksandrus 2016-10-15 19:56:43

1

根据@muistooshort - 如果所有的量化功能确实是使图像更简单通过利用像素颜色平均值(假设) - 如果你只是量化的图像也不会更简单到喜欢的颜色:

img.quantize(1,Magick::RGBColorspace).color_histogram 

,只是使用所产生的颜色?

3

在我测试了此处介绍的所有可能性之后,我找到了我的解决方案(here)。

def maincolor() 
    img = Magick::Image.read(self.url).first 
    pix = img.scale(1, 1) 
    avg_color_hex = pix.to_color(pix.pixel_color(0,0)) 
    return avg_color_hex 
end 

我希望这会有所帮助。我添加了rmagick转换为十六进制颜色,因为它是一个红宝石皮塔(否则我用sprintf到十六进制转换)

+0

不幸的是,这种方法有时会返回无效的十六进制颜色。例如:“#AAC5C3F1”。 – 2014-03-24 19:26:15

+0

你确定,你的图片颜色深度合适吗? – tingel2k 2014-03-25 08:32:51

+0

嗯......我不确定。我怎么知道?或者我该如何转换图像? – 2014-03-26 19:20:32