我正在使用MATLAB的PsychToolbox进行实验,我必须实时收集扫视信息,同时逐帧渲染视频 . 我遇到的问题是,考虑到视频和显示器的帧速率(~24fps),这意味着我有大约40ms的时间窗口来渲染查询并渲染我之前存储在内存中的每一帧 . 这很好,但是由于这个过程需要时间,所以通常意味着我有大约20ms的时间从头到尾一直在进行一次扫视 .
这是一个问题,因为当我对眼跳进行投票时,我通常在做什么(比如静止图像,只需要显示一次),我是等待一个固定的开始和结束,给出一致的轮询跟踪机,检测到观察者注视突然从一个点突然移动到另一个点
速度超过:35度/秒
和
加速度超过:9500度/秒^ 2
但是如果在渲染帧时(大部分时间)渲染帧的开始或者它的结束,那么它就不可能实时获取数据而不将渲染和轮询过程分成两个单独的MATLAB线程 .
我的代码(相关部分)看起来像这样:
while GetSecs-t.stimstart(sess,tc)<fixation_time(stimshownorder(tc))
x =evt.gx(1);
y =evt.gy(1);
pa = evt.pa(1);
x_vec = [x_vec; x];
y_vec = [y_vec; y];
pa_vec = [pa_vec; pa];
evta=Eyelink('NewestFloatSample');
evtype=Eyelink('GetNextDataType');
#%% Ideally this block should detect saccades
#%% It works perfect in still images but it can't do anything here
#%% since it conflicts the main for loop ahead.
if evtype==el.ENDSACC
sacdata=Eyelink('GetFloatData',evtype);
sac.startx(sess,tc,sacc)=sacdata.gstx;
sac.starty(sess,tc,sacc)=sacdata.gsty;
sac.endx(sess,tc,sacc)=sacdata.genx;
sac.endy(sess,tc,sacc)=sacdata.geny;
sac.start(sess,tc,sacc)=sacdata.sttime;
sac.end(sess,tc,sacc)=sacdata.entime;
sacc=sacc+1;
end
#%Main loop where we render each frame:
if (GetSecs-t.space(sess,tc)>lag(tc))
z = floor((GetSecs-t.space(sess,tc)-lag(tc))/(1/24))+1;
if z > frame_number
z = frame_number;
end
Screen('DrawTexture',win,stimTex{z});
Screen('Flip',win);
#DEBUG:
#disp(z);
#%disp(frame_number);
end
end
理想情况下,我想要一个MATLAB函数,可以在后端的一个单独的线程中独立渲染视频,同时仍然在主线程中轮询扫视 . 理想情况下是这样的:
#% Define New thread to render video
#% Some new function that renders video in parallel in another thread
StartParallelThread(1);
#%Play video:
Playmovie(stimTex);
#%Now start this main loop to poll for eye movements.
while GetSecs-t.stimstart(sess,tc)<fixation_time(stimshownorder(tc))
x =evt.gx(1);
y =evt.gy(1);
pa = evt.pa(1);
x_vec = [x_vec; x];
y_vec = [y_vec; y];
pa_vec = [pa_vec; pa];
evta=Eyelink('NewestFloatSample');
evtype=Eyelink('GetNextDataType');
if evtype==el.ENDSACC
sacdata=Eyelink('GetFloatData',evtype);
sac.startx(sess,tc,sacc)=sacdata.gstx;
sac.starty(sess,tc,sacc)=sacdata.gsty;
sac.endx(sess,tc,sacc)=sacdata.genx;
sac.endy(sess,tc,sacc)=sacdata.geny;
sac.start(sess,tc,sacc)=sacdata.sttime;
sac.end(sess,tc,sacc)=sacdata.entime;
sacc=sacc+1;
end
end
似乎运行Screen('Flip',win)命令所需的时间约为16ms . 这意味着如果在此间隔内发生任何跳视,我将无法检测或轮询它们 . 请注意,最后我有42ms(帧刷新率)减去16ms(查询和显示帧所需的时间),因此每帧总共约26ms的探测时间用于获取眼球运动并计算任何实际值时间处理 .
可能的解决方案可能是持续轮询凝视,而不是检查眼球运动是否是扫视 . 但是我仍然有一个问题就是没有捕获每帧大约三分之一的内容,只是因为加载它需要时间 .
1 回答
您需要重新组织代码 . 实现这项工作的唯一方法是了解翻转需要多长时间并了解下一个视频帧的提交时间 . 然后在循环中轮询眼动仪,直到您有足够的时间在下一个屏幕垂直空白之前执行绘图命令 .
你不能在matlab中做任何形式的可靠多线程