动画+平滑地插值矩阵之间的变化

6

I have a matrix of points like:

import numpy as np
import seaborn as sns; sns.set()
import matplotlib.pyplot as plt
%matplotlib inline

originalPoints = np.asarray([[1,2,3,4,5,6],[2,4,6,8,10,12]])
newPoints = np.asarray([[1,2,3,4,5,6],[2,4,6,8,10,12]]) + 20
plt.scatter(originalPoints[0,:],originalPoints[1,:], color='red');
plt.scatter(newPoints[0,:],newPoints[1,:], color='blue');

这给了我:

enter image description here

我正在尝试生成一个gif/动画,展示点沿着某个平滑的路径从红色到蓝色移动。我一直在尝试使用类似于这里讨论的方法 和scipy的插值方法,但我似乎无法弄清楚。

任何帮助都将是极好的。

奖励:也适用于3D的解决方案

编辑:为了明确,我想要的是每个蓝点沿着某个非线性平滑路径移动以达到红点。请注意 - 上面的示例是虚构的。实际上只有一堆蓝点和一堆红点。考虑在两个不同的散点图之间进行动画处理。


你能具体一些吗?你所说的“展示点沿着某个平滑路径从红色到蓝色移动”的意思是什么?有什么问题出现了吗? - PrestonH
此外,您会在哪里添加一个维度? - fuglede
@PrestonH 我在上面加了一个编辑。 - user79950
@fuglede - 额外的维度将存在于点本身。 - user79950
1个回答

18
您可以在每对点之间创建线性路径; 结合 matplotlib.animation.FuncAnimation 使用会像这样。
import matplotlib.animation as animation

def update_plot(t):
    interpolation = originalPoints*(1-t) + newPoints*t
    scat.set_offsets(interpolation.T)
    return scat,

fig = plt.gcf()
plt.scatter(originalPoints[0,:],originalPoints[1,:], color='red')
plt.scatter(newPoints[0,:],newPoints[1,:], color='blue')
scat = plt.scatter([], [], color='green')
animation.FuncAnimation(fig, update_plot, frames=np.arange(0, 1, 0.01))

两点之间的线性路径

编辑:现在修改了问题,要求使用非线性插值;将update_plot替换为

noise = np.random.normal(0, 3, (2, 6))
def update_plot(t):
    interpolation = originalPoints*(1-t) + newPoints*t + t*(1-t)*noise
    scat.set_offsets(interpolation.T)
    return scat,

你会得到以下内容

两点之间的荒谬路径

编辑#2:关于下面评论中颜色插值的查询,您可以通过matplotlib.collections.Collection.set_color来处理;具体来说,用上面的update_plot替换。

def update_plot(t):
    interpolation = originalPoints*(1-t) + newPoints*t + t*(1-t)*noise
    scat.set_offsets(interpolation.T)
    scat.set_color([1-t, 0, t, 1])
    return scat,

我们最终得到的是:

使用颜色进行插值

关于“奖励”的问题:3D情况大多类似;
a = np.random.multivariate_normal([-3, -3, -3], np.identity(3), 20)
b = np.random.multivariate_normal([3, 3, 3], np.identity(3), 20)

def update_plot(t):
    interpolation = a*(1-t) + b*t
    scat._offsets3d = interpolation.T
    scat._facecolor3d = [1-t, 0, t, 1]
    return scat,

fig = plt.figure()
ax = fig.gca(projection='3d')
ax.scatter(a[:, 0], a[:, 1], a[:, 2], c='r')
ax.scatter(b[:, 0], b[:, 1], b[:, 2], c='b')
scat = ax.scatter([], [], [])
ani = animation.FuncAnimation(fig, update_plot, frames=np.arange(0, 1, 0.01))
ani.save('3d.gif', dpi=80, writer='imagemagick')

3D example

关于下面评论中如何逐步完成此操作的编辑:可以通过直接在update_plot中加入路径组合来实现。

a = np.random.multivariate_normal([-3, -3, -3], np.identity(3), 20)
b = np.random.multivariate_normal([3, 3, 3], np.identity(3), 20)
c = np.random.multivariate_normal([-3, 0, 3], np.identity(3), 20)

def update_plot(t):
    if t < 0.5:
        interpolation = (1-2*t)*a + 2*t*b
        scat._facecolor3d = [1-2*t, 0, 2*t, 1]
    else:
        interpolation = (2-2*t)*b + (2*t-1)*c
        scat._facecolor3d = [0, 2*t-1, 2-2*t, 1]
    scat._offsets3d = interpolation.T
    return scat,

fig = plt.figure()
ax = fig.gca(projection='3d')
ax.scatter(a[:, 0], a[:, 1], a[:, 2], c='r')
ax.scatter(b[:, 0], b[:, 1], b[:, 2], c='b')
ax.scatter(c[:, 0], c[:, 1], c[:, 2], c='g')
scat = ax.scatter([], [], [])
ani = animation.FuncAnimation(fig, update_plot, frames=np.arange(0, 1, 0.01))
ani.save('3d.gif', dpi=80, writer='imagemagick')

Example using path composition


谢谢@fuglede!你能发布你的完整工作代码吗?另外,我的意思更像是 - 沿着某个曲线,比如样条曲线之类的。 - user79950
线性路径既可以是曲线也可以是样条。此外,在.save('scatterplots.gif', dpi=80, writer='imagemagick')之外,这实际上是完整的工作代码。 - fuglede
嗯,好的,谢谢。我会试着使用你给我的东西。最后一个问题是,为了让我也能插值颜色,我需要创建一个相应的颜色映射吗? - user79950
此外,您能否在for循环/阶段中调用它?这样绿色首先朝向蓝色,然后朝向另一组点等等。 - user79950
对于第一个问题:不需要;我已经添加了一个示例,说明如何在红色和蓝色之间进行插值。对于第二个问题,我会相应地修改“update_plot”,检查“t”的值。 - fuglede
谢谢你,你帮了我很大的忙,我非常感激。 - user79950

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接