如何根据权重为3D B样条上色

huangapple go评论96阅读模式
英文:

How to color 3D BSplines based on weights

问题

给定一个包含记录的三轴加速度值的数据框,用于确定位置向量。在应用BSpline之后,有一条看起来相当平滑的曲线。

作为下一步,我想使用不同的颜色显示加速度的程度。
对此,https://stackoverflow.com/questions/42215777/matplotlib-line-color-in-3d 提供了一个很好的基础,尽管结果有点混乱,我无法确定根本原因:

这是CSV中的加速度值记录:

  1. ,Counter,Acc.X,Acc.Y,Acc.Z
  2. 18,18,9.71,0.51,4.41
  3. 19,19,9.69,0.65,4.34
  4. 20,20,9.67,0.6,4.3
  5. 21,21,9.6,0.59,4.33
  6. 22,22,9.34,0.11,4.63
  7. 23,23,6.01,-2.75,8.43
  8. 24,24,0.58,-5.01,6.18
  9. 25,25,2.16,-2.19,0.8
  10. 26,26,7.42,-1.84,-4.85
  11. 27,27,12.56,-5.04,-8.95
  12. 28,28,14.78,-9.62,-8.07
  13. 29,29,10.82,-7.58,-5.8
  14. 30,30,11.05,-8.45,-3.82

以下是代码:

  1. import pandas as pd
  2. import numpy as np
  3. from scipy.interpolate import splrep, BSpline
  4. from mpl_toolkits import mplot3d
  5. %matplotlib inline
  6. import matplotlib.pyplot as plt
  7. from matplotlib.colors import ListedColormap
  8. from mpl_toolkits.mplot3d.art3d import Line3DCollection
  9. from enum import Enum
  10. class axis(Enum):
  11. X = 1
  12. Y = 2
  13. Z = 3
  14. records = pd.read_csv(filepath_or_buffer='input.csv', index_col=0, sep=',')
  15. i = range(0, len(records.index)-1)
  16. x = (records.iloc[1:].values-records.iloc[:-1]).loc[:,'Acc.X'].to_numpy()
  17. y = (records.iloc[1:].values-records.iloc[:-1]).loc[:,'Acc.Y'].to_numpy()
  18. z = (records.iloc[1:].values-records.iloc[:-1]).loc[:,'Acc.Z'].to_numpy()
  19. ii = np.linspace(i.start, i.stop)
  20. tckx0 = splrep(i, x, s=0)
  21. tckx = splrep(i, x, s=50)
  22. tcky = splrep(i, y, s=50)
  23. tckz = splrep(i, z, s=50)
  24. ax = plt.figure(figsize=(50, 50)).add_subplot(projection='3d')
  25. ax.plot(BSpline(*tckx)(ii),BSpline(*tcky)(ii),BSpline(*tckz)(ii), 'o--', color='green')
  26. plt.show()

结果如下图所示:
如何根据权重为3D B样条上色

应用颜色,首先使用简单的样式,比如'magma':

  1. # Coloring
  2. points = np.array([BSpline(*tckx)(ii),BSpline(*tcky)(ii),BSpline(*tckz)(ii)]).transpose().reshape(-1,1,3)
  3. segs = np.concatenate([points[:-1],points[1:]],axis=1)
  4. lc = Line3DCollection(segs, cmap=plt.get_cmap('magma'))
  5. lc.set_array(ii)
  6. fig = plt.figure(figsize=(50, 50))
  7. ax = fig.add_subplot(111, projection='3d')
  8. ax.add_collection3d(lc)
  9. plt.show()

图像完全混乱:
如何根据权重为3D B样条上色

我无法确定根本原因,你能帮我吗?

英文:

Given a Dataframe with recorded acceleration values on 3-axis that are used to determine position vectors. After applying BSpline, there is a smooth curve which looks quite well.

As a next step, I want to show also the extent of acceleration using different colors.
For that, https://stackoverflow.com/questions/42215777/matplotlib-line-color-in-3d gives a good base, although the result is somehow messy, and I cannot identify the root cause:

Here is the record of acceleration values in CSV:

  1. ,Counter,Acc.X,Acc.Y,Acc.Z
  2. 18,18,9.71,0.51,4.41
  3. 19,19,9.69,0.65,4.34
  4. 20,20,9.67,0.6,4.3
  5. 21,21,9.6,0.59,4.33
  6. 22,22,9.34,0.11,4.63
  7. 23,23,6.01,-2.75,8.43
  8. 24,24,0.58,-5.01,6.18
  9. 25,25,2.16,-2.19,0.8
  10. 26,26,7.42,-1.84,-4.85
  11. 27,27,12.56,-5.04,-8.95
  12. 28,28,14.78,-9.62,-8.07
  13. 29,29,10.82,-7.58,-5.8
  14. 30,30,11.05,-8.45,-3.82

And the code:

  1. import pandas as pd
  2. import numpy as np
  3. from scipy.interpolate import splrep, BSpline
  4. from mpl_toolkits import mplot3d
  5. %matplotlib inline
  6. import matplotlib.pyplot as plt
  7. from matplotlib.colors import ListedColormap
  8. from mpl_toolkits.mplot3d.art3d import Line3DCollection
  9. from enum import Enum
  10. class axis(Enum):
  11. X = 1
  12. Y = 2
  13. Z = 3
  14. records = pd.read_csv(filepath_or_buffer='input.csv', index_col=0, sep=',')
  15. i = range(0, len(records.index)-1)
  16. x = (records.iloc[1:].values-records.iloc[:-1]).loc[:,'Acc.X'].to_numpy()
  17. y = (records.iloc[1:].values-records.iloc[:-1]).loc[:,'Acc.Y'].to_numpy()
  18. z = (records.iloc[1:].values-records.iloc[:-1]).loc[:,'Acc.Z'].to_numpy()
  19. ii = np.linspace(i.start, i.stop);
  20. tckx0 = splrep(i, x, s=0)
  21. tckx = splrep(i, x, s=50)
  22. tcky = splrep(i, y, s=50)
  23. tckz = splrep(i, z, s=50)
  24. ax = plt.figure(figsize=(50, 50)).add_subplot(projection='3d')
  25. ax.plot(BSpline(*tckx)(ii),BSpline(*tcky)(ii),BSpline(*tckz)(ii), 'o--', color='green')
  26. plt.show()

It results the following figure:
如何根据权重为3D B样条上色

Applying colors, firstly just a simple style such as 'magma':

  1. # Coloring
  2. points = np.array([BSpline(*tckx)(ii),BSpline(*tcky)(ii),BSpline(*tckz)(ii)]).transpose().reshape(-1,1,3)
  3. segs = np.concatenate([points[:-1],points[1:]],axis=1)
  4. lc = Line3DCollection(segs, cmap=plt.get_cmap('magma'))
  5. lc.set_array(ii)
  6. fig = plt.figure(figsize=(50, 50))
  7. ax = fig.add_subplot(111, projection='3d')
  8. ax.add_collection3d(lc)
  9. plt.show()

The figure is completely messed:
如何根据权重为3D B样条上色

I cannot identify the root cause, could you please help me?

答案1

得分: 0

我认为你正在插值错误的内容。

要插值一个3D曲线,你需要使用scipy的splprep参见这个问题)。

要插值一个1D曲线,你需要使用scipy的splrep

在以下代码中,我还绘制了初始的x, y, z数据,以便你可以将你的结果与我的结果进行比较。

  1. from scipy.interpolate import splrep, BSpline, splev, splprep
  2. from mpl_toolkits import mplot3d
  3. import matplotlib.pyplot as plt
  4. from matplotlib.colors import ListedColormap
  5. from mpl_toolkits.mplot3d.art3d import Line3DCollection
  6. import numpy as np
  7. from enum import Enum
  8. class axis(Enum):
  9. X = 1
  10. Y = 2
  11. Z = 3
  12. from io import StringIO
  13. import pandas as pd
  14. mystr = StringIO("""Counter,Acc.X,Acc.Y,Acc.Z
  15. 18,18,9.71,0.51,4.41
  16. 19,19,9.69,0.65,4.34
  17. 20,20,9.67,0.6,4.3
  18. 21,21,9.6,0.59,4.33
  19. 22,22,9.34,0.11,4.63
  20. 23,23,6.01,-2.75,8.43
  21. 24,24,0.58,-5.01,6.18
  22. 25,25,2.16,-2.19,0.8
  23. 26,26,7.42,-1.84,-4.85
  24. 27,27,12.56,-5.04,-8.95
  25. 28,28,14.78,-9.62,-8.07
  26. 29,29,10.82,-7.58,-5.8
  27. 30,30,11.05,-8.45,-3.82
  28. """)
  29. records = pd.read_csv(mystr, sep=",")
  30. i = range(0, len(records.index)-1)
  31. x = (records.iloc[1:].values-records.iloc[:-1]).loc[:,'Acc.X'].to_numpy()
  32. y = (records.iloc[1:].values-records.iloc[:-1]).loc[:,'Acc.Y'].to_numpy()
  33. z = (records.iloc[1:].values-records.iloc[:-1]).loc[:,'Acc.Z'].to_numpy()
  34. ii = np.linspace(i.start, i.stop)
  35. tckx0 = splrep(i, x, s=0)
  36. tckx = splrep(i, x, s=50)
  37. tcky = splrep(i, y, s=50)
  38. tckz = splrep(i, z, s=50)
  39. fig = plt.figure()
  40. ax = fig.add_subplot(projection='3d')
  41. ax.plot(x, y, z, 'ko', label="true data")
  42. ax.plot(BSpline(*tckx)(ii),BSpline(*tcky)(ii),BSpline(*tckz)(ii),
  43. color='green', label="your interpolation")
  44. # 3D曲线的样条插值
  45. tck, u = splprep([x, y, z], s=2)
  46. ii = np.linspace(0, 1)
  47. xs, ys, zs = splev(ii, tck)
  48. # 1D曲线的样条插值
  49. a_x = records["Acc.X"].to_numpy()[:-1]
  50. a_y = records["Acc.Y"].to_numpy()[:-1]
  51. a_z = records["Acc.Z"].to_numpy()[:-1]
  52. # 根据加速度的大小着色
  53. a = np.sqrt(a_x**2 + a_y**2 + a_z**2)
  54. tcka = splrep(np.linspace(0, 1, len(a)), a, s=0)
  55. parameter = splev(ii, tcka)
  56. ax.plot(xs, ys, zs, 'r.', label="new interpolation")
  57. def get_segments(x, y, z):
  58. points = np.ma.array([x, y, z]).T.reshape(-1, 1, 3)
  59. return np.ma.concatenate([points[:-1], points[1:]], axis=1)
  60. line = Line3DCollection(get_segments(xs, ys, zs), cmap="magma", array=parameter)
  61. ax.add_collection(line)
  62. fig.colorbar(line, label="acceleration")
  63. ax.legend()
  64. plt.show()

如何根据权重为3D B样条上色

  1. <details>
  2. <summary>英文:</summary>
  3. I think you are interpolating the wrong things.
  4. To interpolate a 3D curve you have to use scipy&#39;s `splprep` ([see this question](https://stackoverflow.com/questions/18962175/spline-interpolation-coefficients-of-a-line-curve-in-3d-space)).
  5. To interpolate a 1D curve you have to use scipy&#39;s `splrep`.
  6. In the following code I also plotted the initial `x, y, z` data so that you can compare your result with what I come up.
  7. ```py
  8. from scipy.interpolate import splrep, BSpline, splev, splprep
  9. from mpl_toolkits import mplot3d
  10. import matplotlib.pyplot as plt
  11. from matplotlib.colors import ListedColormap
  12. from mpl_toolkits.mplot3d.art3d import Line3DCollection
  13. import numpy as np
  14. from enum import Enum
  15. class axis(Enum):
  16. X = 1
  17. Y = 2
  18. Z = 3
  19. from io import StringIO
  20. import pandas as pd
  21. mystr = StringIO(&quot;&quot;&quot;Counter,Acc.X,Acc.Y,Acc.Z
  22. 18,18,9.71,0.51,4.41
  23. 19,19,9.69,0.65,4.34
  24. 20,20,9.67,0.6,4.3
  25. 21,21,9.6,0.59,4.33
  26. 22,22,9.34,0.11,4.63
  27. 23,23,6.01,-2.75,8.43
  28. 24,24,0.58,-5.01,6.18
  29. 25,25,2.16,-2.19,0.8
  30. 26,26,7.42,-1.84,-4.85
  31. 27,27,12.56,-5.04,-8.95
  32. 28,28,14.78,-9.62,-8.07
  33. 29,29,10.82,-7.58,-5.8
  34. 30,30,11.05,-8.45,-3.82
  35. &quot;&quot;&quot;)
  36. records = pd.read_csv(mystr, sep=&quot;,&quot;)
  37. i = range(0, len(records.index)-1)
  38. x = (records.iloc[1:].values-records.iloc[:-1]).loc[:,&#39;Acc.X&#39;].to_numpy()
  39. y = (records.iloc[1:].values-records.iloc[:-1]).loc[:,&#39;Acc.Y&#39;].to_numpy()
  40. z = (records.iloc[1:].values-records.iloc[:-1]).loc[:,&#39;Acc.Z&#39;].to_numpy()
  41. ii = np.linspace(i.start, i.stop);
  42. tckx0 = splrep(i, x, s=0)
  43. tckx = splrep(i, x, s=50)
  44. tcky = splrep(i, y, s=50)
  45. tckz = splrep(i, z, s=50)
  46. fig = plt.figure()
  47. ax = fig.add_subplot(projection=&#39;3d&#39;)
  48. ax.plot(x, y, z, &#39;ko&#39;, label=&quot;true data&quot;)
  49. ax.plot(BSpline(*tckx)(ii),BSpline(*tcky)(ii),BSpline(*tckz)(ii),
  50. color=&#39;green&#39;, label=&quot;your interpolation&quot;)
  51. # spline interpolation of a 3D curve
  52. tck, u = splprep([x, y, z], s=2)
  53. ii = np.linspace(0, 1)
  54. xs, ys, zs = splev(ii, tck)
  55. # spline interpolation of a 1D curve
  56. a_x = records[&quot;Acc.X&quot;].to_numpy()[:-1]
  57. a_y = records[&quot;Acc.Y&quot;].to_numpy()[:-1]
  58. a_z = records[&quot;Acc.Z&quot;].to_numpy()[:-1]
  59. # color by magnitude of acceleration
  60. a = np.sqrt(a_x**2 + a_y**2 + a_z**2)
  61. tcka = splrep(np.linspace(0, 1, len(a)), a, s=0)
  62. parameter = splev(ii, tcka)
  63. ax.plot(xs, ys, zs, &#39;r.&#39;, label=&quot;new interpolation&quot;)
  64. def get_segments(x, y, z):
  65. points = np.ma.array([x, y, z]).T.reshape(-1, 1, 3)
  66. return np.ma.concatenate([points[:-1], points[1:]], axis=1)
  67. line = Line3DCollection(get_segments(xs, ys, zs), cmap=&quot;magma&quot;, array=parameter)
  68. ax.add_collection(line)
  69. fig.colorbar(line, label=&quot;acceleration&quot;)
  70. ax.legend()
  71. plt.show()

如何根据权重为3D B样条上色

huangapple
  • 本文由 发表于 2023年6月9日 07:17:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76436270.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定