Matlab:在GUI中同时在两个图像上显示十字光标
我正在使用指南构建一个MatlabGUI,用于处理医学图像(MRI扫描上的脑肿瘤分割)。作为预处理步骤,程序会记录不同的扫描,如下所示: 现在我想在两个图像上显示十字光标,作为对共同注册的视觉检查。十字准线应相互链接,以便它们指向两幅图像中的同一像素。此外,当鼠标悬停(或单击)其中一个图像时,它应该移动。这就是我想要实现的目标:Matlab:在GUI中同时在两个图像上显示十字光标,matlab,user-interface,image-processing,matlab-guide,Matlab,User Interface,Image Processing,Matlab Guide,我正在使用指南构建一个MatlabGUI,用于处理医学图像(MRI扫描上的脑肿瘤分割)。作为预处理步骤,程序会记录不同的扫描,如下所示: 现在我想在两个图像上显示十字光标,作为对共同注册的视觉检查。十字准线应相互链接,以便它们指向两幅图像中的同一像素。此外,当鼠标悬停(或单击)其中一个图像时,它应该移动。这就是我想要实现的目标: 是否存在可以实现这一点的内置MATLAB函数?或者,如果我必须自己编写,如何解决这个问题?我将使用玩具GUI来展示它的工作原理: 让我们首先尝试使其仅适用于第一个
是否存在可以实现这一点的内置MATLAB函数?或者,如果我必须自己编写,如何解决这个问题?我将使用玩具GUI来展示它的工作原理: 让我们首先尝试使其仅适用于第一个图像。您想要实现的是:
- 当用户单击图形时,我们希望能够访问鼠标单击的位置
- 然后我们要检查点击是否位于第一个图像内
- 如果是,我们要更新纵横杆的位置,它将由叠加在图像上的两条线表示,并在选定点交叉
- 确保在两次
调用后都添加了对imshow
的调用,否则横杆将删除图像而不是覆盖图像hold on
SuperDuperGUI\u OpeningFcn
),您希望添加对以下内容的调用:
set(gcf, 'WindowButtonDownFcn', @getMousePositionOnImage);
这将在用户每次在GUI中单击时触发函数getMousePositionOnImage
然后,您需要添加并实现函数getMousePositionOnImage
:
function getMousePositionOnImage(src, event)
% Fetch the current handles structure
handles = guidata(src);
% Get the coordinate IN THE AXES UNITS OF AXES1 (Here I chose to define them
% as pixels) of the point where the user clicked
cursorPoint = get(handles.axes1, 'CurrentPoint')
步骤2:检查鼠标单击是否在第一个图像内
仍在getMousePositionOnImage
函数中:
% Get the Position of the first image (We're only interested by the width
% and height of the axes1 object)
Img1Pos=get(handles.axes1,'Position')
% Check if inside
if(cursorPoint(1,1)<Img1Pos(3)&&cursorPoint(1,2)<Img1Pos(4)&&cursorPoint(1,1)>=0&&cursorPoint(1,2)>=0)
% Do stuff
end
%获取第一幅图像的位置(我们只对宽度感兴趣)
%axes1对象的大小和高度)
Img1Pos=get(handles.axes1,'Position')
%检查是否在里面
if(光标点(1,1)=0)
%做事
结束
步骤3:如果点击在第一张图像内,则更新纵横杆的位置
%检查是否在内部
if(光标点(1,1)=0)
Lines=findobj('Type','line','Parent',handles.axes1);
如果为空(行)
%如果Lines为空,则需要创建line对象
行([0 Img1Pos(3)],[cursorPoint(1,2)cursorPoint(1,2)],'Color','g','Parent',handles.axes1);
行([cursorPoint(1,1)cursorPoint(1,1)],[0 Img1Pos(4)],'Color','g','Parent',handles.axes1);
其他的
%如果没有,我们只更新两行的XData和YData字段
第(1)行。扩展数据=[0 Img1Pos(3)];%没有必要,但为了清楚起见,我会把它放在那里
第(1)行。YData=[光标点(1,2)光标点(1,2)];
第(2)行。扩展数据=[光标点(1,1)光标点(1,1)];
第(2)行。YData=[0 Img1Pos(4)];%没有必要,但为了清楚起见,我会把它放在那里
结束
结束
结果:
现在我让你们来做最后一部分,这涉及到连接两个横杆。您将分别检查这两个图像,而不是仅检查单击是否在第一个图像上。然后,如果它在一个图像中,您将更新twarecrossbar到右轴对象中单击的位置Edit
下面的代码灵感来自BillBokeey的答案,对此我非常感谢
首先,执行BillBokeey解决方案的第0步和第1步。然后我把这个函数放在我的代码中:
% Check if inside
if(cursorPoint(1,1)<Img1Pos(3)&&cursorPoint(1,2)<Img1Pos(4)&&cursorPoint(1,1)>=0&&cursorPoint(1,2)>=0)
Lines=findobj('Type','line','Parent',handles.axes1);
if isempty(Lines)
% If Lines is empty, we need to create the line objects
line([0 Img1Pos(3)],[cursorPoint(1,2) cursorPoint(1,2)],'Color','g','Parent',handles.axes1);
line([cursorPoint(1,1) cursorPoint(1,1)],[0 Img1Pos(4)],'Color','g','Parent',handles.axes1);
else
% If not, we just update the fields XData and YData of both Lines
Lines(1).XData=[0 Img1Pos(3)]; % Unnecessary but I'll leave it there for clarity
Lines(1).YData=[cursorPoint(1,2) cursorPoint(1,2)];
Lines(2).XData=[cursorPoint(1,1) cursorPoint(1,1)];
Lines(2).YData=[0 Img1Pos(4)]; % Unnecessary but I'll leave it there for clarity
end
end
函数getMousePositionInImage(src,事件)
%获取当前句柄结构
handles=guidata(src);
%以AXES1的轴单位获取坐标(这里我选择定义它们)
%作为用户单击点的像素)
cursorPoint1=get(handles.axes2,'CurrentPoint');
cursorPoint2=get(handles.axes3,“CurrentPoint”);
%获取第一张图像的位置(我们只对宽度感兴趣)
%axes1对象的大小和高度)
Img1Pos=getpixelposition(handles.axes2);
Img2Pos=getpixelposition(handles.axes3);
XLim1=get(handles.axes2,'XLim');
YLim1=get(handles.axes2,'YLim');
XLim2=get(handles.axes3,'XLim');
YLim2=get(handles.axes3,'YLim');
%检查是否在里面
如果(光标点1(1)=YLim1(1))
Lines1=findobj('Type','line','Parent',handles.axes2);
Lines2=findobj('Type','line','Parent',handles.axes3);
如果为空(第1行)
%如果Lines为空,则需要创建line对象
行(XLim1,[cursorPoint1(1,2)cursorPoint1(1,2)],'Color','g','Parent',handles.axes2);
行([cursorPoint1(1,1)cursorPoint1(1,1)],YLim1,'Color','g','Parent',handles.axes2);
行(XLim2,[cursorPoint1(1,2)cursorPoint1(1,2)],'Color','g','Parent',handles.axes3);
行([cursorPoint1(1,1)cursorPoint1(1,1)],YLim2,'Color','g','Parent',handles.axes3);
其他的
%如果没有,我们只更新两行的XData和YData字段
行1(1).扩展数据=XLim1;%没有必要,但为了清楚起见,我会把它放在那里
第1(1)行。YData=[光标点1(1,2)光标点1(1,2)];
行1(2).扩展数据=[cursorPoint1(1,1)cursorPoint1(1,1)];
第1(2)行。YData=YLim1;%没有必要,但为了清楚起见,我会把它放在那里
Lines2(1).扩展数据=XLim2;%没有必要,但为了清楚起见,我会把它放在那里
Lines2(1).YData=[光标点1(1,2)光标点1(1,2)];
行2(2).扩展数据=[cursorPoint1(1,1)cursorPoint1(1,1)];
Lines2(2).YData=YLim2;%没有必要,但为了清楚起见,我会把它放在那里
结束
elseif(光标点2(1)=YLim2(1))
Lines1=findobj('Type','line','Parent',handles.axes2);
Lines2=findobj('Type','line','Parent',handles.axes3);
如果为空(第2行)
%如果Lines为空,则需要创建line对象
第(XLi)行
function getMousePositionOnImage(src, event)
% Fetch the current handles structure
handles = guidata(src);
% Get the coordinate IN THE AXES UNITS OF AXES1 (Here I chose to define them
% as pixels) of the point where the user clicked
cursorPoint1 = get(handles.axes2, 'CurrentPoint');
cursorPoint2 = get(handles.axes3, 'CurrentPoint');
% Get the Position of the first image (We're only interested by the width
% and height of the axes1 object)
Img1Pos = getpixelposition(handles.axes2);
Img2Pos = getpixelposition(handles.axes3);
XLim1 = get(handles.axes2, 'XLim');
YLim1 = get(handles.axes2, 'YLim');
XLim2 = get(handles.axes3, 'XLim');
YLim2 = get(handles.axes3, 'YLim');
% Check if inside
if (cursorPoint1(1)<XLim1(2) && cursorPoint1(2)<YLim1(2) && cursorPoint1(1)>=XLim1(1) && cursorPoint1(1)>=YLim1(1))
Lines1=findobj('Type','line','Parent',handles.axes2);
Lines2=findobj('Type','line','Parent',handles.axes3);
if isempty(Lines1)
% If Lines is empty, we need to create the line objects
line(XLim1,[cursorPoint1(1,2) cursorPoint1(1,2)],'Color','g','Parent',handles.axes2);
line([cursorPoint1(1,1) cursorPoint1(1,1)],YLim1,'Color','g','Parent',handles.axes2);
line(XLim2,[cursorPoint1(1,2) cursorPoint1(1,2)],'Color','g','Parent',handles.axes3);
line([cursorPoint1(1,1) cursorPoint1(1,1)],YLim2,'Color','g','Parent',handles.axes3);
else
% If not, we just update the fields XData and YData of both Lines
Lines1(1).XData=XLim1; % Unnecessary but I'll leave it there for clarity
Lines1(1).YData=[cursorPoint1(1,2) cursorPoint1(1,2)];
Lines1(2).XData=[cursorPoint1(1,1) cursorPoint1(1,1)];
Lines1(2).YData=YLim1; % Unnecessary but I'll leave it there for clarity
Lines2(1).XData=XLim2; % Unnecessary but I'll leave it there for clarity
Lines2(1).YData=[cursorPoint1(1,2) cursorPoint1(1,2)];
Lines2(2).XData=[cursorPoint1(1,1) cursorPoint1(1,1)];
Lines2(2).YData=YLim2; % Unnecessary but I'll leave it there for clarity
end
elseif (cursorPoint2(1)<XLim2(2) && cursorPoint2(2)<YLim2(2) && cursorPoint2(1)>=XLim2(1) && cursorPoint2(1)>=YLim2(1))
Lines1=findobj('Type','line','Parent',handles.axes2);
Lines2=findobj('Type','line','Parent',handles.axes3);
if isempty(Lines2)
% If Lines is empty, we need to create the line objects
line(XLim1,[cursorPoint2(1,2) cursorPoint2(1,2)],'Color','g','Parent',handles.axes2);
line([cursorPoint2(1,1) cursorPoint2(1,1)],YLim1,'Color','g','Parent',handles.axes2);
line(XLim2,[cursorPoint2(1,2) cursorPoint2(1,2)],'Color','g','Parent',handles.axes3);
line([cursorPoint2(1,1) cursorPoint2(1,1)],YLim2,'Color','g','Parent',handles.axes3);
else
% If not, we just update the fields XData and YData of both Lines
Lines1(1).XData=XLim1; % Unnecessary but I'll leave it there for clarity
Lines1(1).YData=[cursorPoint2(1,2) cursorPoint2(1,2)];
Lines1(2).XData=[cursorPoint2(1,1) cursorPoint2(1,1)];
Lines1(2).YData=YLim1; % Unnecessary but I'll leave it there for clarity
Lines2(1).XData=XLim2; % Unnecessary but I'll leave it there for clarity
Lines2(1).YData=[cursorPoint2(1,2) cursorPoint2(1,2)];
Lines2(2).XData=[cursorPoint2(1,1) cursorPoint2(1,1)];
Lines2(2).YData=YLim2; % Unnecessary but I'll leave it there for clarity
end
end