Numpy 在Python中二维多项式拟合的等效函数
在数据科学领域中,我们经常需要拟合一些复杂的数据模型。其中一个常见的拟合方法是多项式拟合。而在实现这个方法时,可以使用Numpy库的 polyfit 函数。但是,这个函数只支持一维多项式拟合。在需要使用二维多项式拟合时,我们需要一些特殊的技巧来实现。本文将为您详细介绍如何使用Numpy实现在Python中的二维多项式拟合。
阅读更多:Numpy 教程
什么是二维多项式?
二维多项式是一个拥有两个变量的高阶多项式函数。对于一个二维多项式函数 f(x,y),可以使用以下公式进行表示:
f(x,y) = \sum_{i=0}^{m} \sum_{j=0}^{n} c_{ij} x^i y^j
其中,m 和 n 分别代表多项式的阶数,c_{ij} 代表多项式系数。
二维多项式拟合
在Python中,我们可以使用 numpy.polyfit函数实现一维多项式拟合。当我们需要对一个由 (x,y) 所组成的点集进行二维多项式拟合时,最常用的方法是将所有数据用一维数组表示。但是,要注意将输入点的坐标 (x,y) 转换成 x^i y ^j 格式,以便利用一维多项式拟合函数。
因此,我们需要对输入点坐标进行转换。这种转换需要使点 (x,y) 映射到长度为 p 的一维向量 v:
v = [1, x, y, x^2, xy, y^2, \dots, x^n, x^{n-1}y, \dots, y^n]
可以看到,当 n 和 m 的值较大时,一维数组的长度会变得非常大。而在实际中,很难保证拟合的精度,因此,需要使用二维多项式拟合函数。
目前,Numpy库并没有内置的二维多项式拟合函数。然而,我们可以使用多项式系数矩阵来实现二维多项式拟合。
多项式系数矩阵
在二维多项式拟合中,我们需要生成多项式系数矩阵以完成系数的计算。对于一个二维多项式,多项式系数矩阵的大小为 (n+1)(m+1) \times (n+1)(m+1),其中,n 和 m 分别表示多项式的阶数。
多项式系数矩阵可以通过以下公式进行计算:
A_ij = x_i^j y_i^k
其中,“x_i^jy_i^k”代表输入点 (x_i,y_i) 的坐标在多项式公式中对应的项。
这样,一个由 (x,y) 所组成的点集就可以被用来计算多项式系数矩阵了。然后就可以使用Numpy的线性代数函数将总体方程的系数求出来。
下面的代码演示了如何生成多项式系数矩阵并计算多项式系数:
import numpy as np
# 初始化输入点(x,y)数据
point_data = np.array([(0, 0), (1, 1), (1, -1), (-1, 1), (-1, -1),(2, 0), (-2, 0),(0, 2), (0, -2)])
x = point_data[:, 0]
y =point_data[:, 1]
# 设置多项式阶数
m = 3
n = 3
# 生成数组,用于组成多项式系数矩阵
vt = []
for i in range(n+1):
for j in range(m+1):
vt.append((x**j)*(y**i))
vander = np.column_stack(vt)
# 计算多项式系数
coeffs = np.linalg.lstsq(vander, point_data[:, 1], rcond=None)[0]
这里的 lstsq 函数使用Numpy的线性代数库,以确保高效且准确地计算多项式系数。我们还需要注意,数组索引采用的是“列组成”的形式,因此我们需要使用 point_data [:, 1] 来表示点的 y 值。
应用于图像拟合
在图像处理过程中,二维多项式拟合可以用来进行图像校正或者提取目标轮廓。我们来看一个简单的例子,用二维多项式拟合函数来匹配并拟合两幅图像。
我们首先需要导入相关的Python库。这里我们导入 numpy 库用来进行数组计算,以及 matplotlib 库用于画图。同时,还需导入 cv2 用于加载,并进行图像处理。
import numpy as np
import cv2
import matplotlib.pyplot as plt
接下来,我们需要加载两幅图像,一个是原始图像,另一个是带有一定偏移量的图像。然后,通过使用OpenCV函数 cv2.getAffineTransform 得到变换矩阵(AffineTransform),也可以通过矩阵计算得到。
# 读取图像文件
img1 = cv2.imread('image1.jpg')
img2 = cv2.imread('image2.jpg')
# 获取图像的宽高
height, width = img1.shape[:2]
# 设定原图像和目标图像需要匹配的点
src_points = np.float32([[0, 0], [width-1, 0], [0, height-1]])
dest_points = np.float32([[50, 50], [width-71, 31], [44, height-60]])
# 对目标图像进行变形,得到对齐后的图像,并获得变换矩阵
M = cv2.getAffineTransform(src_points, dest_points)
img2_aligned = cv2.warpAffine(img2, M, (width, height))
现在,已经得到了两个相同形状的图像,图像间没有任何形变,对齐后的目标图像上的点与原始图像匹配的点之间的偏移量也已知。我们只需计算这些点并进行拟合就可以了。
# 计算需要拟合的点坐标
point_data = []
for y in range(height):
for x in range(width):
if img1[y, x][0] > 0 and img2_aligned[y, x][0] > 0:
point_data.append([x, y])
# 转换成Numpy数组并进行多项式拟合
point_data = np.array(point_data)
x, y = point_data.T
m, n = 3, 3
X = np.zeros((len(x), (m + 1) * (n + 1)))
for i in range(n + 1):
for j in range(m + 1):
X[:, i * (m + 1) + j] = x ** j * y ** i
C, _, _, _ = np.linalg.lstsq(X, point_data[:, 1], rcond=None)
print(C)
z = np.zeros_like(x)
for i in range(n + 1):
for j in range(m + 1):
z += C[i * (m + 1) + j] * x ** j * y ** i
# 改变拟合出来的Z轴数据成为图像矩阵,并绘制对比图
z = z.reshape(height, width)
img1_vs_img2 = np.zeros((height, width * 2, 3))
img1_vs_img2[:, :width] = img1
img1_vs_img2[:, width:] = img2_aligned
for x, y in point_data:
x = int(round(x))
y = int(round(y))
cv2.circle(img1_vs_img2, (x, y), 1, (0, 255, 0), -1)
cv2.circle(img1_vs_img2, (x + width, y), 1, (0, 255, 0), -1)
plt.imshow(cv2.cvtColor(img1_vs_img2.astype(np.uint8), cv2.COLOR_BGR2RGB))
plt.show()
这里生成的三维多项式系数矩阵 C,可以使用也可以将其绘制成图像。以上代码演示了如何在两幅图像中进行匹配,并使用多项式拟合实现图像处理。
总结
Python中无法直接使用Numpy库的 polyfit 函数实现二维多项式拟合。但是,可以使用多项式系数矩阵等技术实现这一功能。在实际应用中,二维多项式拟合被广泛用于图像匹配、图像平面校正等领域,可以大大提高数据拟合的准确性和精度。技术不断进步,本文介绍的二维多项式拟合只是冰山一角,在不断发展的领域里,我们期待更多的高效算法和方式来处理这种复杂的问题。
极客教程