How can you stop live video from playing in the GUI?

7 views (last 30 days)
Hi, I have code that displays video footage from a camera in a GUI. I am unable to stop this video once it starts, the code that I copied to get the image to display tells the user to close the image simply by clicking on the "x" button on the top right corner. The problem with this, is that the "x" box is not visible once the image runs inside my GUI.
Most attempts either are ignored or cause matlab to freeze/hang. I believe a loop is running when I try to close the video and it simply ignores the close request.
disp('iCam Live Mode Preview')
PrepareAcquisition()
% init system
disp('Initialising Camera');
ret=AndorInitialize('');
CheckError(ret);
disp('Configuring Acquisition');
[ret]=CoolerON(); % Turn on temperature cooler
CheckWarning(ret);
[ret]=SetAcquisitionMode(5); % Set acquisition mode; 5 for RTA
CheckWarning(ret);
[ret]=SetExposureTime(0.02); % Set exposure time in second
CheckWarning(ret);
[ret]=SetReadMode(4); % Set read mode; 4 for Image
CheckWarning(ret);
[ret]=SetTriggerMode(10); % Set Software trigger mode
useSoftwareTrigger = true;
if ret == atmcd.DRV_INVALID_TRIGGER_MODE
disp('Software trigger not available, using Internal trigger instead')
SetTriggerMode(0); % Set internal trigger mode
useSoftwareTrigger = false;
end
CheckWarning(ret);
[ret]=SetShutter(1, 1, 0, 0); % Open Shutter
CheckWarning(ret);
[ret,XPixels, YPixels]=GetDetector; % Get the CCD size
CheckWarning(ret);
[ret]=SetImage(1, 1, 1, XPixels, 1, YPixels); % Set the image size
CheckWarning(ret);
disp('Starting Acquisition');
[ret] = StartAcquisition();
CheckWarning(ret);
I = zeros(YPixels,XPixels);
h = imagesc(I);
colormap(gray);
warndlg('To Abort the acquisition close the image display.','Starting Acquisition');
while(get(0,'CurrentFigure'))
if useSoftwareTrigger == true
[ret] = SendSoftwareTrigger();
CheckWarning(ret);
[ret] = WaitForAcquisition();
CheckWarning(ret);
end
[ret, imageData] = GetMostRecentImage(XPixels * YPixels);
CheckWarning(ret);
if ret == atmcd.DRV_SUCCESS
%display the acquired image
I=flipdim(transpose(reshape(imageData, XPixels, YPixels)),1);
set(h,'CData',I);
drawnow;
end
end
disp('Acquisition Complete! Cleaning Up and Shutting Down');
[ret]=AbortAcquisition;
CheckWarning(ret);
[ret]=SetShutter(1, 2, 1, 1);
CheckWarning(ret);
[ret]=AndorShutDown;
CheckWarning(ret);
I tried to use the last 6 or 7 lines of this code as a separate "stop" button but this occurs once pressed, most of the time I cant even open the main matlab window to see due to it hanging...
Can someone explain how I can close or stop this video without matlab crashing?
Thanks Johnny

Accepted Answer

Geoff Hayes
Geoff Hayes on 3 Sep 2014
Johnny - where is the above code taken from? Is it within a callback (push button?) from your GUI that kicks off the process of capturing images and displaying them in a figure, h, that is outside of your GUI? Or is it (more likely) that you are displaying the images within an axes widget on your GUI - which would explain why there is no x button to close.
So let's assume that you have start button that invokes the above code and starts the image acquisition, and that you have a stop button that will try to stop the process.
It is almost correct when you say that since the while loop is running, all other requests (like pressing the stop button) will be ignored. "Almost" because you have a drawnow command that should allow other processes to interrupt the current one (see callback sequencing and interruption for details). So pressing a stop button should allow us to exit the while loop if we change a couple of things. I'm assuming that the interruptible property of the start button is on (which is the default setting).
In the above code, just before the while loop starts add the following lines and change the condition in the loop
% create a data field within handles to say that we've started the
% image acquisition
handles.imgAcqStarted = 1;
% save the field to the handles structure
guidata(hObject,handles);
% condition on this field being one
while handles.imgAcqStarted==1
% get the most recent copy of handles
handles = guidata(hObject);
% etc., as before
end
So we will continue to do the image acquisition until told otherwise. We need to get the updated copy of handles at each iteration because it is the stop button that will update this object, and in particular the imgAcqStarted flag. In the stop button callback do
function stop_Callback(hObject, eventdata, handles)
fprintf('trying to stop...\n');
% stop the image acquisition
handles.imgAcqStarted = 0;
% save the field to the handles structure
guidata(hObject,handles);
So when the stop button is pressed, the above code should be invoked. The imgAcqStarted will now be zero, and when the other callback resumes, the while loop condition should evaluate to false, and we will exit the loop.
The above code should help provided that we always call the drawnow function. However, this isn't always the case as it is only called when ret == atmcd.DRV_SUCCESS. So we will need to handle the case where this isn't a success. Just change this block of code to
if ret == atmcd.DRV_SUCCESS
%display the acquired image
I=flipdim(transpose(reshape(imageData, XPixels, YPixels)),1);
set(h,'CData',I);
drawnow;
else
pause(0.001);
end
Adding a short pause will allow this callback to be interrupted by the stop button callback, and so the image acquisition should end gracefully.
One "gotcha" that I can think of is what happens if the user closes the GUI (hits the x). How do we instruct the start button callback to stop? We can do something similar to the stop button, but it does get a little kludgy. For your GUI/figure, create a CloseRequestFcn callback and add the following code (in this case, my GUI/figure name (or tag) is figure1)
% --- Executes when user attempts to close figure1.
function figure1_CloseRequestFcn(hObject, eventdata, handles)
% hObject handle to figure1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
if handles.imgAcqStarted==1
handles.imgAcqStarted = 2;
guidata(hObject,handles);
else
delete(hObject);
end
In the above, if the image acquisition has started (so its integer value is one) then we set this flag to two (so that we exit the while loop) and save the change to the handles structure. If image acquisition has not been started, then we just delete the figure and it will close gracefully.
So if the flag/indicator changes to two, then the start button callback resumes and will exit the while loop since this flag is no longer one. The acquisition will end gracefully but we still need to close the figure. Add the following line to the end of your start button callback
if handles.imgAcqStarted==2
delete(handles.figure1);
end
This should then delete the GUI/figure, hopefully without errors. If I knew more about how the image acquisition worked, I would suggest replacing some of the above with a timer that would periodically fire and grab the next image. You may still be able to do this, but I'm not sure how often you wish to acquire new images and whether a timer can be fast enough.
Try the above and see what happens!
  5 Comments
Jonathan O'Neill
Jonathan O'Neill on 5 Sep 2014
Thanks Geoff your code did the trick, all is good now!

Sign in to comment.

More Answers (0)

Categories

Find more on Startup and Shutdown in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!