16 Psychtoolbox 帧计时

2018-06-12  本文已影响0人  花生_毛豆

之前讲过利用双 buffers 来快速呈现图像的原理。Psychtoolbox 采用 VBL Synchronization 的方式实现对图像呈现时间的精确控制。

这一次,主要说下这个方法在实验程序中的实现。

上次的练习中,是在屏幕的中间呈现了一个灰色的圆点,现在要求一秒后呈现一个红色的圆点。

有一些时间控制类的函数可以做到,但是 PTB 推荐采用指定在哪一帧翻转的方式来实现。

举例如下:

先做一些准备工作

sca;
close all;
clearvars;
PsychDefaultSetup(2);

screen = max(Screen('Screens'));
white = WhiteIndex(screen);
grey = white / 2;

% 下面 打开一个窗口,颜色设为白色
[win, rect] = PsychImaging('OpenWindow', screen, white);

% 获取每帧间的时间差
ifi = Screen('GetFlipInterval', win);

注意上面的例子中,通过 Screen('GetFlipInterval') 获取了显示器的刷新时间,一般来说,液晶显示器的刷新率为 60 hz ,可以据此估算,ifi 的值约为16.67 ms.

接下来,画一个灰色的圆点:

Screen( 'FillOval', win, grey, [ 1260, 700, 1300, 740] );
vbl = Screen('Flip', win);

这次,与上次的例子中,有一个不太一样的地方, " Flip " 之后,返回了一个值给 vbl. 这里,vbl 相当于一个标记,它标记了 " Flip " 动作完成的时间点。

大家查看下帮助,可以看到 Screen('Flip') 还可以传入更多的参数,其中 "when" 参数是这个任务的核心。when 可以指Flip 动作的翻转时间。

画了一个灰色的圆点以后,随着 Flip 动作,原先的灰色圆点也随之被清除。

现在画一个红色的圆点:

Screen( 'FillOval', win, [255 0 0], [ 1260, 700, 1300, 740]);

接着指定它在何时翻转。

Screen('Flip', win, vbl + (1 / ifi - 0.5) * ifi);

简单解释下它的原理:
先看这个式子: ( 1 / ifi - 0.5 ) * ifi ,它可以理解为 第 "1 / ifi + 1" 帧之后执行翻转动作。1 是指 1 秒,因为我们前面指定了 1 秒钟以后变为红色的点。

有点奇怪啊,为什么第"1 / ifi + 1" 之后执行翻转动作,在计算的时候要减 0.5 呢?这是因为执行程序需要时间,写成 " 1/ifi +1 "的话,程序有可能稍微滞后一些,这样就错过了那一帧的翻转,就变成了更之后的一帧进行翻转,这会带来误差。

为了避免这样的误差,如果需要在哪一帧翻转,就提前半帧执行动作,这样就可以保证它一定会在那一帧进行翻转。请结合教程13理解一下。

但是程序内部,它不是按照帧来完成动作的,它仍然是按照计时的。所以需要将帧转换成为时间。

所以 when 参数就变成了 "vbl + ( 1 / ifi - 0.5 ) * ifi" ,意味着在vbl 之后 ( 1 / ifi - 0.5 ) * ifi 时间执行翻转动作。

上一篇下一篇

猜你喜欢

热点阅读