簡體   English   中英

HSV 到 RGB 顏色轉換

[英]HSV to RGB Color Conversion

有沒有辦法使用 python 中的 pygame 模塊將 HSV 顏色 arguments 轉換為 RGB 類型顏色 arguments? 我嘗試了以下代碼,但它返回了荒謬的值。

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-chain 實際上比使用 elif 快

使用包裝器,就像在 Cyber​​ 的回答中一樣,解釋器需要執行一些額外的步驟。
另外,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)

^ 這保證 int() 輸出范圍為 255(輸入仍然相同)

>>> hsv_to_rgb(359./360.,1,1)
(255, 0, 0)

提示:盡可能遠離第 3 方,如果可以,請嘗試直接方法。
排除:已編譯的 C 擴展,例如 PIL 或 NumPy,或 ctypes 包裝器,例如 PyOpenGL(使用 DLL)

Hue 參數也應該在 0-1 之間變化。

import colorsys
test_color = colorsys.hsv_to_rgb(359/360.0, 1, 1)

我准備了一個矢量化版本,它的速度快了 10 倍

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] 范圍內。

由於問題被標記為 ,我想提一下PyGame允許在配色方案之間進行轉換。 pygame.Color對象可用於在 RGB 和HSL/HSV配色方案之間進行轉換。

hsva屬性:

獲取或設置顏色的 HSVA 表示。 HSVA 分量在 H = [0, 360]、S = [0, 100]、V = [0, 100]、A = [0, 100] 的范圍內。

hsva = pygame.Color((red, green, blue, alpha)).hsva
color = pygame.Color(0)
color.hsva = (hue, saturation, value, alpha)
rgba = (color.r, color.g, color.b, color.a)

hsla屬性:

獲取或設置顏色的 HSLA 表示。 HSLA 分量的范圍為 H = [0, 360]、S = [0, 100]、V = [0, 100]、A = [0, 100]。

hsla = pygame.Color((red, green, blue, alpha)).hsla
color = pygame.Color(0)
color.hsla = (hue, saturation, lightness, alpha)
rgba = (color.r, color.g, color.b, color.a)

最小的例子:

import pygame

pygame.init()

window = pygame.display.set_mode((450, 300))
clock = pygame.time.Clock()

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    window.fill((255, 255, 255))
    w, h = window.get_size()
    for i in range(6):
        color = pygame.Color(0)
        color.hsla = (i * 60, 100, 50, 100)
        pygame.draw.circle(window, color, 
            (w//6 + w//3 * (i%3), h//4 + h//2 * (i//3)), 
            round(min(window.get_width() * 0.16, window.get_height() * 0.2)))

    pygame.display.flip()

pygame.quit()
exit()

我發現以下代碼可以處理表示為 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.0 到 1.0 之間的浮動表示很有用,因為出於某種原因,最后一個分量最初的范圍在 0 到 255 之間。

OpenCV 也提供了這種可能性。 請注意,R 和 B 通道是反轉的,即 BGR。 所以使用最適合您需求的函數:

import cv2

rgbimg = cv2.cvtColor(hsvimg, cv2.COLOR_HSV2RGB)
bgrimg = cv2.cvtColor(hsvimg, cv2.COLOR_HSV2BGR)

在 opencv 中,使用它們的任何顏色轉換。 請注意,BGR 和 RGB 在 cv2 區域中翻轉。

def convertColor(hsv, conversion):
    return tuple(int(i) for i in cv2.cvtColor(np.uint8([[hsv]]), conversion).flatten())

用法:

hsvColor = (0,255,255) #bright red
bgrColor = convertColor(hsvColor, cv2.COLOR_HSV2BGR)

如果您在轉換顏色時需要更多地控制顏色格式(例如,希望 RGB 最大值為 255 而不是 1),我會推薦colorir

from colorir import HSV, sRGB
rgb = HSV(359, 100, 100, max_sva=100).rgb()
... your code

colorir 還設計為與 pygame 和其他圖形庫完全兼容,因此您不必浪費時間對預期輸入和 output 顏色分量的最大值進行這種操作......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM