Matlab实现鼠标拖动显示轮廓线
在处理高度数据等非图像二维数据时候,难免需要实时查看x,y方向的截线信息,此时就需要一种简洁的方法来实现这一功能,目前在工程以及实验室环境下的方法是C++方法,显示大多数采用的是openCV开源代码,这里介绍了一种利用matlab实现这一功能的方法,其中借鉴了一些前辈的经验。
将通过以下步骤进行讲解
- 1.建立GUI界面
- 2.显示图片
- 3.显示line以及轮廓截线
- 4.实现鼠标拖动联动
- 5.功能升级
1.建立GUI界面
如图1所示
该图中,InputImageData和OutputImage控件正常创建即可,2个黑框控件需要调整一些属性,可根据个人需求调整背景颜色,重要的是调整NextPlot属性为replacechildren,这样可以在此控件中实时重绘曲线
此外还需创建一个开始按钮,这里我采用的是菜单形式,如图2所示
也可以根据个人喜好建立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所示
需要实现的功能是拖动竖线,能够实时显示竖线所在位置的截面线,拖动横线,能够实时显示横线所在位置的截面线;
添加代码如下:
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