Matplotlib FuncAnimation:如何使 3D 像素跟踪的先前轨迹变灰? [英] Matplotlib FuncAnimation: How to gray out previous trajectory of in 3D pixel tracking?

查看:105
本文介绍了Matplotlib FuncAnimation:如何使 3D 像素跟踪的先前轨迹变灰?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有3个列表,分别包含x坐标,y坐标和z坐标.我正在尝试跟踪3D空间中的位置.我使用以下代码:

I have 3 lists which contain the x cordinates, y coordinates and z coordinates respectively. I am trying to track the position in 3D space. I use the below code:

fig = plt.figure()
ax = p3.Axes3D(fig)
def update(num, data, line):
    
    line.set_data(data[:2, :num])
    line.set_3d_properties(data[2, :num])

N = 4000
d3d=np.array([xdata,ydata,zdata])

line, = ax.plot(d3d[0, 0:1], d3d[1, 0:1], d3d[2, 0:1], color='blue')
ax.set_xlim3d([2.0, -2.0])
ax.set_xlabel('X')

ax.set_ylim3d([2.0, -2.0])
ax.set_ylabel('Y')

ax.set_zlim3d([0.0, 4.0])
ax.set_zlabel('Z')
ani = animation.FuncAnimation(fig, update, N, fargs=(d3d, line), interval=10000/N, blit=False)
plt.show()

通过此操作,我可以成功地看到蓝色的轨迹.但是,我想以蓝色查看更新的轨迹,并希望将其上一个显示为灰色:

With this I can successfully see the trajectory in blue color. However, I want to see the updated trajectory in blue and want to gray out he previous one:

我尝试在更新函数中使用下面的内容,使上一行变灰:

I tried using below in update function so gray out he previous line:

def update(num, data, line):
    
    line.set_data(data[:2, :num])
    line.set_3d_properties(data[2, :num])
    if line is not None:
        line.set_color('gray')

但是这只会使整个轨迹变灰.任何帮助将不胜感激.

but this just grays out the whole trajectory. Any help would be appreciated.

推荐答案

更新
回想起来,我注意到我的第一次尝试是一种浪费的方法——蓝线仍然保留在内存中,我们只是再也看不到它们了(实际上,我们看到了——它们的颜色不是灰色而是灰蓝色).因此,我们最好跟踪绘制的线条并更改它们的颜色.

Update
I noticed in retrospect that my first attempt was a wasteful approach - the blue lines are still kept in the memory, we just don't see them anymore (actually, we do - their color was not grey but grey-blue). So, we better keep track of the plotted lines and just change their color.

import matplotlib.pyplot as plt
import matplotlib.animation as anim
import numpy as np

fig = plt.figure()
ax = fig.gca(projection="3d")

#random data
np.random.seed(12345)
d3d = np.random.random((3, 12))

line_list = []
#number of line segments to retain in blue before greying them out
line_delay = 4    

def init():
    ax.clear()
    #you can omit the fixed scales, then they will be automatically updated
    ax.set_xlim3d(0, 1)
    ax.set_ylim3d(0, 1)
    ax.set_zlim3d(0, 1)        

def update(i):
    #initializing the plot, emptying the line list 
    if not i:
        init()
        line_list[:] = []
    
    #set line color to grey if delay number is exceeded
    if len(line_list)>=line_delay:
        line_list[-line_delay].set_color("grey")
    
    #plot new line segment
    newsegm, = ax.plot(*d3d[:, i:i+2], "blue") 
    line_list.append(newsegm)

ani = anim.FuncAnimation(fig, update, init_func=init, frames = np.arange(d3d.shape[1]), interval = 300, repeat=True)
plt.show()

这种方法的另一个优点是我们可以轻松地对其进行调整以更好地表示数据 - 例如,如果我们有大量数据,我们可以使它们淡化并删除所有不可见的线条:

This approach also has the advantage that we can easily adapt it for better representation of the data - for instance, if we have a lot of data, we can make them fade and remove all invisible lines:

import matplotlib.pyplot as plt
import matplotlib.animation as anim
import numpy as np

fig = plt.figure()
ax = fig.gca(projection="3d")

#random data
np.random.seed(12345)
d3d = np.random.random((3, 40))

#defines the number of disappearing line segments
max_length = 20

line_list = []

def init():
    ax.clear()
    ax.set_xlim3d(0, 1)
    ax.set_ylim3d(0, 1)
    ax.set_zlim3d(0, 1)

def update(i): 
    if not i:
        init()
        line_list[:] = []   
             
    else:
        #if not the first line segment, change color to grey, 
        line_list[-1].set_color("grey")
        #then reduce gradually the alpha value for all line segments
        diff2max = max(0, max_length-len(line_list))
        [x.set_alpha((j+diff2max)/max_length) for j, x in enumerate(line_list)]
    
    #delete line segments that we don't see anymore to declutter the space
    if len(line_list)>max_length:
        del_line = line_list.pop(0)
        del_line.remove()    
        
    #plot new segment and append it to the list
    newsegm, = ax.plot(*d3d[:, i:i+2], "blue") 
    line_list.append(newsegm)

ani = anim.FuncAnimation(fig, update, init_func=init, frames = np.arange(d3d.shape[1]), interval = 300, repeat=True)
plt.show()

样本输出:

初步回答如果单独绘制线条,则可以用灰线覆盖之前的蓝线.

Initial answer If you plot the lines separately, you can overwrite the previous blue line with a grey line.

import matplotlib.pyplot as plt
import matplotlib.animation as anim
import numpy as np

fig = plt.figure()
ax = fig.gca(projection="3d")

#random data
np.random.seed(12345)
d3d = np.random.random((3, 10))

def init():
    ax.clear()
    #you can omit the fixed scales, then they will be automatically updated
    ax.set_xlim3d(0, 1)
    ax.set_ylim3d(0, 1)
    ax.set_zlim3d(0, 1)

def update(i): 
    if not i:
        init()
    else:
        ax.plot(*d3d[:, i-1:i+1], "grey") #plot old segment
            
    ax.plot(*d3d[:, i:i+2], "blue") #plot new segment

ani = anim.FuncAnimation(fig, update, init_func=init, frames = np.arange(d3d.shape[1]-1), interval = 300, repeat=True)
plt.show()

样本输出:

这篇关于Matplotlib FuncAnimation:如何使 3D 像素跟踪的先前轨迹变灰?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆