在此代码中
*
最后一行抛出
im = Vips::Image.new_from_file "some.jpg"
r = (im * [1,0,0]).avg
g = (im * [0,1,0]).avg
b = (im * [0,0,1]).avg
p [r,g,b] # => [57.1024, 53.818933333333334, 51.9258]
p Vips::Image.sRGB2HSV [r,g,b]
P.S。:临时采取并重构了ChunkyPNG实施:
/ruby-vips-1.0.3/lib/vips/argument.rb:154:in `set_property': invalid argument Array (expect #<Class:0x007fbd7c923600>) (ArgumentError)`
答案 0 :(得分:2)
像素平均值应该在线性色彩空间中。 XYZ是一个简单的,但scRGB也可以很好地工作。获得1x1像素图像后,转换为HSV并读出该值。
#!/usr/bin/ruby
require 'vips'
im = Vips::Image.new_from_file ARGV[0]
# xyz colourspace is linear, ie. the value is each channel is proportional to
# the number of photons of that frequency
im = im.colourspace "xyz"
# 'shrink' is a fast box filter, so each output pixel is the simple average of
# the corresponding input pixels ... this will shrink the whole image to a
# single pixel
im = im.shrink im.width, im.height
# now convert the one pixel image to hsv and read out the values
im = im.colourspace "hsv"
h, s, v = im.getpoint 0, 0
puts "h = #{h}"
puts "s = #{s}"
puts "v = #{v}"
我不会自己使用HSV,LCh通常要好得多。
https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC
对于LCh,只需将结尾更改为:
im = im.colourspace "lch"
l, c, h = im.getpoint 0, 0
答案 1 :(得分:0)
我意识到,将平均Hue计算为算术平均值显然是错误的,所以我通过添加长度等于饱和度的向量来解决它。但是我没有找到如何在视频中迭代像素,所以我使用了chunky_png的拐杖:
require "vips"
require "chunky_png"
def get_average_hsv_by_filename filename
im = Vips::Image.new filename
im.write_to_file "temp.png"
y, x = 0, 0
ChunkyPNG::Canvas.from_file("temp.png").to_rgba_stream.unpack("N*").each do |rgba|
h, s, v = ChunkyPNG::Color.to_hsv(rgba)
a = h * Math::PI / 180
y += Math::sin(a) * s
x += Math::cos(a) * s
end
h = Math::atan2(y, x) / Math::PI * 180
_, s, v = im.colourspace("hsv").bandsplit.map(&:avg)
[h, s, v]
end
对于使用.resize
的大图像,当使用默认内核调整到10000平方像素区域时,似乎只会导致高达~2%的错误。