注意:我之前问过这个问题,但它作为重复问题被关闭,但是,我和其他几个人认为它被不当关闭,我在我原来的编辑中解释了为什么 post .所以我想在这里再次提出这个问题。
有谁知道可以在两行之间进行插值的 python 库。例如,给定下面的两条实线,我想在中间生成虚线。换句话说,我想得到中心线。输入只是两个 numpy
坐标数组,大小分别为 N x 2
和 M x 2
。
此外,我想知道是否有人在一些优化的 python 库中为此编写了一个函数。虽然优化并不是必需的。
这是我可能拥有的两条线的示例,您可以假设它们彼此不重叠并且 x/y 可以有多个 y/x 坐标。
array([[ 1233.87375018, 1230.07095987],
[ 1237.63559365, 1253.90749041],
[ 1240.87500801, 1264.43925132],
[ 1245.30875975, 1274.63795396],
[ 1256.1449357 , 1294.48254424],
[ 1264.33600095, 1304.47893299],
[ 1273.38192911, 1313.71468591],
[ 1283.12411536, 1322.35942538],
[ 1293.2559388 , 1330.55873344],
[ 1309.4817002 , 1342.53074698],
[ 1325.7074616 , 1354.50276051],
[ 1341.93322301, 1366.47477405],
[ 1358.15898441, 1378.44678759],
[ 1394.38474581, 1390.41880113]])
array([[ 1152.27115094, 1281.52899302],
[ 1155.53345506, 1295.30515742],
[ 1163.56506781, 1318.41642169],
[ 1168.03497425, 1330.03181319],
[ 1173.26135672, 1341.30559949],
[ 1184.07110925, 1356.54121651],
[ 1194.88086178, 1371.77683353],
[ 1202.58908737, 1381.41765447],
[ 1210.72465255, 1390.65097106],
[ 1227.81309742, 1403.2904646 ],
[ 1244.90154229, 1415.92995815],
[ 1261.98998716, 1428.56945169],
[ 1275.89219696, 1438.21626352],
[ 1289.79440676, 1447.86307535],
[ 1303.69661656, 1457.50988719],
[ 1323.80994319, 1470.41028655],
[ 1343.92326983, 1488.31068591],
[ 1354.31738934, 1499.33260989],
[ 1374.48879779, 1516.93734053],
[ 1394.66020624, 1534.54207116]])
因此,我尝试使用 skemage.morphology
库中的 skeletonize
函数,首先将坐标栅格化为填充的多边形。但是,我在这样的末端得到分支:
最佳答案
首先,请原谅矫枉过正;我对你的问题很感兴趣。如果描述太长,请随意跳到底部,我定义了一个函数来完成我描述的所有事情。
如果您的数组长度相同,您的问题会相对简单。在这种情况下,您所要做的就是找到每个数组中对应的 x 值与每个数组中对应的 y 值之间的平均值。
所以我们可以做的是创建相同长度的数组,这些数组或多或少是对原始数组的良好估计。我们可以通过将多项式拟合到您拥有的数组来做到这一点。正如评论和其他答案中所述,您的原始阵列的中线没有具体定义,因此一个好的估计应该可以满足您的需求。
注意:在所有这些示例中,我已经将您发布的两个数组命名为 a1
和 a2
。
第一步:创建新的数组来估计你的旧行
查看您发布的数据:
这些并不是特别复杂的函数,看起来 3 次多项式可以很好地适合它们。我们可以使用 numpy
创建它们:
import numpy as np
# Find the range of x values in a1
min_a1_x, max_a1_x = min(a1[:,0]), max(a1[:,0])
# Create an evenly spaced array that ranges from the minimum to the maximum
# I used 100 elements, but you can use more or fewer.
# This will be used as your new x coordinates
new_a1_x = np.linspace(min_a1_x, max_a1_x, 100)
# Fit a 3rd degree polynomial to your data
a1_coefs = np.polyfit(a1[:,0],a1[:,1], 3)
# Get your new y coordinates from the coefficients of the above polynomial
new_a1_y = np.polyval(a1_coefs, new_a1_x)
# Repeat for array 2:
min_a2_x, max_a2_x = min(a2[:,0]), max(a2[:,0])
new_a2_x = np.linspace(min_a2_x, max_a2_x, 100)
a2_coefs = np.polyfit(a2[:,0],a2[:,1], 3)
new_a2_y = np.polyval(a2_coefs, new_a2_x)
结果:
这还不错,太糟糕了!如果您有更复杂的函数,则必须拟合更高阶的多项式,或找到其他一些足够的函数来拟合您的数据。
现在,您有两组相同长度的数组(我选择了 100 的长度,您可以根据您希望中点线的平滑程度来增加或减少)。这些集合表示原始数组的估计值 的 x 和 y 坐标。在上面的示例中,我将它们命名为 new_a1_x
、new_a1_y
、new_a2_x
和 new_a2_y
。
第二步:计算新数组中每个 x 和每个 y 之间的平均值
然后,我们要为每个估计数组找到平均 x 和平均 y 值。只需使用 np.mean
:
midx = [np.mean([new_a1_x[i], new_a2_x[i]]) for i in range(100)]
midy = [np.mean([new_a1_y[i], new_a2_y[i]]) for i in range(100)]
midx
和 midy
现在代表我们的 2 个估计数组之间的中点。现在,只需绘制您的原始(不是估计)数组以及您的中点数组:
plt.plot(a1[:,0], a1[:,1],c='black')
plt.plot(a2[:,0], a2[:,1],c='black')
plt.plot(midx, midy, '--', c='black')
plt.show()
瞧:
此方法仍然适用于更复杂、嘈杂的数据(但您必须仔细考虑函数):
作为函数:
我把上面的代码放在了一个函数中,所以你可以很容易地使用它。它以原始数组的格式返回您估计的中点数组。
参数:a1
和 a2
是你的 2 个输入数组,poly_deg
是你想要拟合的次数多项式,n_points
是你想要的中点数组中的点数,plot
是一个 bool 值,无论你是否想要绘制它。
import matplotlib.pyplot as plt
import numpy as np
def interpolate(a1, a2, poly_deg=3, n_points=100, plot=True):
min_a1_x, max_a1_x = min(a1[:,0]), max(a1[:,0])
new_a1_x = np.linspace(min_a1_x, max_a1_x, n_points)
a1_coefs = np.polyfit(a1[:,0],a1[:,1], poly_deg)
new_a1_y = np.polyval(a1_coefs, new_a1_x)
min_a2_x, max_a2_x = min(a2[:,0]), max(a2[:,0])
new_a2_x = np.linspace(min_a2_x, max_a2_x, n_points)
a2_coefs = np.polyfit(a2[:,0],a2[:,1], poly_deg)
new_a2_y = np.polyval(a2_coefs, new_a2_x)
midx = [np.mean([new_a1_x[i], new_a2_x[i]]) for i in range(n_points)]
midy = [np.mean([new_a1_y[i], new_a2_y[i]]) for i in range(n_points)]
if plot:
plt.plot(a1[:,0], a1[:,1],c='black')
plt.plot(a2[:,0], a2[:,1],c='black')
plt.plot(midx, midy, '--', c='black')
plt.show()
return np.array([[x, y] for x, y in zip(midx, midy)])
[编辑]:
我在回想这个问题时,忽略了一种更简单的方法,即使用 np.interp
将两个数组“致密化”到相同数量的点。 .此方法遵循与上述线拟合方法相同的基本思想,但不是使用 polyfit
/polyval
来近似线,它只是增密:
min_a1_x, max_a1_x = min(a1[:,0]), max(a1[:,0])
min_a2_x, max_a2_x = min(a2[:,0]), max(a2[:,0])
new_a1_x = np.linspace(min_a1_x, max_a1_x, 100)
new_a2_x = np.linspace(min_a2_x, max_a2_x, 100)
new_a1_y = np.interp(new_a1_x, a1[:,0], a1[:,1])
new_a2_y = np.interp(new_a2_x, a2[:,0], a2[:,1])
midx = [np.mean([new_a1_x[i], new_a2_x[i]]) for i in range(100)]
midy = [np.mean([new_a1_y[i], new_a2_y[i]]) for i in range(100)]
plt.plot(a1[:,0], a1[:,1],c='black')
plt.plot(a2[:,0], a2[:,1],c='black')
plt.plot(midx, midy, '--', c='black')
plt.show()
关于python - 如何在python中的另外两条线之间插入一条线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49037902/