vlambda博客
学习文章列表

【图像识别】基于 Haar分类器实现五官定位matlab源码含 GUI

一、简介

1 Haar分类器的前世今生

人脸检测属于计算机视觉的范畴,早期人们的主要研究方向是人脸识别,即根据人脸来识别人物的身份,后来在复杂背景下的人脸检测需求越来越大,人脸检测也逐渐作为一个单独的研究方向发展起来。

1.1 目前的人脸检测方法主要有两大类:基于知识和基于统计。
Ø 基于知识的方法:主要利用先验知识将人脸看作器官特征的组合,根据眼睛、眉毛、嘴巴、鼻子等器官的特征以及相互之间的几何位置关系来检测人脸。
Ø 基于统计的方法:将人脸看作一个整体的模式——二维像素矩阵,从统计的观点通过大量人脸图像样本构造人脸模式空间,根据相似度量来判断人脸是否存在。

1.2 基于知识的人脸检测方法:
模板匹配、人脸特征、形状与边缘、纹理特性、颜色特征

1.3 基于统计的人脸检测方法:
主成分分析与特征脸、神经网络方法、支持向量机、隐马尔可夫模型、Adaboost算法
本文中介绍的Haar分类器方法,包含了Adaboost算法,稍候会对这一算法做详细介绍。所谓分类器,在这里就是指对人脸和非人脸进行分类的算法,在机器学习领域,很多算法都是对事物进行分类、聚类的过程。OpenCV中的ml模块提供了很多分类、聚类的算法。
注:聚类和分类的区别是什么?
Ø 分类:一般对已知物体类别总数的识别方式我们称之为分类,并且训练的数据是有标签的,比如已经明确指定了是人脸还是非人脸,这是一种有监督学习。
Ø 聚类:也存在可以处理类别总数不确定的方法或者训练的数据是没有标签的,这就是聚类,不需要学习阶段中关于物体类别的信息,是一种无监督学习。
其中包括Mahalanobis距离、K均值、朴素贝叶斯分类器、决策树、Boosting、随机森林、Haar分类器、期望最大化、K近邻、神经网络、支持向量机。
我们要探讨的Haar分类器实际上是Boosting算法的一个应用,Haar分类器用到了Boosting算法中的AdaBoost算法,只是把AdaBoost算法训练出的强分类器进行了级联,并且在底层的特征提取中采用了高效率的矩形特征和积分图方法,这里涉及到的几个名词接下来会具体讨论。

在2001年,Viola和Jones两位大牛发表了经典的《Rapid Object Detection using a Boosted Cascade of Simple Features》和《Robust Real-Time Face Detection》,在AdaBoost算法的基础上,使用Haar-like小波特征和积分图方法进行人脸检测,他俩不是最早使用提出小波特征的,但是他们设计了针对人脸检测更有效的特征,并对AdaBoost训练出的强分类器进行级联。这可以说是人脸检测史上里程碑式的一笔了,也因此当时提出的这个算法被称为Viola-Jones检测器。又过了一段时间,Rainer Lienhart和Jochen Maydt两位大牛将这个检测器进行了扩展【3】,最终形成了OpenCV现在的Haar分类器。
AdaBoost是Freund和Schapire在1995年提出的算法,是对传统Boosting算法的一大提升。Boosting算法的核心思想,是将弱学习方法提升成强学习算法,也就是“三个臭皮匠顶一个诸葛亮”
Haar分类器 = Haar-like特征 + 积分图方法 + AdaBoost +级联;
Haar分类器算法的要点如下:
① 使用Haar-like特征做检测。
② 使用积分图(Integral Image)对Haar-like特征求值进行加速。
③ 使用AdaBoost算法训练区分人脸和非人脸的强分类器。
④ 使用筛选式级联把强分类器级联到一起,提高准确率。

2 Haar分类器的浅入浅出

2.1 Haar-like特征你是何方神圣?

什么是特征,我把它放在下面的情景中来描述,假设在人脸检测时我们需要有这么一个子窗口在待检测的图片窗口中不断的移位滑动,子窗口每到一个位置,就会计算出该区域的特征,然后用我们训练好的级联分类器对该特征进行筛选,一旦该特征通过了所有强分类器的筛选,则判定该区域为人脸。
那么这个特征如何表示呢?好了,这就是大牛们干的好事了。后人称这他们搞出来的这些东西叫Haar-Like特征。

下面是Viola牛们提出的Haar-like特征。

下面是Lienhart等牛们提出的Haar-like特征。
【图像识别】基于 Haar分类器实现五官定位matlab源码含 GUI
这些所谓的特征不就是一堆堆带条纹的矩形么,到底是干什么用的?我这样给出解释,将上面的任意一个矩形放到人脸区域上,然后,将白色区域的像素和减去黑色区域的像素和,得到的值我们暂且称之为人脸特征值,如果你把这个矩形放到一个非人脸区域,那么计算出的特征值应该和人脸特征值是不一样的,而且越不一样越好,所以这些方块的目的就是把人脸特征量化,以区分人脸和非人脸。

为了增加区分度,可以对多个矩形特征计算得到一个区分度更大的特征值,那么什么样的矩形特征怎么样的组合到一块可以更好的区分出人脸和非人脸呢,这就是AdaBoost算法要做的事了。这里我们先放下积分图这个概念不管,为了让我们的思路连贯,我直接开始介绍AdaBoost算法。

二、源代码

function varargout = gui(varargin)
% GUI MATLAB code for gui.fig
% GUI, by itself, creates a new GUI or raises the existing
% singleton*.
%
% H = GUI returns the handle to a new GUI or the handle to
% the existing singleton*.
%
% GUI('CALLBACK',hObject,eventData,handles,...) calls the local
% function named CALLBACK in GUI.M with the given input arguments.
%
% GUI('Property','Value',...) creates a new GUI or raises the
% existing singleton*. Starting from the left, property value pairs are
% applied to the GUI before gui_OpeningFcn gets called. An
% unrecognized property name or invalid value makes property application
% stop. All inputs are passed to gui_OpeningFcn via varargin.
%
% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one
% instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help gui

% Last Modified by GUIDE v2.5 19-Dec-2016 02:28:04

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @gui_OpeningFcn, ...
'gui_OutputFcn', @gui_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(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
% End initialization code - DO NOT EDIT


% --- Executes just before gui is made visible.
function gui_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to gui (see VARARGIN)

% Choose default command line output for gui
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes gui wait for user response (see UIRESUME)
% uiwait(handles.figure1);


% --- Outputs from this function are returned to the command line.
function varargout = gui_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;









%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%按钮功能实现%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% 读取图片按钮
[filename, pathname] = uigetfile( {'*.jpg;*.jpeg;*.tif;*.png;*.gif','All Image Files';'*.*','All Files' },'请选择图片');
str=[pathname filename];
global im;
im = imread(str);
axes(handles.axes1);
imshow(im);
title(filename);
set(handles.edit1,'string',sprintf('%i × %i', size(im,1), size(im,2)));


% --- Executes on button press in pushbutton2.
function pushbutton2_Callback(hObject, eventdata, handles)
% 退出程序按钮
close;


% --- Executes on button press in pushbutton3.
function pushbutton3_Callback(hObject, eventdata, handles)
% 人脸识别按钮
mergeThreshole = str2num(get(handles.edit2,'String'));
maxS = str2num(get(handles.edit3,'String'));
minS = str2num(get(handles.edit4,'String'));
isPrint = 0; % 0表示不打印五官
isTest = 0; % 1表示进行五官检验
if get(handles.radiobutton1,'value')
isPrint = 1;
end
if get(handles.radiobutton2,'value')
isTest = 1;
end
detector = buildDetector(mergeThreshole,1,maxS, minS); % 构建探测器
global im;
[bbimg, faces] = detectFaceParts(detector,im,5,isPrint,isTest);
axes(handles.axes2);
imshow(bbimg);
title('识别结果');
for i=1:7 % 清空原图
str = ['cla(handles.axes' num2str(i+2) ')'];
eval(str);
end
for i=1:7
if i > size(faces, 1)
break;
end
str = ['axes(handles.axes' num2str(i+2) ')'];
eval(str);
imshow(faces{i});
title(sprintf('人脸%i', i));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%









% --- Executes during object creation, after setting all properties.
function axes1_CreateFcn(hObject, eventdata, handles)
% hObject handle to axes1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
set(hObject,'xTick',[]); % 去掉坐标轴
set(hObject,'ytick',[]); % 去掉坐标轴
set(hObject,'box','on'); % 去掉坐标轴
% Hint: place code in OpeningFcn to populate axes1


% --- Executes during object creation, after setting all properties.
function axes2_CreateFcn(hObject, eventdata, handles)
% hObject handle to axes2 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
set(hObject,'xTick',[]); % 去掉坐标轴
set(hObject,'ytick',[]); % 去掉坐标轴
set(hObject,'box','on'); % 去掉坐标轴
% Hint: place code in OpeningFcn to populate axes2


% --- Executes during object creation, after setting all properties.
function axes3_CreateFcn(hObject, eventdata, handles)
% hObject handle to axes3 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
set(hObject,'xTick',[]); % 去掉坐标轴
set(hObject,'ytick',[]); % 去掉坐标轴
set(hObject,'box','on'); % 去掉坐标轴
% Hint: place code in OpeningFcn to populate axes3

% --- Executes during object creation, after setting all properties.
function axes4_CreateFcn(hObject, eventdata, handles)
% hObject handle to axes3 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
set(hObject,'xTick',[]); % 去掉坐标轴
set(hObject,'ytick',[]); % 去掉坐标轴
set(hObject,'box','on'); % 去掉坐标轴
% Hint: place code in OpeningFcn to populate axes3

% --- Executes during object creation, after setting all properties.
function axes5_CreateFcn(hObject, eventdata, handles)
% hObject handle to axes3 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
set(hObject,'xTick',[]); % 去掉坐标轴
set(hObject,'ytick',[]); % 去掉坐标轴
set(hObject,'box','on'); % 去掉坐标轴
% Hint: place code in OpeningFcn to populate axes3

% --- Executes during object creation, after setting all properties.
function axes6_CreateFcn(hObject, eventdata, handles)
% hObject handle to axes3 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
set(hObject,'xTick',[]); % 去掉坐标轴
set(hObject,'ytick',[]); % 去掉坐标轴
set(hObject,'box','on'); % 去掉坐标轴
% Hint: place code in OpeningFcn to populate axes3

三、运行结果


 》》  喜欢可以关注我