I'd like to plot some points over an image in a dialog.

조회 수: 7 (최근 30일)
Chris
Chris 2023년 1월 26일
댓글: Voss 2023년 2월 4일
I want to be able to select one point with a left-click, a second point with a right-click, but I'm running into all sorts of trouble.
This dialog calls nested function replot() on creation, and in the ButtonDownFcn() callback.
In this form, the image never shows up but the points do. If I un-comment the colormap line, everything looks right when the dialog is opened, but the image disappears again when the callback triggers.
To boot, I can't debug effectively because breakpoints inside replot() don't work.
The heck is going on? Alternatively, is there a better, lightweight way to accomplish this?
im = rgb2gray(imread('peppers.png'));
stats(1).Centroid = [260 260];
stats(2).Centroid = [350 260];
dHandle = cDialog(im,stats);
function d = cDialog(im, stats, d)
ddims = size(im).*1.5;
if nargin < 3
dp = [50 50 51+fliplr(ddims)];
else
dp = d.Position;
end
d = dialog('Units','pixels','Position', dp, ...
'Name','Confirm Selections');
ax = uiaxes('Parent',d,...
'Units','pixels',...
'Position',[25 10 dp([3,4])-25],...
'Visible','off');
ax.Title.String = 'Confirm or Select points (Left- & Right-click)';
% Show the current points
replot;
uiwait(d);
%%% Nested functions
function replot
hold(ax,"off")
image(im,'Parent',ax,'ButtonDownFcn',@clicked);
drawnow
hold(ax,"on")
% colormap(ax,parula);
pts = {stats(1).Centroid;stats(2).Centroid};
if ~isempty(pts{1})
scatter(ax,pts{1}(1),pts{1}(2),'bo','filled')
end
if ~isempty(pts{2})
scatter(ax,pts{2}(1),pts{2}(2),'ro','filled')
end
end
function clicked(~,event)
switch event.Button
case 1
stats(1).Centroid = event.IntersectionPoint([1 2]);
case 3
stats(2).Centroid = event.IntersectionPoint([1 2]);
otherwise
end
replot;
end
end
  댓글 수: 3
Jan
Jan 2023년 1월 28일
@Chris: Please do not use notifications to attract specific users. I've read your question before and do not understand, what you want to achieve and have no idea, what I could answer. Now I got your notification, read the question again, found out, that it does not contain new information and still cannot help you. So this was a waste of time.
Imagine what will happen, if all users send notification to some preferred members: They will drown in a pile of messages and this reduces their time to post answers in the forum. So please don't do this. Thank you.
Today I got 4 of such notifications. I've disabled the possibility to contact me over my profile page already for these reasons.
Chris
Chris 2023년 1월 28일
편집: Chris 2023년 1월 28일
My bad. I saw you had some know-how regarding axes stealing focus from an image, and this felt like it was in the same vein.
To perhaps word my question better for others:
I want this dialog to display an image and plot two point ROIs on top of the image. I want to allow the user to reposition the points using a left-click for the leftmost point, or a right-click for the right-most. However, the image fails to display. I can't use a breakpoint to figure out what's going on, because (I think) the dialog is interrupting the debugging process. I imagine that has something to do with how I have implemented the clicked callback.
The function as it sits is incomplete (for instance, it should probably return stats), but the script should be enough to reproduce the bug.

댓글을 달려면 로그인하십시오.

채택된 답변

Voss
Voss 2023년 2월 4일
편집: Voss 2023년 2월 4일
The reason it doesn't work when the "colormap(ax,parula)" line is commented-out:
  • dialog() creates a figure with an empty Colormap.
  • The image you create from im is an indexed image, i.e., the values in im are interpreted as indices into the current colormap.
  • In this case (indexing into an empty colormap), MATLAB apparently just silently renders nothing.
The reason it doesn't work when the "colormap(ax,parula)" line is uncommented:
  • parula() called with no inputs uses the size of the current figure's Colormap to determine the size of the colormap it returns. If there is no current figure, then it uses the size of the root property DefaultFigureColormap. (You can open parula.m in the editor to see this logic in the first few lines of code; I'm using R2016b, but I imagine parula.m in R2022b is substantially similar and maybe exactly the same.)
  • The figure created by dialog() has its HandleVisibility set to 'callback' by default.
  • The first time parula() is called (during initialization, within replot when replot is called within cDialog), it's not being called from within a callback, so the dialog figure is not considered the current figure (i.e., not returned by gcf()), so parula returns a 64-by-3 colormap (assuming there are no other figures around that are the current figure, and assuming that the root DefaultFigureColormap is of size 64, which is the default).
  • The second time parula() is called (within replot when replot is called within clicked), it is being called from within a callback (clicked), so the dialog figure is considered the current figure (i.e., is returned by gcf()), so parula() uses the size of its colormap - which is empty - and returns an empty colormap as well.
  • I'm not 100% sure about this reasoning because if it were true, then setting the HandleVisibility of the dialog figure to 'off' should cause parula() to return a 64-by-3 colormap each time (i.e., never find the dialog figure as the current figure and always use the size of the root property DefaultFigureColormap), but in fact setting HandleVisibility to 'off' exhibits the same behavior as when HandleVisibility is 'callback'. (It's possible I misunderstand something about how the HandleVisibility of a figure determines under what conditions it is considered the root's CurrentFigure.)
In any case, the solution is to always make sure you are providing the correct colormap you want to use. In particular, you can bypass the behavior of parula() trying to use the size of the current figure's Colormap by specifying as an input the size of the colormap you want, i.e., use parula(N), either in specifying the figure's Colormap in the call to dialog():
  • d = dialog(___, 'Colormap',parula(64));
or in the command to set the axes colormap:
  • colormap(ax,parula(64))
  댓글 수: 3
Chris
Chris 2023년 2월 4일
Excellent, thank you!
Voss
Voss 2023년 2월 4일
You're welcome!

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

Help CenterFile Exchange에서 Orange에 대해 자세히 알아보기

제품


릴리스

R2022b

Community Treasure Hunt

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

Start Hunting!

Translated by