2017-08-05 29 views
2

我希望能夠生成接近一種RGB顏色的多種顏色,如下圖所示。如何生成一個rgb值的關閉顏色?

enter image description here

這裏是我所用Python做:

def similarColors(rgb, loop=6): 
    difference = 30 
    colors = [] 
    for i in range(loop): 
     red = rgb[0] 
     red_highest = red + difference 
     red_lowest = red - difference 
     red = randint(red_lowest, red_highest) 

     green = rgb[1] 
     green_highest = green + difference 
     green_lowest = green - difference 
     green = randint(green_lowest, green_highest) 

     blue = rgb[2] 
     blue_highest = blue + difference 
     blue_lowest = blue - difference 
     blue = randint(blue_lowest, blue_highest) 

     colors.append([red, green, blue]) 
    return colors 

palette = similarColors([244, 83, 28]) 

問題:我覺得我過於複雜的事情用這種方法是有沒有辦法讓上面的代碼更清潔和更短?

我想避免對每種顏色(紅色,藍色,綠色)分別進行同樣的處理,我也不確定這種方法對於我想實現的目標是否真的很精確。

+0

我添加了一個新的版本,我的答案是(部分)補償的事實,人類視覺系統ISN對紅色,綠色和藍色同樣敏感。 –

回答

2

我們可以通過循環RGB組件來壓縮該代碼。但是,您當前的算法存在一個錯誤:它可以生成顏色通道值爲< 0或> 255,因此我們需要修復該錯誤。

from random import randint 

def similarColors(rgb, loop=6): 
    colors = [] 
    delta = 30 
    for i in range(loop): 
     new_rgb = [randint(max(0, x - delta), min(x + delta, 255)) for x in rgb] 
     colors.append(new_rgb)     
    return colors 

colors = similarColors([244, 83, 28]) 
print(colors) 

典型輸出

[[249, 75, 28], [226, 111, 34], [235, 85, 46], [228, 66, 28], [244, 62, 8], [233, 102, 21]] 

你說:「我也不敢肯定,如果這方法是什麼,我想真正做到精確」。我不知道你想要達到什麼目標,但是我能看到的一個問題是,人類視覺系統對R,G,B不同等敏感。因此,在一個通道中給定量的變化不會與另一個頻道中的相同更改具有相同的效果。爲了正確處理這個問題,你需要在與人類視覺系統更接近的色彩空間中工作,例如Lab color space。但是,我們可以通過在信道變化量上使用比例因子來獲得合理的近似值。

Grayscale的維基百科文章提供了可用於計算的RGB顏色的亮度的公式:

y = 0.299*R + 0.587*G + 0.114*B 

該公式在模擬NTSC & PAL電視使用。

下面是使用這些縮放因子的上述代碼的一個版本。我們將基數delta除以那些縮放因子,所以藍色三角洲是最大的,因爲綠色三角洲是最小的,因爲眼睛對綠色最敏感並且對藍色最不敏感。

def similarColors(rgb, loop=6): 
    colors = [] 
    delta = 10 
    deltas = [round(delta/u) for u in (0.299, 0.587, 0.114)] 
    for i in range(loop): 
     new_rgb = [randint(max(0, x - delta), min(x + delta, 255)) 
      for x, delta in zip(rgb, deltas)] 
     colors.append(new_rgb) 
    return colors 

colors = similarColors([244, 83, 28]) 
print(colors) 

典型輸出

[[236, 84, 65], [233, 74, 78], [226, 93, 73], [249, 88, 89], [240, 84, 40], [226, 75, 22]] 

爲了使該代碼更有效的,因爲我們使用固定鹼delta我們可以預先計算deltas陣列,而不是重新計算它每我們打電話給similarColors

+0

現在讓它到位,我會說它更容易 - 沒有返回值,並將其應用於圖片的每個像素自動更改圖片 – Sanitiy

+1

@Sanitiy每個Python函數都會返回一些內容:如果沒有返回值,則返回None對象顯式返回。當然,這個函數可以接受一個列表arg,我們可以用新的顏色列表來擴展它。這比擴展全球'顏色'列表要好。我不明白你的意思是什麼「將其應用於圖片的每個像素」,因爲'similarColor'將單個顏色值作爲其arg並返回6個顏色值。 –

+0

爲了提高精度,我的意思是如果顏色是橙色的,它會顯示橙色而不是其他顏色。 – Lindow

1

沒有必要每種顏色複製粘貼,你可以使用一個循環是這樣的:

def similarColors(rgb, loop=6, difference=30): 
    colors = [] 
    for _ in range(loop): 
     color = [] 
     for curr_color in rgb: 
      color.append(randint(curr_color - difference, curr_color + difference)) 
     colors.append(color) 

    return colors 

通知我也把difference中的參數。

並且存在一個錯誤,其中rgb部分可能是< 0或> 255,您可以使用max(0, min(255, randint(curr_color - difference, curr_color + difference)))來解決此問題。

1

如果你可以使用numpy,一個更緊湊的解決方案是這樣的:

import numpy as np 

def similarColors(rgb, loop=6): 
    delta = 30 
    origClrs = np.tile(np.array(rgb), (loop, 1)) 
    randOffsets = np.random.randint(-delta, delta, size=(loop, 3)) 
    return origClrs + randomOffsets