基于MatlabGUI的Harris角点检测程序
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于MatlabGUI的Harris角点检测程序
作 者: Bugzhao Mailto: bugzhao@ QQ:88576613 发表时间: 2005-2-17
内容概要: 我写的一个使用matlab制作的角点检测程序
图片支持格式:jpg、bmp、tif等格式的灰度、彩色图片 目前仅实现了harris检测器
最终将实现四种角点检测算法
包括经典的harris、基于canny边缘检测和弧度、
基于多分辨率、基于SUSAN
本文分三部分
第一部分简要介绍图像处理理论中的角点检测
第二部分介绍matlab GUI编程
第三部分介绍本程序的完整实现
Part(1)
角点检测(corner detection/extration)经常被用于作为特征提取的第一步。
比如在制作一个全景图拼接程序中,我们可以首先检测邻接图片的角点,然后在这些角点中进行适当选择排除,最终形成两幅图片的特征点对。
接下来可以根据这些特征点对来计算邻接图片的变换矩阵(一般使用仿射变换来近似投影变换),最终经图像融合技术就可以得到全景图。
角点检测大体有两种思路,一种是直接基于灰度,另一种是先检测边缘,然后计算弧度的局部极大值得到角点。
后者对噪声有较好的抗干扰性能。
本课题中首先来实现harris角点检测算法
首先来看最为经典的Moravec算法。
算法思路是计算图像灰度在任意方向上的变化,使用一个移动窗口,在像素点的4个方向进行移动,然后求最小E值的局部最大值。
在均匀灰度中,E值在各个方向都很小;在边缘处,最小值依赖于边缘的方向,可以想像E值变化有大有小;而在角点处,每个方向的E值变化都较大。
所以检测4个方向中E值变化最小的那个量,如果它仍大于某一给定阈值,即可认为此点为角点。
这就是Moravec算法的思路。
以上公式即为E值计算公式。
W为窗口,I为像素。
Moravec算法的思想可以直观的理解。
Harris在此算法的基础之上进行了改进,他利用泰勒级数展开方法将移动方向进行了扩展使之不再局限,同时引入了一种平滑因子,增强了抗干扰能力。
关于算法的梗概介绍到此
更加详细的介绍请参见harris的原文:
C. Harris and M. Stephens, A combined corner and edge detector, Fourth Alvey Vision Conference, pp.147-151, 1988.
Part(2)
先来看看程序界面:
利用matlab进行GUI程序设计的步骤:
1,输入guide,进入layout设计界面,进行控件排布的外观设计 2,为每个控件链接上代码
介绍GUI设计的文章很多,我这里以FAQ的形式讲述一下。
首先如何制作一个按钮?
第一步将按钮图标拖入,然后设置图标属性
调整按钮属性:
接下来,如何为按钮的响应链接一个响应函数?
就是在这个Callback里设置的
这样就进入了响应函数设计部分。
怎么样,十分简单吧。
hObject这里就是这个按钮的句柄,而handles是一种和次figure相关连的结构体,用于存放传递参数。
我们就可以在此书写函数语句了。
比如输入:
prompt = {"Enter a number"};
dlg_title = "Input test";
num_lines= 1;
def = {"1"};
answer = inputdlg(prompt,dlg_title,num_lines,def);
val=str2num(answer{1});
disp(val)
这里顺便介绍一下inputdlg,这是一个类似于VCVB中的弹出对话框的东东,可以接收用户输入参数。
上述语句可以将用户输入保存在val中,并在命令行窗口中显示结果。
如下:
这里1是默认值,如果用户直接按回车则接收此作为输入
本程序还用到了popupmenu,大家可以参考第三部分的源代码。
另外还有一个重要的函数:
[FileName,PathName] = uigetfile("*.bmp","Select BMP file"); 本函数弹出一个文件选择对话框并返回文件完整路径。
GUI的介绍到此结束
Part(3)
现在来看看如何编写完整的代码
首先,设计figure文件,最终做成如下界面:
完整matlab代码如下:
function varargout = cornerdetect(varargin)
gui_Singleton = 1;
gui_State = struct("gui_Name", mfilename, ...
"gui_Singleton", gui_Singleton, ...
"gui_OpeningFcn", @cornerdetect_OpeningFcn, ...
"gui_OutputFcn", @cornerdetect_OutputFcn, ...
"gui_LayoutFcn", [] , ...
"gui_Callback", []);
if nargin & isstr(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% --- Executes just before cornerdetect is made visible.
function cornerdetect_OpeningFcn(hObject, eventdata, handles, varargin)
%set initial parameters
handles.output = hObject;
handles.type1=1;
handles.type2=1;
set(handles.button_detectcorner1,"Enable","Off");
set(handles.popupmenu_selectdetector1,"Enable","Off");
set(handles.button_detectcorner2,"Enable","Off");
set(handles.popupmenu_selectdetector2,"Enable","Off");
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes cornerdetect wait for user response (see UIRESUME)
% uiwait(handles.figure1);
function varargout = cornerdetect_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;
% --------------------------------------------------------------------------------------------------------------- function button_loadimage1_Callback(hObject, eventdata, handles)
[FileName,PathName] = uigetfile("*.bmp","Select BMP file");
[handles.i1,handles.map1,handles.g1,handles.d1]=loadimage(PathName,FileName); imageshow(handles.i1,handles.map1,handles.axes1);
set(handles.popupmenu_selectdetector1,"Enable","On");
set(handles.button_detectcorner1,"Enable","On");
guidata(gcf,handles);
% --- Executes during object creation, after setting all properties.
function popupmenu_selectdetector1_CreateFcn(hObject, eventdata, handles)
if ispc
set(hObject,"BackgroundColor","white");
else
set(hObject,"BackgroundColor",get(0,"defaultUicontrolBackgroundColor")); end
% --- Executes on selection change in popupmenu_selectdetector1.
function popupmenu_selectdetector1_Callback(hObject, eventdata, handles) handles.type1=get(hObject,"Value");
guidata(hObject,handles);
% --- Executes on button press in button_detectcorner1.
function button_detectcorner1_Callback(hObject, eventdata, handles)
[cim,r,c]=cornertype(handles.g1,handles.type1);
set(handles.axes1,"NextPlot","add");
plot(c,r,"g+","Parent",handles.axes1);
str=strcat("Number of corners : ",num2str(size(r,1)));
set(handles.text_cornernumber1,"String",str);
guidata(hObject,handles);
% --------------------------------------------------------------------
function button_loadimage2_Callback(hObject, eventdata, handles) [FileName,PathName] = uigetfile("*.bmp","Select BMP file");
[handles.i2,handles.map2,handles.g2,handles.d2]=loadimage(PathName,FileName); imageshow(handles.i2,handles.map2,handles.axes2);
set(handles.popupmenu_selectdetector2,"Enable","On");
set(handles.button_detectcorner2,"Enable","On");
guidata(gcf,handles);
function button_detectcorner2_Callback(hObject, eventdata, handles)
[cim,r,c]=cornertype(handles.g2,handles.type2);
set(handles.axes2,"NextPlot","add");
plot(c,r,"r+","Parent",handles.axes2);
str=strcat("Number of corners : ",num2str(size(r,1)));
set(handles.text_cornernumber2,"String",str);
guidata(hObject,handles);
function popupmenu_selectdetector2_CreateFcn(hObject, eventdata, handles)
if ispc
set(hObject,"BackgroundColor","white");
else
set(hObject,"BackgroundColor",get(0,"defaultUicontrolBackgroundColor")); end
function popupmenu_selectdetector2_Callback(hObject, eventdata, handles) handles.type2=get(hObject,"Value");
guidata(hObject,handles);
function [I,map,G,D]=loadimage(pathname,filename)
[I,map]=imread([pathname filename]);
iii = size(size(I));
if iii(2) == 3
G = rgb2gray(I);
else
G = I;
end
D=double(G);
function imageshow(I,map,axes_handle)
axis equal;
colormap(map);
image(I,"Parent",axes_handle);%,"XData",-n1/2,"YData",-m1/2);
function [cim,r,c]=cornertype(G,type)
switch type
case 1
sigma=1;
thresh=30000;
radius=2;
prompt = {"Enter sigma:","Enter thresh:","Enter radius:"};
dlg_title = "Input parameters for harris corner detector";
num_lines= 1;
def = {"1","30000","2"};
answer = inputdlg(prompt,dlg_title,num_lines,def);
sigma=str2num(answer{1});
thresh=str2num(answer{2});
radius=str2num(answer{3});
[cim,r,c]=harris(G,sigma,thresh,radius);
end
================================================
Harris.m
function [cim, r, c] = harris(im, sigma, thresh, radius)
error(nargchk(2,5,nargin));
dx = [-1 0 1; -1 0 1; -1 0 1]; % Derivative masks
dy = dx";
Ix = conv2(im, dx, "same"); % Image derivatives
Iy = conv2(im, dy, "same");
% Generate Gaussian filter of size 6*sigma (+/- 3sigma) and of
% minimum size 1x1.
g = fspecial("gaussian",max(1,fix(6*sigma)), sigma);
Ix2 = conv2(Ix.^2, g, "same"); % Smoothed squared image derivatives
Iy2 = conv2(Iy.^2, g, "same");
Ixy = conv2(Ix.*Iy, g, "same");
% Compute the Harris corner measure. Note that there are two measures % that can be calculated. I prefer the first one below as given by
% Nobel in her thesis (reference above). The second one (commented out) % requires setting a parameter, it is commonly suggested that k=0.04 - I % find this a bit arbitrary and unsatisfactory.
cim = (Ix2.*Iy2 - Ixy.^2)./(Ix2 + Iy2 + eps); % My preferred measure.
% k = 0.04;
% cim = (Ix2.*Iy2 - Ixy.^2) - k*(Ix2 + Iy2).^2; % Original Harris measure.
if nargin > 2 % We should perform nonmaximal suppression and threshold
% Extract local maxima by performing a grey scale morphological
% dilation and then finding points in the corner strength image that
% match the dilated image and are also greater than the threshold.
sze = 2*radius+1; % Size of mask.
mx = ordfilt2(cim,sze^2,ones(sze)); % Grey-scale dilate.
cim = (cim==mx)&(cim>thresh); % Find maxima.
[r,c] = find(cim); % Find row,col coords.
end
程序最终界面:
参数输入部分:
(本文完)。