imshow and Scatter in GUIDE
Show older comments
Hello everybody, I have lost many hours and I can not find the problem, if someone can help me, I thank you immensely.
I have a program that shows an image at the beginning, then pressing a key, refresh the image (constantly), pressing another key, displays a new image. I'm working with imshow and Scatter, but apparently, they do not relate well, because when I present first the imshow image, the hScatter variants cease to exist and error appears.
this is the initialization:

and this is the Loop:

when i press first "state_3d_view" everything is OK, but if i press "state_3d_view" and then "state_depth_view" and again "state_3d_view" appear the below error!!
i know that the problem is the imshow, because i already commented "set(imshow(depth,[0 outOfRange]),'CData',depth);" and the program and variables works weel.
the error:

Thank you for all the help you can offer.
Answers (2)
Calling imshow can delete the previous axes handle (which is your handles.axes1 and thus your hScatter too).
The following examples shows how imshow deletes handles.
a = axes;
b = imshow(ones(100), 'parent', a); %Show white image
imshow(zeros(100)); %Show black image, BUT deletes previous handles!
a =
handle to deleted Axes
b =
handle to deleted Image
To avoid deleting handles, directly change 'CData' of the image handle.
a = axes;
b = imshow(ones(100), 'parent', a); %Show white image
set(b, 'CData', zeros(100)); %Show black image, but no handles are deleted
So in your code, instead of this:
set(imshow(depth, [0 outOfRange]), 'CData', depth) %Which deletes hScatter when imshow is called.
try this (assuming the image handle is named ImHandle):
set(ImHandle, 'CData', depth) %Doesn't delete any handle
You can also use two separate handles on the GUI, like handles.axes1 and handles.axes2. Store the scatter on handles.axes1 ( using scatter(handles.axes1, ...) ), and image on handles.axes2 ( using imshow(...,'Parent', handles.axes2) ). If you want the image/scatter to be at the same place, use the handles.axesN.Visible = 'on' or 'off' to show or hide the the correct axes in the GUI.
11 Comments
Walter Roberson
on 12 Sep 2017
Right. In particular imshow() looks at the axes position to determine whether it is in the default position. If it is, then it sets the figure NextPlot to 'replace', which triggers the next high level graphics call to delete the axes and all of its contents.
You can avoid this by:
- using a non-default axes position; Or
- calling "hold on" after doing the imshow(); this will set the figure NextPlot property as well as the axes NextPlot property, and if you then "hold off" then that will change the axes NextPlot property but leave the figure NextPlot property set to not delete the axes; Or
- like Donald says, set the CData property of the image to the new content instead of calling imshow() with the new content. This has the advantage of being more efficient too.
Márcio Marques
on 12 Sep 2017
Hi Marcio. Just read the message. So these images are getting pretty big - copy paste the code and use the {} Code button to make it neat.
Use the following example as a reference. This example implements Walter's suggestion of using hold on right before you create the first image handle.
clear, clc, close all
handles.axes1 = axes;
hScatter = scatter(handles.axes1, 50, 50, 100, 'fill', 'or');
hold on
hImage = imshow([], [0 1], 'Parent', handles.axes1); %Create an empty image where scatter plot is.
hold off
for j = 1:10
%Update your CData
hImage.CData = rand(100); %Replace rand(100) with your depth
%Update your x, y, z data
hScatter.XData = 50 + 5*j;
hScatter.YData = 50 + 5*j;
hScatter.ZData = 1;
pause(0.5) %Just so you can see what's going on
end
Run this script by itself. Hope this helps to debug your code.
Márcio Marques
on 12 Sep 2017
OCDER
on 13 Sep 2017
Are you drawing a scatter plot separately from the axes? Sorry, thought you wanted to overlay a tracking dot over an image using scatter.
In this case... Do you have another axes handle in your GUI? Like handles.axes2 where you want to show your image and handles.axes1 where you want to draw scatter plots?
If so, then change the parent handle in imshow to the other axes like this:
hImage = imshow([], [0 1], 'Parent', handles.axes2);
Márcio Marques
on 13 Sep 2017
OCDER
on 13 Sep 2017
Ok, so you want to replace the image with the plot depending on what the user chose? Try this example function, and look at what's going on. Every time you switch between imshow and scatter, you have to replace the children handle under handles.axes1. Also, in your showPointCloud function, have it so you can specify which axes handle to draw to. I've commented the code for you.
This is all I can help you with as others need help, but hope this give you a good idea of how to debug your code. Good luck!
function debug_this
handles.axes1 = axes;
state_view = 1; %This is the state_depth_view and state_3d_view combined into one for simplicity.
if state_view == 1 %Place a for loop inside the statement to prevent checking if's alot, and remaking handle
%Create an empty image under handles.axes1, before the for loop
hImage = imshow([], [0 1], 'Parent', handles.axes1);
for k = 1:10
depth = rand(100);
hImage.CData = depth;
pause(0.5)
end
end
state_view = 2;
if state_view == 2
%Modify showPointCloud to take the parent handle as an input. See below for how to edit showPointCloud
pc = [1, 2];
hScatter = showPointCloud(pc, 'VerticalAxis', 'Y', 'Parent', handles.axes1);
for k = 1:10
%Update your x, y, z data
hScatter.XData = 50 + 5*k;
hScatter.YData = 50 + 5*k;
hScatter.ZData = 1;
pause(0.5)
end
end
function Sx = showPointCloud(pc, varargin)
%Do some input parsing
if nargin >= 4
ParentHandle = varargin{4};
else
ParentHandle = gca;
end
%... your code
Sx = scatter(ParentHandle, pc(:, 1), pc(:, 2)); %HERE, make sure to specify the axes to use.
Márcio Marques
on 13 Sep 2017
Try making a completely different axes handle, handles.axes1 and handles.axes2, in your GUI.
Then see if you can draw scatter on handles.axes1.Children, and draw images on handles.axes2.Children.
Then play around with the "Visible" handle field to show either the scatter or the image in the same position.
Remember, creating a new handle will delete/replace the previous handle and data, so figure out when you do/do not want data to be replaced.
Beyond this, it'll be hard to figure out how your GUI is structured to help you further.
Also, this thread is getting too long and we're answering a different question now. Try re-asking the question "In a GUI, how to switch between a scatter and imshow in the same axes without replacing handles & data?" Upload your .fig and .m file you're using. There might be others who've done something similar, or wants to do something similar, to what you're trying.
Hope this helps!
Márcio Marques
on 14 Sep 2017
Márcio Marques
on 12 Sep 2017
0 votes
2 Comments
Walter Roberson
on 12 Sep 2017
It makes it more difficult for us to fix the code when you post images of the code instead of the code itself.
Before the loop, initialize a loop counter to 0.
Inside the loop, add 1 to the loop counter.
Replace the call
ter = imshow(depth, [0 OutOfRange]);
set(ter, 'CData', depth)
with
if loop_counter == 1
ter = imshow(depth, [0 OutOfRange]);
else
set(ter, 'CData', depth');
end
Márcio Marques
on 12 Sep 2017
Categories
Find more on Creating, Deleting, and Querying Graphics Objects 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!

