我正在尝试使用Shady来呈现一系列图像帧。我从另一台机器控制流程,所以我首先指示运行Shady的机器呈现第一帧,然后再运行其余的帧。我创建了一个World实例,并附加了一个动画回调函数。在这个回调中,我监听来自另一台机器的通信(使用UDP)。首先,我收到一个加载给定序列(存储为numpy数组)的命令,然后我就这样做了
def loadSequence(self, fname):
yy = np.load(fname)
pages = []
sz = yy.shape[0]
for j in range(yy.shape[1]/yy.shape[0]):
pages.append(yy[:, j*sz:(j+1)*sz])
deltax, deltay = (self.screen_px[0] - sz) / 2, (self.screen_px[1] - sz) / 2
if (self.sequence is None):
self.sequence = self.wind.Stimulus(pages, 'sequence', multipage=True, anchor=Shady.LOCATION.UPPER_LEFT, position=[deltax, deltay], visible=False)
else:
self.sequence.LoadPages(pages, visible=False)当我收到显示第一帧的命令时,我会这样做:
def showFirstFrame(self, pars):
self.sequence.page = 0 if (pars[0] == 0) else (len(self.sequence.pages) - 1)
self.sequence.visible = True但是现在我该怎么做才能让其他的帧被显示呢?在我看到的示例中,s.page被设置为时间的函数,但我需要显示所有帧,而不考虑时间。所以我想要做的事情是这样的:
def showOtherFrames(self, pars, ackClient):
direction, ack = pars[0], pars[2]
self.sequence.page = range(1, len(self.sequence.pages)) if (direction == 0) else range(len(self.sequence.pages)-2, -1, -1)但这行不通。或者,我想定义一个以t为参数的函数,但忽略它,而使用保存在全局变量中的计数器,但我想知道这样做的正确方法是什么。
发布于 2019-05-31 01:37:14
当您将s.page设置为动态属性时,分配给它的函数必须接受一个参数(t),但在定义该函数时,您仍然可以只使用空间中的任何变量,甚至不使用时间参数。
所以,举个例子,你可以做一些简单的事情:
w = Shady.World(...)
s = w.Stimulus(...)
s.page = lambda t: w.framesCompleted这会将page属性设置为当前帧计数。这听起来可能对你的问题很有用。
发布于 2019-05-31 01:55:03
您的全局变量思想是实现此目的的一种非常有效的方法。或者,因为看起来像是将事物定义为您自己的自定义类的实例的方法,所以您可以使用实例方法作为动画回调和/或动态属性值-然后,使用self的属性而不是真正的全局变量是有意义的
import Shady
class Foo(object):
def __init__(self, stimSources):
self.wind = Shady.World()
self.stim = self.wind.Stimulus(stimSources, multipage=True)
self.stim.page = self.determinePage # dynamic property assignment
def determinePage(self, t):
# Your logic here.
# Ignore `t` if you think that's appropriate.
# Use `self.wind.framesCompleted` if it's helpful.
# And/or use custom attributes of `self` if that's
# helpful (or, similarly, global variables if you must).
# But since this is called once per frame (whenever the
# frame happens to be) it could be as simple as:
return self.stim.page + 1
# ...which is indefinitely sustainable since page lookup
# will wrap around to the number of available pages.
# Let's demo this idea:
foo = Foo(Shady.PackagePath('examples/media/alien1/*.png'))
Shady.AutoFinish(foo.wind)等同于这个简单的示例,您可以在更通用的动画回调中使用语句self.stim.page += 1 (以及其他任何逻辑)。
另一个用于逐帧动画的有用工具是对python的生成器函数的支持,即包含yield语句的函数。工作示例包含在python -m Shady demo precision和python -m Shady demo dithering中。
它也可以在StateMachine中完成,这始终是我对这些事情的首选答案:
import Shady
class Foo(object):
def __init__(self, stimSources):
self.wind = Shady.World()
self.stim = self.wind.Stimulus(stimSources, multipage=True)
foo = Foo(Shady.PackagePath('examples/media/alien1/*.png'))
sm = Shady.StateMachine()
@sm.AddState
class PresentTenFrames(sm.State):
def ongoing(self): # called on every frame while the state is active
foo.stim.page += 1
if foo.stim.page > 9:
self.ChangeState()
@sm.AddState
class SelfDestruct(sm.State):
onset = foo.wind.Close
foo.wind.SetAnimationCallback(sm)
Shady.AutoFinish(foo.wind)https://stackoverflow.com/questions/56382543
复制相似问题