颜色混合的插值方法好吗?
Good interpolation method for color mixing?
这个问题特别解决了油漆、颜料等颜色混合背景下的曲线拟合问题。
我正在尝试猜测两种涂料所需的比例,比方说 "Brown" (B) 和 "white" (W) 以获得给定的亮度值 L。
我做了一个 "calibration curve" 与在化学中应用 Beer-lambert 定律的方式相同。但是,曲线不是线性的,所以我不能使用 Beer-Lambert 法则。
这是我所做的:
(1)
我已经测量了这些混合物比例的油漆样品的光谱,标记为 a、b、c、d、...等
a >>> W = 1, B = 0 (纯白)
b >>> W = 63/64, B = 1/64
c >>> W = 31/32, B = 1/32
d >>> W = 15/16, B = 1/16
e >>> W = 7/8, B = 1/8
f >>> W = 3/4, B = 1/4
g >>> W = 1/2, B = 1/2
h >>> W = 0, B = 1 (纯棕)
这些是我得到的光谱反射率曲线:
如果我 pick-up 一个给定波长的反射率值,例如500 nm,我得到这条漂亮的曲线,其中 x 轴表示混合物中白色涂料的比例,y 轴表示 500 nm 处的反射光:
我想通过插值来猜测需要多少白色才能达到一定的反射光量。
(2)
我尝试用 scipy.optimize.curve_fit
对数据拟合指数曲线,但拟合很差:
什么样的函数最适合数据?
由于没有人回答,我将扩展我的评论。
从图中我看到的,是有规律的。最好的方法是拟合一条适合整个模式的曲线。您可以使用 Eureqa 无需任何数学运算即可完成此操作(免费试用就足够了):http://www.nutonian.com/products/eureqa/
如果你想保持在python并符合指数分布,你可以进行以下操作:
How to do exponential and logarithmic curve fitting in Python? I found only polynomial fitting
所以假设您对波长 500nm 有以下值:
y = [10,20,30,30,50,60,70,80,90,100]
x = [0.,0.3,0.5,0.6,0.72,0.77,0.84,0.9,0.95,1]
那么拟合指数曲线的代码为:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def func(x, a, b, c):
return a * np.exp(-b * x) + c
popt, pcov = curve_fit(func, x, y)
在这种情况下,我们得到 a、b 和 c 是:
popt = array([ 7.1907744 , -2.62804994, 2.45029842])
所以要得到某个x(例如0.2)的反射光值,你可以这样做:
func(0.2, 7.1907744 , -2.62804994, 2.45029842)
也就是 14.61
但是你说它不合适,如果你不需要模型,你可以执行以下操作:如果你真的不在乎模型,你可以使用这个:https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html#scipy.interpolate.interp1d
from scipy import interpolate
f = interpolate.interp1d(x, y, kind="quadratic") #you can try different kinds of interpolation
然后求一个值(比如x=0.2):
ynew = f(0.2)
也就是 6.549
或者有很多值,这样你就可以绘制它们:
ynew = f(np.linspace(0,1,1000)
这个问题特别解决了油漆、颜料等颜色混合背景下的曲线拟合问题。
我正在尝试猜测两种涂料所需的比例,比方说 "Brown" (B) 和 "white" (W) 以获得给定的亮度值 L。
我做了一个 "calibration curve" 与在化学中应用 Beer-lambert 定律的方式相同。但是,曲线不是线性的,所以我不能使用 Beer-Lambert 法则。
这是我所做的:
(1)
我已经测量了这些混合物比例的油漆样品的光谱,标记为 a、b、c、d、...等
a >>> W = 1, B = 0 (纯白)
b >>> W = 63/64, B = 1/64
c >>> W = 31/32, B = 1/32
d >>> W = 15/16, B = 1/16
e >>> W = 7/8, B = 1/8
f >>> W = 3/4, B = 1/4
g >>> W = 1/2, B = 1/2
h >>> W = 0, B = 1 (纯棕)
这些是我得到的光谱反射率曲线:
如果我 pick-up 一个给定波长的反射率值,例如500 nm,我得到这条漂亮的曲线,其中 x 轴表示混合物中白色涂料的比例,y 轴表示 500 nm 处的反射光:
我想通过插值来猜测需要多少白色才能达到一定的反射光量。
(2)
我尝试用 scipy.optimize.curve_fit
对数据拟合指数曲线,但拟合很差:
什么样的函数最适合数据?
由于没有人回答,我将扩展我的评论。
从图中我看到的,是有规律的。最好的方法是拟合一条适合整个模式的曲线。您可以使用 Eureqa 无需任何数学运算即可完成此操作(免费试用就足够了):http://www.nutonian.com/products/eureqa/
如果你想保持在python并符合指数分布,你可以进行以下操作: How to do exponential and logarithmic curve fitting in Python? I found only polynomial fitting
所以假设您对波长 500nm 有以下值:
y = [10,20,30,30,50,60,70,80,90,100]
x = [0.,0.3,0.5,0.6,0.72,0.77,0.84,0.9,0.95,1]
那么拟合指数曲线的代码为:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def func(x, a, b, c):
return a * np.exp(-b * x) + c
popt, pcov = curve_fit(func, x, y)
在这种情况下,我们得到 a、b 和 c 是:
popt = array([ 7.1907744 , -2.62804994, 2.45029842])
所以要得到某个x(例如0.2)的反射光值,你可以这样做:
func(0.2, 7.1907744 , -2.62804994, 2.45029842)
也就是 14.61
但是你说它不合适,如果你不需要模型,你可以执行以下操作:如果你真的不在乎模型,你可以使用这个:https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html#scipy.interpolate.interp1d
from scipy import interpolate
f = interpolate.interp1d(x, y, kind="quadratic") #you can try different kinds of interpolation
然后求一个值(比如x=0.2):
ynew = f(0.2)
也就是 6.549
或者有很多值,这样你就可以绘制它们: ynew = f(np.linspace(0,1,1000)