I'd like to plot some points over an image in a dialog.
조회 수: 6 (최근 30일)
이전 댓글 표시
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
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.
채택된 답변
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))
추가 답변 (0개)
참고 항목
카테고리
Help Center 및 File Exchange에서 Orange에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!