Pythonでpygameモジュールを使用してHSVカラー引数をRGBタイプのカラー引数に変換する方法はありますか?次のコードを試しましたが、とんでもない値が返されます。
import colorsys
test_color = colorsys.hsv_to_rgb(359, 100, 100)
print(test_color)
このコードは次のナンセンスを返します
(100, -9900.0, -9900.0)
これは明らかにRGBではありません。何が悪いのですか?
この関数は、パーセントではなく、s
(飽和)とv
(値)に小数を期待しています。 100で割ります。
>>> import colorsys
# Using percent, incorrect
>>> test_color = colorsys.hsv_to_rgb(359,100,100)
>>> test_color
(100, -9900.0, -9900.0)
# Using decimal, correct
>>> test_color = colorsys.hsv_to_rgb(1,1,1)
>>> test_color
(1, 0.0, 0.0)
正規化されていないRGBタプルが必要な場合は、colorsys
関数をラップする関数を次に示します。
def hsv2rgb(h,s,v):
return Tuple(round(i * 255) for i in colorsys.hsv_to_rgb(h,s,v))
機能例
>>> hsv2rgb(0.5,0.5,0.5)
(64, 128, 128)
パフォーマンスが好きな場合は、インポートを避けて、独自の最適化されたコードを使用することをお勧めします
以下は、バイトコードをわずかに速くするためにわずかに変更されたcolorsysの正確なコードです。
def hsv_to_rgb(h, s, v):
if s == 0.0: return (v, v, v)
i = int(h*6.) # XXX assume int() truncates!
f = (h*6.)-i; p,q,t = v*(1.-s), v*(1.-s*f), v*(1.-s*(1.-f)); i%=6
if i == 0: return (v, t, p)
if i == 1: return (q, v, p)
if i == 2: return (p, v, t)
if i == 3: return (p, q, v)
if i == 4: return (t, p, v)
if i == 5: return (v, p, q)
出力:
>>> hsv_to_rgb(359,1,1)
[1, 0.0, 0.0]
上記のようなifチェーンを使用すると、Elifを使用するよりも実際に高速になります。
Cyberの回答のようにラッパーを使用すると、インタープリターが実行するための追加の手順がいくつか必要になります。
追加すると、サイバーの例のforループは、そのように使用すると実際のパフォーマンスが大幅に低下します
もう少しパフォーマンスが必要な場合は、次のようにします。
(これが最高のパフォーマンスであるとは言いませんが、確かに優れています)
def hsv_to_rgb(h, s, v):
if s == 0.0: v*=255; return (v, v, v)
i = int(h*6.) # XXX assume int() truncates!
f = (h*6.)-i; p,q,t = int(255*(v*(1.-s))), int(255*(v*(1.-s*f))), int(255*(v*(1.-s*(1.-f)))); v*=255; i%=6
if i == 0: return (v, t, p)
if i == 1: return (q, v, p)
if i == 2: return (p, v, t)
if i == 3: return (p, q, v)
if i == 4: return (t, p, v)
if i == 5: return (v, p, q)
^これにより、255の範囲のint()出力が保証されます(入力は変わりません)。
>>> hsv_to_rgb(359./360.,1,1)
(255, 0, 0)
ヒント:可能な場合はサードパーティから離れて、可能であれば直接的なアプローチを試してください。
除外:PILやNumPyなどのコンパイル済みC拡張、またはPyOpenGLなどのctypesラッパー(DLLを使用)
色相の引数も0〜1の範囲で変化します。
import colorsys
test_color = colorsys.hsv_to_rgb(359/360.0, 1, 1)
私はベクトル化されたバージョンを用意しました、それは10倍速いCCAです
def hsv_to_rgb(h, s, v):
shape = h.shape
i = int_(h*6.)
f = h*6.-i
q = f
t = 1.-f
i = ravel(i)
f = ravel(f)
i%=6
t = ravel(t)
q = ravel(q)
clist = (1-s*vstack([zeros_like(f),ones_like(f),q,t]))*v
#0:v 1:p 2:q 3:t
order = array([[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]])
rgb = clist[order[i], arange(prod(shape))[:,None]]
return rgb.reshape(shape+(3,))
Numpy配列を使用している場合は matplotlib.colors.hsv_to_rgb
は非常に直接的です。
import numpy as np
from matplotlib.colors import hsv_to_rgb
# This will create a Nice image of varying hue and value
hsv = np.zeros((512, 512, 3))
hsv[..., 0] = np.linspace(0, 1, 512)
hsv[..., 1] = 1.
hsv[..., 2] = np.linspace(0, 1, 512)[:, np.newaxis]
rgb = hsv_to_rgb(hsv)
入力画像と出力画像は、[0、1]の範囲の値を持つことに注意してください。
Numpy ndarraysとして表される画像を処理する次のコードを見つけました。
from skimage.io import imread
import matplotlib.colors as mcolors
img = imread( 'my_image.png' )
img_hsv = mcolors.rgb_to_hsv( img )
img_hsv = img_hsv / (1.0, 1.0, 255.0)
最後の除算は、何らかの理由で最後のコンポーネントが元々0〜255の範囲であったため、0.0〜1.0の浮動表現に変換するのに役立ちました。