Matlab实现鼠标拖动显示轮廓线

Matlab实现鼠标拖动显示轮廓线

在处理高度数据等非图像二维数据时候,难免需要实时查看x,y方向的截线信息,此时就需要一种简洁的方法来实现这一功能,目前在工程以及实验室环境下的方法是C++方法,显示大多数采用的是openCV开源代码,这里介绍了一种利用matlab实现这一功能的方法,其中借鉴了一些前辈的经验。

将通过以下步骤进行讲解

  • 1.建立GUI界面
  • 2.显示图片
  • 3.显示line以及轮廓截线
  • 4.实现鼠标拖动联动
  • 5.功能升级

1.建立GUI界面

如图1所示 
图1,采用12b版本的Matlab,版本过低会出错
该图中,InputImageData和OutputImage控件正常创建即可,2个黑框控件需要调整一些属性,可根据个人需求调整背景颜色,重要的是调整NextPlot属性为replacechildren,这样可以在此控件中实时重绘曲线 
此外还需创建一个开始按钮,这里我采用的是菜单形式,如图2所示 
Tools->Menu Editer 
也可以根据个人喜好建立Bottom按钮。此外需要注意的是创建控件过程中,需要右键创建各自CreatFcn函数,没有这个函数就说明这个函数没有正确创建。

2.显示图片

显示图片很简单,在创建的开始函数中写相关代码,例如

function InputTXT_Callback(hObject, eventdata, handles)
% hObject    handle to InputTXT (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

InputData=importdata('039高度.txt');
InputData=reshape(InputData,128,128)';
axes(handles.InputImageData);
imagesc(InputData);
axis off;
title('输入图像');%根据需求改变显示效果
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

3.显示line以及轮廓线

假定需要添加的效果如图3所示 
图3.效果图 
需要实现的功能是拖动竖线,能够实时显示竖线所在位置的截面线,拖动横线,能够实时显示横线所在位置的截面线; 
添加代码如下:

function InputTXT_Callback(hObject, eventdata, handles)
% hObject    handle to InputTXT (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global MinInput;
global MaxInput;
global h w;
global xdata_start;
global ydata_start;
global InputData OutputData;
global xpos ypos;
global Xhand Yhand;

InputData=importdata('039高度.txt');
InputData=reshape(InputData,128,128)';
OutputData=[];
[MinInput,MaxInput]=FindRange(InputData);%找到输入数据的最大值和最小值
axes(handles.InputImageData);
imagesc(InputData);
xpos=64;%初始截线位置
ypos=64;
xdata_start=[64 64];%后续操作用
ydata_start=[64 64];
h=line([1,128],[ypos,ypos], 'LineWidth', 2,'color','black');%画出相关截线
w=line([xpos,xpos],[1,128], 'LineWidth', 2,'color','black');
axis off;
Xhand=handles.InputHorLine;%选择在哪个控件上画图
Yhand=handles.InputParLine;
showInputXLine(InputData,OutputData,ypos,Xhand);%画横向截线
showInputYLine(InputData,OutputData,xpos,Yhand);%画纵向截线
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

接下来是画截线的代码

function showInputYLine(nData,mData,a,hand)
%显示当前点的轮廓线
global MinInput;
global MaxInput;
[M,N]=size(nData);
x=1:M;
 nDatayline=nData(:,a);
 axes(hand);
if isempty(mData)
  plot(nDatayline,x,'color','white'); %如果输出数据是空的,画输入数据的白色线
else
    nDatayline2=mData(:,a);
   plot(nDatayline,x,'w',nDatayline2,x,'g');
   %输出数据不是空的,画输入和输出数据两条线,用白色和绿色表示 
end
axis([MinInput,MaxInput,0,128]);%坐标轴范围
set(gca,'YDir','reverse','XDir','reverse');%调整坐标轴位置至右上
set(gca,'xaxislocation','top','yaxislocation','right');
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

以上代码便可以实现截线和截面线的相关显示,接下来说明下如何实现鼠标拖动截线,并同时显示截线位置的截面线。

4.实现鼠标拖动联动

此处代码存在借鉴了前辈们的一些成果 
在之前代码后面添加以下两句:

DragModeYY(untitled,handles.InputImageData,h,InputData,Xhand,Yhand);
DragModeXX(untitled,handles.InputImageData,w,InputData,Xhand,Yhand);
  • 1
  • 2

这两个函数分别对应y,x向截线的拖动以及显示截面线的功能,代码如下: 
代码1:

function DragModeXX(f,aH,h,data,Xhand,Yhand)
global xy_start;
global xdata_start;
global ydata_start;
global xpos;
global ypos;
global OutputData;
set(h,'ButtonDownFcn',@startDragXFcn);
set(f,'WindowButtonUpFcn',@stopDragXFcn);

    function startDragXFcn(varargin)
    set(f,'WindowButtonMotionFcn',@draggingXFcn)
    xy_start=get(aH,'CurrentPoint');
    xdata_start=get(h,'xdata');
    end
    function draggingXFcn(varargin)
      xy_current=get(aH,'CurrentPoint');
      if xy_current(1)>128
          xy_current(1)=128;%超出显示截面便置边界
      elseif xy_current(1)<1
          xy_current(1)=1;
      else 
          xy_current(1)= xy_current(1);
      end
      dx=xy_current(1)-xy_start(1);
      set(h,'xdata',xdata_start+dx);%获得截线x方向的实时位置
    end
    function stopDragXFcn(varargin)
      set(f,'WindowButtonMotionFcn','');
      xpos=round(xdata_start);
      showInputYLine(data,OutputData,xpos,Yhand);%显示相关曲线
      ypos=round(ydata_start);
      showInputXLine(data,OutputData,ypos,Xhand);
    end
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

代码2:

function DragModeYY(f,aH,h,data,Xhand,Yhand)
global xy_start;
global ydata_start;
set(h,'ButtonDownFcn',@startDragYFcn);
set(f,'WindowButtonUpFcn',@stopDragYFcn);
    function startDragYFcn(varargin)
    set(f,'WindowButtonMotionFcn',@draggingYFcn)
    xy_start=get(aH,'CurrentPoint');
    ydata_start=get(h,'ydata');
    end
    function draggingYFcn(varargin)
      xy_current=get(aH,'CurrentPoint');
      if xy_current(3)>128
          xy_current(3)=128;
      elseif xy_current(3)<1
          xy_current(3)=1;
      else 
          xy_current(3)= xy_current(3);
      end   
      dy=xy_current(3)-xy_start(3);
      set(h,'ydata',ydata_start+dy);
    end
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

这里解释一个问题:为什么其中一个函数没写stopDragYFcn函数,原因好像是ButtomUp按钮只能赋一次函数(猜测);

5.功能升级

可以看出以上有同时画两条截面线的功能,两条截面线来自与输入数据和处理后的数据,因此在进行其他操作后得到OutputData后可根据以上代码实现两者联立,效果图如下,采用的是均值滤波处理 
最终效果图
可以看出通过移动截线,可以实现截面线的实时显示(两条截线是分开移动的);

第一篇帖子,看到的觉得有用的给个赞,谢谢!!!

转:https://blog.csdn.net/wiehau1993/article/details/51940751

猜你喜欢

转载自blog.csdn.net/eric_e/article/details/80780239