【问题标题】:Matlab: display crosshairs simultaneously on two images in GUIMatlab:在 GUI 中的两个图像上同时显示十字准线
【发布时间】:2016-10-31 20:01:08
【问题描述】:

我正在使用 GUIDE 构建一个 MATLAB GUI,用于处理医学图像(MRI 扫描上的脑肿瘤分割)。作为预处理步骤,该程序会注册不同的扫描,如下所示:

我现在想在两个图像上都显示十字准线,作为对配准的视觉检查。十字准线应该相互链接,以便它们指向两个图像中的相同像素。此外,它应该在悬停(或单击)其中一个图像时移动。这就是我想要实现的目标:

是否存在可以实现此目的的内置 MATLAB 函数?或者,如果我必须自己写,如何解决这个问题?

【问题讨论】:

  • 我在您的帖子中将 [guide] 标签更改为 [matlab-guide]。请阅读您要使用的标签的标签维基;他们往往不是你想象的那样。

标签: matlab user-interface image-processing matlab-guide


【解决方案1】:

我将使用一个玩具 GUI 来展示它的工作原理:

让我们首先尝试使其仅适用于第一张图片。你想要达到的是:

  • 当用户点击图形时,我们希望能够访问鼠标点击的位置。
  • 然后我们要检查点击是否位于第一张图片内
  • 如果是,我们要更新横杆的位置,这将由覆盖在图像上并在所选点交叉的两条线表示。

步骤 0:初始设置

你想先确定一些细节:

  • 确保在您的两次imshow 调用之后添加对hold on 的调用,否则横杆将删除您的图像而不是覆盖在其上。

第一步:获取鼠标点击位置

在您的 GUI 打开函数中(这里将是SuperDuperGUI_OpeningFcn),您要添加一个调用:

set(gcf, 'WindowButtonDownFcn', @getMousePositionOnImage);

这将触发函数getMousePositionOnImage 每次用户在您的 GUI 中点击。

然后,你要添加并实现函数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

第 3 步:如果点击在第一张图片内,则更新横杆的位置

% 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

结果:

现在我将让您完成最后一部分,即连接两个横杆。您将分别检查两者,而不是只检查点击是否在第一张图片上。然后,如果它在其中一个图像中,您将更新 both 交叉栏到右轴对象中单击的位置

【讨论】:

  • 非常感谢!我会尝试并及时通知您。
  • 我相信你会明白的。当你这样做时,你能用最终代码发布答案吗?
  • 我已在单独的答案中发布了我的代码。如您所见,到目前为止它还不能完美运行。你知道我该如何解决这个问题吗?非常感谢!
【解决方案2】:

编辑

下面的代码灵感来自 BillBokeey 的回答,对此我非常感谢。

首先,执行 BillBokeey 解决方案的第 0 步和第 1 步。然后我把这个函数放在我的代码中:

    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

【讨论】:

  • 线条的交点是否在正确的位置?
  • 十字路口正是我点击的地方,原来如此!
  • 问题出在变量Img1PosImg2Pos
  • 它和Img1Pos=get(handles.axes2,'Position')有同样的行为吗?
  • 不,这对我不起作用,我无法联系到if "position is in image?"
猜你喜欢
  • 1970-01-01
  • 2013-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-15
  • 1970-01-01
  • 2020-04-09
相关资源
最近更新 更多