问题描述:尝试使用UnivariateSpline实现曲线调整,为了完成图像处理的曲线调整。遇到的问题如:dfitpack.error:(m>k) failed for hidden m: fpcurf0:m=2
原代码处理:
# 计算曲线插值
def _find_coefficients(curves):
polynomials = []
for curve in curves:
xdata = [x[0] for x in curve]
ydata = [x[1] for x in curve]
xs = np.array(xdata)
ys = np.array(ydata)
p = interpolate.UnivariateSpline(xdata, ydata)
polynomials.append(p)
return polynomials
回溯:
---------------------------------------------------------------------------
error Traceback (most recent call last)
<ipython-input-38-289216dd01e1> in <module>
8 x=[0,128,255]
9 y=[0,190,255]
---> 10 myLUT=spline_to_lookup_table(x,y)
<ipython-input-38-289216dd01e1> in spline_to_lookup_table(spline_breaks, break_values)
1 def spline_to_lookup_table(spline_breaks: list, break_values: list):
----> 2 spl = UnivariateSpline(spline_breaks, break_values)
4 return spl(range(256))
~/anaconda3/envs/computer-vision/lib/python3.8/site-packages/scipy/interpolate/fitpack2.py in __init__(self, x, y, w, bbox, k, s, ext, check_finite)
200
201 # _data == x,y,w,xb,xe,k,s,n,t,c,fp,fpint,nrdata,ier
--> 202 data = dfitpack.fpcurf0(x, y, k, w=w, xb=bbox[0],
203 xe=bbox[1], s=s)
204 if data[-1] == 1:
error: (m>k) failed for hidden m: fpcurf0:m=3
主要错误:
curves = [[(0, 0), (89, 67),(120, 87), (186, 255), (255, 255)], [(0, 0), (74, 56), (175, 206), (255, 255)], [(0, 0), (74, 54), (179, 206), (255, 255)],
[(0, 0), (49, 79), (202, 181), (255, 255)], [(0, 0), (255, 255)]];
其实就是使用的lumo滤镜模板最后的 [(0, 0), (255, 255)] 元素只有两个,不能使用不能用三个点来拟合一条三次样条曲线(spline函数默认k值为3),甚至也不能只有三个点,通俗的说就是即使是一条三次抛物线也有四个参数。
实际上应该先了解一下scipy.interpolate.UnivariateSpline的用法和作用还有优点
下面为该函数的主要详细介绍:
用法:
class scipy.interpolate.UnivariateSpline(x, y, w=None, bbox=[None, None], k=3, s=None, ext=0, check_finite=False)
一维平滑样条拟合到一组给定的数据点。
将 k 次的样条 y = spl(x) 拟合到提供的 x, y 数据。 s 通过指定平滑条件来指定节数。
参数:
x: (N,) 数组
独立输入数据的一维数组。必须增加;如果 s 为 0,则必须严格递增。
y: (N,) 数组
与 x 长度相同的相关输入数据的一维数组。
w: (N,) 数组, 可选
花键拟合的权重。必须是积极的。如果 w 为 None,则权重均相等。默认为无。
bbox: (2,) 类数组,可选
2-sequence 指定近似区间的边界。如果盒子是无,bbox=[x[0], x[-1]]
.默认为无。
k: 整数,可选
平滑样条的度数。必须是 1 <=k<= 5。k = 3
是三次样条。默认值为 3。
s: 浮点数或无,可选
用于选择结数的正平滑因子。节点数将增加,直到满足平滑条件:
sum((w[i] * (y[i]-spl(x[i])))**2, axis=0) <= s
如果s是无,s = len(w)
如果这应该是一个很好的值1/w[i]
是标准差的估计值y[i]
.如果为 0,则样条将插入所有数据点。默认为无。
ext: int 或 str,可选
控制不在节点序列定义的区间内的元素的外推模式。
-
如果 ext=0 或 ‘extrapolate’,则返回外推值。
-
如果 ext=1 或 ‘zeros’,返回 0
-
如果 ext=2 或 ‘raise’,引发 ValueError
-
如果‘const’的ext=3,返回边界值。
默认值为 0。
check_finite: 布尔型,可选
是否检查输入数组是否仅包含有限数。禁用可能会提高性能,但如果输入确实包含无穷大或 NaN,则可能会导致问题(崩溃、非终止或无意义的结果)。默认为假。
注意:
数据点的数量必须大于样条度 k。
NaN handling:如果输入数组包含nan
值,结果没有用,因为底层的样条拟合例程无法处理nan
.一种解决方法是对not-a-number 数据点使用零权重:
>>> from scipy.interpolate import UnivariateSpline
>>> x, y = np.array([1, 2, 3, 4]), np.array([1, np.nan, 3, 4])
>>> w = np.isnan(y)
>>> y[w] = 0.
>>> spl = UnivariateSpline(x, y, w=~w)
请注意,需要用数值替换 nan
(只要相应的权重为零,精确值无关紧要。)
参考博客:
Python scipy.interpolate.UnivariateSpline用法及代码示例 - 纯净天空 (vimsky.com)
Scipy UnivariateSpline错误:(m>k)隐藏m: fpcurf0:m=3失败 - 问答 - 腾讯云开发者社区-腾讯云 (tencent.com)