Play a Video Frame-by-Frame Using VideoReader?

53 views (last 30 days)
Matt
Matt on 17 Jun 2015
Commented: Image Analyst on 17 Jun 2015
Hello -
I have been working with a GUI in which I have a video, whose data is read through VideoReader, which I would like to be played frame-by-frame using a "for"-loop. The reason for playing it frame-by-frame is that I also have a data file which I would like to plot alongside the video in real time. Right now I am simply performing a test to see if a "for"-loop can be used to play a video frame-by-frame, however, I do not seem to have had much success. I have included the test code below. I am not that familiar with VideoReader or GUIs, hence the difficulty. Any ideas on what I might be doing wrong?
% --- Executes on button press in PlayVideo.
function PlayVideo_Callback(hObject, eventdata, handles)
% hObject handle to PlayVideo (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
videofile = handles.videofile;
nFrames = handles.nFrames;
MOV = VideoReader(videofile);
axes(handles.VideoBox);
for i = 1:nFrames
img = read(MOV,1);
image(img);
end
guidata(hObject, handles);

Answers (1)

Image Analyst
Image Analyst on 17 Jun 2015
After the call to image(), put these lines:
drawnow; % Force immediate repainting of screen.
pause(0.25); % Pause a fraction of a second to slow down the video.
  2 Comments
Matt
Matt on 17 Jun 2015
Thanks for replying. I'm curious: why is the pause statement necessary? I was actually able to figure out what was going on with my overall code (not the test one I had referenced previously), which plays the video and plots the data at the same time. There is a pause statement included within that "for"-loop, however, when I comment it out, neither the video nor animation of the data play. I wasn't sure if there was, like in your own recommendation, some particular usefulness to incorporating a pause statement? Here's the master code I got working. Note the pause statement - when it's commented out, the code goes kaput.
% --- Executes on button press in Playbutton.
function Playbutton_Callback(hObject, eventdata, handles)
% hObject handle to Playbutton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
videofile = handles.videofile;
scanrate = handles.scanrate;
frame_rate = handles.frame_rate;
Time = handles.Time;
Chamber_P = handles.Chamber_P;
TimeScale = scanrate/frame_rate;
handles.TimeScale = TimeScale;
MOV = VideoReader(videofile); %Video performs better when moved outside for loop.
for i = 1:1:200
Img = read(MOV,i);
axes(handles.VideoBox)
image(Img);
axis off;
set(gca,'Visible','off')
axes(handles.DataPlotBox)
plot (Time, Chamber_P,'LineWidth',2);
xlabel ('Time [s]','LineWidth',3,'FontSize',12,'FontWeight','Bold')
ylabel ('Chamber Pressure [psia]','LineWidth',3,'FontSize',12,'FontWeight','Bold')
set(gca,'FontSize',12,'FontWeight','Bold')
grid on;
line([Time(round(i*TimeScale)) Time(round(i*TimeScale))],[0 Chamber_P(round(i*TimeScale))],[1 1],'LineStyle','--','LineWidth',3,'Color','red');
pause(0) %Not entirely sure why the GUI cannot function without it
end
guidata(hObject,handles)
So there you have it. Even incorporating an essentially useless pause statement makes a difference. Any insight into that? Thanks again!
Image Analyst
Image Analyst on 17 Jun 2015
The pause is not necessary. It's just to slow it down. It's the drawnow that is necessary, though a long enough pause gives the same effect. Essentially the image() function sends a "message" to the graphics card (video adapter) to refresh the screen with the current image. But the operating system in a multitasking system can decide on what order to process messages. When you have a tight, intensive loop, it might decide that that loop takes precedence over other things like screen refreshes, disk I/O, playing music, etc. What was happening was that it was screaming through the loop and the screen refresh messages were piling up, essentially getting ignored until it thought it had enough time to act upon them, which was only after your loop had finished, then it did them all so fast you didn't see any of them except the final one. Putting a drawnow in there will force it to not continue until the screen has been refreshed/repainted/updated. So now you will see them all. However depending on how fast the loop is and how many frame there are, you might not see much. For example, it might display all 10 frames in a quarter of a second which is too fast for you to see. The pause() makes each image be visible for the specified amount of time before the loop continues on to the next image.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!