2017-01-29 7 views
0

最後の行はイメージの平均ピクセルのHSV値を取得するにはどうすればよいですか?

/ruby-vips-1.0.3/lib/vips/argument.rb:154:in `set_property': invalid argument Array (expect #<Class:0x007fbd7c923600>) (ArgumentError)` 

PSスロー

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] 

このコードで:一時はChunkyPNGの実装を取って、リファクタリング:

def to_hsv r, g, b 
    r, g, b = [r, g, b].map{ |component| component.fdiv 255 } 
    min, max = [r, g, b].minmax 
    chroma = max - min 
    [ 
    60.0 * (chroma.zero? ? 0 : case max 
     when r ; (g - b)/chroma 
     when g ; (b - r)/chroma + 2 
     when b ; (r - g)/chroma + 4 
     else 0 
    end % 6), 
    chroma/max, 
    max, 
    ] 
end 

答えて

1

画素平均は本当にAにする必要があります線形色空間。 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は一般にはるかに優れています。平均的な色相として算術平均を計算することが明らかに間違っていることを、私は実現

im = im.colourspace "lch" 
l, c, h = im.getpoint 0, 0 
+0

Cool。あなたはおそらくそれを 'im.bandsplit.map(&:avg)'と書くことができます。 – Nakilon

+0

これと私との結果を今日または明日比較します。 – Nakilon

+0

ああ、 'map(&:avg)'の良い点。まったく同じ結果をもたらす可能性は低いです。 – user894763

0

ので、私は長さのベクトルを追加することによってそれを解決:

https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC

はLCHについては、わずかに端を変更します彩度と等しい。 10000にダウンサイズ変更時のみ〜2%の誤差まで負わせているようだ、私は.resizeを使用し、大きな画像の場合

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 

:しかし、私はchunky_pngの松葉杖を使用して要人のピクセルを反復する方法を見つけることができませんでした正方形のピクセル領域とデフォルトのカーネル。

+0

@ user894763、これを見てください。 – Nakilon

+0

アルファチャンネルの画像ではテストされませんでした。 – Nakilon

+0

0/360境界の両側の値に対して、平均的な色合いは機能しません。画像が自然な場面であれば、光子(または光子数に比例するもの)を平均化する必要があります。つまりXYZで、最後にHSVに変換します。私は私の答えを更新します。 – user894763

関連する問題