[英]Simplest Example of Linear Interpolation for Color in Python
我正在尋找一種基於附近物體的 colors 為物體着色的方法,從我讀過的內容來看,它看起來像線性插值是要做的事情。
我已經瀏覽了很多(全部?)關於 Python 中顏色線性插值的 SO 帖子,但無法使其中的任何一個與我的代碼一起使用。
我現在想盡量保持這個簡單。 如果我有一個從紫色到白色的漸變和兩個對象,我怎么能告訴 python:如果 object 1 是紫色,那么讓 object 2 變成淺紫色?
查看這篇文章,function lerp 定義為:
def lerp(color1, color2, frac):
return color1 * (1 - frac) + color2 * frac
但我不明白如何應用它。 這篇文章有很多建議,但似乎沒有解決,盡管它確實包含許多關於加色和減色方法的有趣信息。 我知道着色很復雜,我不想做一個多余的帖子,所以我希望真正強調我正在尋找最簡單、最基本的方法來做一些非常簡單的事情,比如讓 object 的顏色更淺如果它與深紫色的 object 相鄰,則為紫色。
對於這個例子,我創建了 3 個多邊形並將它們全部着色為洋紅色:
import matplotlib.pyplot as plt
from shapely.geometry import Point, LineString
# functions for plotting
def plot_coords(coords, color):
pts = list(coords)
x, y = zip(*pts)
# print(color)
plt.plot(x,y, color='k', linewidth=1)
plt.fill_between(x, y, facecolor=color)
def plot_polys(polys, color):
for poly, color in zip(polys, color):
plot_coords(poly.exterior.coords, color)
x = 0
y = 0
# make some points
points = [Point(x, y),
Point((x + 2), y),
Point((x - 2), y)]
#buffer points by 2 to make circles
circles = []
for point in points:
circles.append(point.buffer(2))
# plot 3 magenta circles
plot_polys(circles, "m"*3)
我如何使用上面的 lerp function (或不同的)在漸變上為我的圓圈着色?
注意:我知道我可以使用 matplotlib 中的預制調色板,但我的長期目標是了解控制顏色變化的算法。
謝謝你的幫助!
在下文中,我不使用圓形或多邊形,只是使用普通曲線,但我相信你會明白我的意思。
我的3分,就是……
如果我們可以對顏色分量使用實數,顏色插值的工作方式非常簡單,因此我們在RGB
空間中定義 colors,使用matplotlib.colors.to_rgb
。
必須對兩個 colors 的每個單獨組件進行插值。
最終,我們可以為每條曲線指定不同的顏色,使用正弦的時間偏移作為我們的參數。
我還添加了一條細黑線來“關閉”繪圖,只是為了美觀。
如果你能適應你的問題,好的,否則就問!
import numpy as np
import matplotlib.pyplot as plt
# point no. 1
from matplotlib.colors import to_rgb
mgt, wht = to_rgb('magenta'), to_rgb('white')
# point no.2
def mix(col0, col1, ratio):
return tuple(cmp0*ratio+cmp1*(1-ratio)
for cmp0, cmp1 in zip(col0, col1))
t = np.linspace(0, 2*np.pi, 629)
# point no. 3, the phase shifts but also the interpolation ratios
for phase_shift in np.linspace(0, 1, 31):
plt.plot(t, np.sin(t-phase_shift), color=mix(wht, mgt, phase_shift))
plt.plot(t, np.sin(t-phase_shift), color='k', lw=0.4)
plt.show()
PS最好在生產中檢查0 ≤ ratio ≤ 1
,不是嗎?
那很好笑。 在過去,我對漸變和顏色混合的感覺與您完全一樣。 這是一個一開始看起來很容易理解的主題,但你越深入,你就越困惑。 這促使我編寫了一個名為colorir的庫,其目的是使用 python 中的 colors 簡化工作流程。 它的主要賣點之一是制作漸變和插入 colors 是多么容易。
貝婁遵循您的代碼的工作版本,我只更改了兩行使其工作。 我還刪除了您的評論,以突出我所做的更改。
import matplotlib.pyplot as plt
from shapely.geometry import Point, LineString
from colorir import Grad
def plot_coords(coords, color):
pts = list(coords)
x, y = zip(*pts)
plt.plot(x,y, color='k', linewidth=1)
plt.fill_between(x, y, facecolor=color)
def plot_polys(polys, color):
for poly, color in zip(polys, color):
plot_coords(poly.exterior.coords, color)
x = 0
y = 0
points = [Point((x - 2), y), # Points were ordered according to their x values
Point(x, y),
Point((x + 2), y)]
circles = []
for point in points:
circles.append(point.buffer(2))
# Create a gradient from magenta to white and sample three colors
colors = Grad(["ff00ff", "ffffff"]).n_colors(3)
plot_polys(circles, colors)
plt.show()
既然你說你想對插值如何工作有一些直覺,我會盡力解釋 colorir 在桌子底下做了什么。
首先,您需要了解插值的含義。
簡單地說,插值是在坐標系中找到兩點之間的中點的過程。 這意味着如果我有一個點 (1, 2, 3) 和一個點 (0, 0, 0),則這些點的中間 (0.5) 插值是 (0.5, 1, 1.5)。 我們還可以在 0 - 1 區間內插入其他值,例如 0.3、0.7 等。
顏色插值的問題特別來自於 RGB 不是一個感知統一的顏色系統這一事實。 從本質上講,這意味着兩個 RGB 點的中間點插值並不是大多數人認為的 colors 的完美混合。 您可以在此處閱讀有關此主題的更多信息。
我們如何解決這個問題? 嗯,最簡單的方法是首先將 RGB 值轉換為感知一致的顏色系統,然后才在新坐標系統中插入點。
這是 colorir 在您創建Grad
object 時所做的:
"ff00ff"
- 洋紅色和"ffffff"
- 白色)Grad.n_colors()
此過程的第三步實際上實現了一個與您在問題中提到的非常相似的公式。 類似(偽代碼):
function lerp(color1, color2, percentage):
return [
(color2[0] - color2[0]) * percentage,
(color2[1] - color2[1]) * percentage,
(color2[2] - color2[2]) * percentage
]
有關如何使用 colorir,請參閱colorir 的文檔和其他問題。
另外,請隨意查看colorir 源代碼中的數學運算!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.