getframe produces greater image

Hello,
I am using getframe() to read out axes that show an image. For example an 120x90 image. But the image I get from the getframe() function has a size of 121x91. There is a small white border. How can I turn that off? Btw I am showing the image without axis.

 Accepted Answer

Jan
Jan on 29 Aug 2013
Edited: Jan on 29 Aug 2013
I do not understand your explanations. What is "the number of the current frame"? You cannot store a number "in a handle", because a handle is a kind of pointer to a HG object and created by Matlab. You mean a struct called "handle", but this is a confusing formulation. What do you think is stored in handle.frame_xy?
Again, please show us the code. It sounds like you forgot to store the modified handles struct. Then this might help:
function TheButtonCallback(hObject, EventData)
handles = guidata(hObject); % Get handles struct from figure
handles.frame_xy = how ever you obtain it
guidata(hObject, handles); % Store modified struct in the figure
Then the modified handles struct can be obtained by guidata again. If this is your problem, sharing data between callbacks is your main problem, and the extremely confusing decision of TMW to call the struct for storing figure related information "handles". Use the Search field of this forum and look form "share gui" to find many related threads: http://www.mathworks.com/matlabcentral/answers/?term=share+gui

3 Comments

okay, thank you for your answer but I still don't know what to do... I wrote an easy example to point out the problem.
I created a GUI with 2 static text and 2 pushbuttons. In the OpeningFcn I created
handles.counter = 1
With the first button I want to start a loop: (callback fcn pushbutton1)
while handles.counter < 3;
set(handles.text1, 'string', num2str(handles.counter));
drawnow;
end
set(handles.text2, 'string', 'ende');
So the first textfield shows the counter. With the second pushbutton I want to increase the counter: (callback fcn pushbutton2)
handles.counter = handles.counter+1;
guidata (hObject, handles);
What do I have to do to let this work?
These are only parts of the code and if the complete code contains the necessary further commands, everything is fine. But you do not show us the additional lines, such that we must guess, what is missing.
Please post the complete relevant part of the code.
Running a while loop, which does not perform anything, is a waste of time. If actions are triggered by the callback of another button, you can omit the loop completely and insert the action in the callback.
Adrian
Adrian on 29 Aug 2013
Edited: Adrian on 29 Aug 2013
it is the whole code and the
handles = guidata(hObject); % Get handles struct from figure
command is missing, thats why the loop never ends and the counter doesn't work. Thank you Jan Simon and Image Analyst!!
while handles.counter < 3;
set(handles.text1, 'string', num2str(handles.counter));
drawnow;
handles = guidata(hObject);
end
set(handles.text2, 'string', 'ende');

Sign in to comment.

More Answers (2)

Image Analyst
Image Analyst on 29 Aug 2013
Just get the image itself, like what you put into the axes when you called image(), imshow(), or imagesc(). I mean, you have it, since you put it in there, right?

9 Comments

No, I have a while loop showing a movie on an axes. If I push the "Snap" button (drawnow in the loop) you get the current frame of the movie. This frame I display in another axes. When the loop goes on, the handles are reseted to an older status. That's why I lose "the image".
Did you try various axis options like axis off, axis image, etc.?
Adrian
Adrian on 29 Aug 2013
Edited: Adrian on 29 Aug 2013
axis off yes, axis image not yet. I am just looking for a way not to lose the handles. maybe you have a solution for me. I want to hold the handle of the interrupting callback function instead of them from the function with the loop. That would solve the problem as well.
I've never tried to grab a screenshot off a video as it's playing "live." Maybe you could use VideoReader to extract a frame at a time and use imshow() to display it then capture the last frame extracted when the user clicks the button. Alternatively, you can use imcrop to cut off the small white border. By the way, I don't know what you mean by "lose the handles."
Jan
Jan on 29 Aug 2013
Edited: Jan on 29 Aug 2013
I still do not get the problem. What exactly does "I have a while loop showing a movie on an axes" mean? If you show the move image by image, the image data are available directly. Then using GETFRAME is an unnecessary indirection. Please show us the code.
Adrian
Adrian on 29 Aug 2013
Edited: Adrian on 29 Aug 2013
okay let me try to explain: I have a function with a while loop showing frames from a '.avi' file. I used that loop because with the 'movie()'-function I were not able to grab single frames by user click. In my case the callback function of the user-click interrupts the loop. I know the number of the current frame, so I can store it in a handle (for example: handle.frame_xy) and display it (for example: imshow(handle.frame_xy, 'parent', handles.axes_xy) ). When the callback completes the program returns to the loop. When it returns, matlab restores the handles. (for example imshow(handle.frame_xy) would cause an error now because the frame_xy does not exist)
added the code below
See my answer.
You need to call guidata immeidately after you attach/update handles.frame_xy, otherwise anything you attached to handle inside your function with the loop will not be available in it's current/updated form to the function with the button that saves the current image to disk.

Sign in to comment.

Adrian
Adrian on 29 Aug 2013
Edited: Adrian on 29 Aug 2013
Here is a part of the function with the loop:
for count = 1:videoObj.NumberOfFrames
handles.count=count;
start = clock;
imshow(handles.mov(count).cdata, 'parent', handles.LiveCam_axes);
drawnow
guidata(hObject, handles);
time = etime(clock, start);
while (time < 1/FrameRate)
time = etime(clock, start);
end
end
And here is the interesting part of the callback that interrupts the loop:
handles.Snapshot1 = handles.mov(handles.count).cdata;
imshow(handles.Snapshot1, 'parent', handles.Snapshot1_axes);
handles.Snapshot1 gets lost if the callback function is completed and the loop continiues.

3 Comments

Yes, that's true - it will be lost unless you take care to retain it. Why do you need Snapshot1 anyway? You can either pass handles back in the output argument list, or call guidata() right after you attach Snapshot1 to handles.
Adrian
Adrian on 29 Aug 2013
Edited: Adrian on 29 Aug 2013
Could you give me an example how that would look like for one of your two options.
Jan
Jan on 29 Aug 2013
Edited: Jan on 29 Aug 2013
while (time < 1/FrameRate), time = etime(clock, start); end is a brute waste of time. A timer would be smarter and more flexible.
As I have written already: If you want to share the handles struct with other callback, store it by guidata:
handles.count=count;
guidata(hObject, handles);
...
Then you can obtain the current value by:
handles = guidata(hObject);
The problem is that the updated handles struct is contained in the local copy in the workspace of the corresponding function. But each function, here each callback, has its own workspace and changes in one workspace do not propagate magically to others.
Please take the time and follow my suggestion to search in the forum for methods to share variables between callbacks. It has been discussed such often, that it is worth to use the history of this forum instead of asking new questions.

Sign in to comment.

Asked:

on 29 Aug 2013

Community Treasure Hunt

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

Start Hunting!