【人脸表情识别】基于matlab GUI稀疏表示人脸表情识别【含Matlab源码 786期】

224 阅读9分钟

一、简介

用较少的基本信号的线性组合来表达大部分或者全部的原始信号。
其中,这些基本信号被称作原子,是从过完备字典中选出来的;而过完备字典则是由个数超过信号维数的原子聚集而来的。可见,任一信号在不同的原子组下有不同的稀疏表示。
假设我们用一个MN的矩阵表示数据集X,每一行代表一个样本,每一列代表样本的一个属性,一般而言,该矩阵是稠密的,即大多数元素不为0。 稀疏表示的含义是,寻找一个系数矩阵A(KN)以及一个字典矩阵B(MK),使得BA尽可能的还原X,且A尽可能的稀疏。A便是X的稀疏表示。
在这里插入图片描述
南大周志华老师写的《机器学习》这本书上原文:“为普通稠密表达的样本找到合适的字典,将样本转化为合适的稀疏表达形式,从而使学习任务得以简化,模型复杂度得以降低,通常称为‘字典学习’(dictionary learning),亦称‘稀疏编码’(sparse coding)”块内容。

表达为优化问题的话,字典学习的最简单形式为:
在这里插入图片描述
其中xi为第i个样本,B为字典矩阵,αi为xi的稀疏表示,λ为大于0参数。

•寻找少量重要的系数来表示原始信号的技术被称作Sparse Coding(稀疏编码或稀疏分解);

•从任意一个字典中为原始信号寻找最稀疏的表示常用的方法分类两类:

①贪婪算法,比如匹配追踪(MP)、正交匹配追踪(OMP)、弱匹配追踪(WMP)、阈值方法等;

②松弛算法,比如迭代加权最小二乘(Iterative-Reweighed-Least-Squares,IRLS)、基追踪(BP)等。

其中,贪婪算法的特点是速度快,精度相对较低;松弛算法是精度高,但速度慢。

•穷举法——NP难:

假设 的非零项数目为L(sparse level),先令L=1,字典里的每一个原子(列向量)尝试一遍,看是否满足终止条件,共有K种组合。如果没有满足,再令L=2,再次尝试,共有K(K-1)/2种组合。还没有满足条件的,则令L=3……组合的数目呈指数增长,于是遇到了NP难问题。

•贪婪算法——Matching Pursuit

第一步,找到最接近X的原子,等效于 向量上仅取一个非零项,求出最接近的原子,保留下来;

第二步,计算误差是否满足要求,如果满足,算法停止,否则,计算出残差信号,和第一步类似,找到最接近残差向量的原子,保留下来;

第三步,调整已选向量的系数,使得 最接近X,重复第二步。

•松弛算法——Basis Pursuit,将L0问题转化为L1问题,解决的方法有很多,比如内点法、迭代收缩法等。事实上,它可以化成一个线性规划的问题,用MATLAB很容易解。
上式中第一个累加项说明了字典学习的第一个目标是字典矩阵与稀疏表示的线性组合尽可能的还原样本;第二个累加项说明了αi应该尽可能的稀疏。之所以用L1范式是因为L1范式正则化更容易获得稀疏解。具体原因参看该书11.4章或移步机器学习中的范数规则化之(一)L0、L1与L2范数。字典学习便是学习出满足上述最优化问题的字典B以及样本的稀疏表示A(A{α1,α2,…,αi})。L1正则化常用于稀疏,可以获得稀疏解。如下图表示,L1正则化交点在轴上,所得的解一般只是在某个轴上有实数,另外的轴为0,从而最终得到稀疏解。
在这里插入图片描述
2.字典学习:

寻找字典的过程称为字典学习。字典学习的一个假设是字典对于指定信号具有稀疏表示。因此,选择字典的原则就是能够稀疏地表达信号。
两种方法来设计字典:
•从已知的变换基中选取,比如 DCT 、小波基等,这种方法很通用,但是不能自适应于信号。
学习字典,即通过训练和学习大量的与目标数据相似的数据来获得。这里,我们介绍一种叫K-SVD的方法
字典学习算法理论包含两个阶段:字典构建阶段(Dictionary Generate)和利用字典(稀疏的)表示样本阶段(Sparse coding with a precomputed dictionary)。这两个阶段(如下图)的每个阶段都有许多不同算法可供选择,每种算法的诞生时间都不一样,以至于稀疏字典学习的理论提出者已变得不可考。笔者尝试找了Wikipedia和Google Scolar都无法找到这一系列理论的最早发起人。
在这里插入图片描述
字典学习的第一个好处——它实质上是对于庞大数据集的一种降维表示。第二,正如同字是句子最质朴的特征一样,字典学习总是尝试学习蕴藏在样本背后最质朴的特征(假如样本最质朴的特征就是样本最好的特征).稀疏表示的本质:用尽可能少的资源表示尽可能多的知识,这种表示还能带来一个附加的好处,即计算速度快。我们希望字典里的字可以尽能的少,但是却可以尽可能的表示最多的句子。这样的字典最容易满足稀疏条件。也就是说,这个“字典”是这个“稀疏”私人订制的。

稀疏表达有两点好处:

  1. 省空间;
  2. 奥卡姆剃刀说:如果两个模型的解释力相同,选择较简洁的那个。稀疏表达就符合这一点。

How to find the dictionary D?——K-SVD
假设现在有原始信号矩阵 , 该矩阵的每一行表示一个信号或者一张图片, D 矩阵是字典矩阵,右下方是 稀疏解矩阵S,红色的点表示非零项。
在这里插入图片描述
Step 1: Initialize. 在 矩阵中随机挑选一些行向量(一些原图),填满矩阵 D,并归一化每一列。

Step 2: Sparse Coding. 用松弛或者贪婪法进行稀疏编码,使得
在这里插入图片描述
得到稀疏表示 构成稀疏矩阵S的第i行。

What are sparse representations/approximations good for?
•稀疏性是DFT、WT和SVD分解得以广泛利用的原因之一,这些变换的目的都是为了反映信号的确定性结构,并用紧凑的或稀疏的表示来表征这些结构;

•稀疏表示的思想为模式分类方法建立了基础,比如SVM和RVM,其中稀疏性直接与估计函数(estimator)的学习能力有关。

•稀疏表示解决的问题主要集中在:

•图像去噪(Denoise),代表性paper:Image Denoise Via Sparse and Redundant Representations Over Learned Dictionaries(Elad M. and Aharon M. IEEE Trans. on Image Processing,Dec,2006);Image Sequence Denoising Via Sparse and Redundant Representations(Protter M. and Elad M.IEEE Trans. on Image Processing,Jan,2009);

•超分辨率重建(Super-Resolution OR Scale-Up),代表性paper:Image Super-Resolution via Sparse Representation(Jianchao Yang, John Wright, Thomas Huang, and Yi Ma,IEEE Transactions on Image Processing, Nov,2010),A Shrinkage Learning Approach for Single Image Super-Resolution with Overcomplete Representations( A. Adler, Y. Hel-Or, and M. Elad,ECCV,Sep,2010);

另外还有inpaintting,deblurring,compression等等…更多应用参考Elad M的书。
在这里插入图片描述
在这里插入图片描述

二、源代码

function varargout = FacialExpressionRecognitiontool(varargin)
% FACIALEXPRESSIONRECOGNITIONTOOL MATLAB code for FacialExpressionRecognitiontool.fig
%      FACIALEXPRESSIONRECOGNITIONTOOL, by itself, creates a new FACIALEXPRESSIONRECOGNITIONTOOL or raises the existing
%      singleton*.
%
%      H = FACIALEXPRESSIONRECOGNITIONTOOL returns the handle to a new FACIALEXPRESSIONRECOGNITIONTOOL or the handle to
%      the existing singleton*.
%
%      FACIALEXPRESSIONRECOGNITIONTOOL('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in FACIALEXPRESSIONRECOGNITIONTOOL.M with the given input arguments.
%
%      FACIALEXPRESSIONRECOGNITIONTOOL('Property','Value',...) creates a new FACIALEXPRESSIONRECOGNITIONTOOL or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before FacialExpressionRecognitiontool_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to FacialExpressionRecognitiontool_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 FacialExpressionRecognitiontool

% Last Modified by GUIDE v2.5 23-Oct-2014 12:52:25

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @FacialExpressionRecognitiontool_OpeningFcn, ...
                   'gui_OutputFcn',  @FacialExpressionRecognitiontool_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 FacialExpressionRecognitiontool is made visible.
function FacialExpressionRecognitiontool_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 FacialExpressionRecognitiontool (see VARARGIN)

% Choose default command line output for FacialExpressionRecognitiontool
set(handles.togglebutton1,'visible','off')
set(handles.togglebutton2,'visible','off');
set(handles.text2,'visible','off');
set(handles.edit2,'visible','off');
set(handles.text3,'visible','off');
axes(handles.axes2)
cla
axes(handles.axes1)
cla
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

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


% --- Outputs from this function are returned to the command line.
function varargout = FacialExpressionRecognitiontool_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;



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

% Hints: get(hObject,'String') returns contents of edit1 as text
%        str2double(get(hObject,'String')) returns contents of edit1 as a double


% --- Executes during object creation, after setting all properties.
function edit1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global A m1 n1 No_Files_In_Class_Folder Class_Count Training_Set_Folder

Training_Set_Folder = [uigetdir(''),'\'];
m1 =9;
n1 =9;
TS_Vector = dir(Training_Set_Folder);
No_Folders_In_Training_Folder = length(TS_Vector);
File_Count = 1;
Class_Count = 1;
h = waitbar(0,'Reading Test Images,Please wait...');
for k = 3:No_Folders_In_Training_Folder
    waitbar(k/(No_Folders_In_Training_Folder-2))
    Class_Folder = [Training_Set_Folder '\' TS_Vector(k).name,'\'];
    CF_Tensor = dir(Class_Folder);
    No_Files_In_Class_Folder(Class_Count) = length(CF_Tensor)-2;
    %     strr = sprintf('Reading Test Images...!, # of Classes = %d, Now Reading %d ',No_Folders_In_Training_Set_Folder-2,Class_Count);
    %     set(handles.edit3,'String',strr);
    drawnow;
    for p = 3:No_Files_In_Class_Folder(Class_Count)+2
        Tmp_Image_Path = Class_Folder;
        Tmp_Image_Name = CF_Tensor(p).name;
        Tmp_Image_Path_Name = [Tmp_Image_Path,Tmp_Image_Name];
        if strcmp(Tmp_Image_Name,'Thumbs.db')
            break
        end
        test = imread(Tmp_Image_Path_Name);
        if length(size(test))==3
            Tmp_Image = rgb2gray(test);
        else
            Tmp_Image = test;
        end
        Tmp_Image_Down_Sampled = double(imresize(Tmp_Image,[m1 n1]));
        Image_Data_Matrix(:,File_Count) = Tmp_Image_Down_Sampled(:);
        File_Count = File_Count+1;
        
    end
    Class_Count = Class_Count+1;
    
end
close(h)
A = Image_Data_Matrix;
A = A/(diag(sqrt(diag(A'*A))));
set(handles.edit5,'visible','off');
set(handles.edit1,'visible','off');

% --- Executes on button press in pushbutton2.
function pushbutton2_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global A m1 n1 No_Files_In_Class_Folder Class_Count Training_Set_Folder
set(handles.togglebutton1,'visible','off')
set(handles.togglebutton2,'visible','off');
set(handles.text2,'visible','off');
[Test_File Test_File_Path] = uigetfile('*.jpg;*.pgm;*.png;*.tiff;*.bmp','Select a Test Image');
test_image_path = [Test_File_Path Test_File];
axes(handles.axes1)
cla
axes(handles.axes2)
cla
axes(handles.axes1)
imshow(test_image_path);
title('测试图片','Color','black','FontSize',15);
drawnow;
% set(handles.edit2,'string',test_image_path);
% set(handles.text5,'Visible','Off');
Test_File = [Test_File_Path Test_File];
test = imread(Test_File);
if length(size(test))==3
    Test_Image = rgb2gray(test);
else
    Test_Image = test;
end
Test_Image_Down_Sampled = double(imresize(Test_Image,[m1 n1]));
y = Test_Image_Down_Sampled(:);
n = size(A,2);
% minimize norm(x1,1)
% subject to
% A*x1 == y;
% cvx_end
% figure,plot(x1);
f=ones(2*n,1);
Aeq=[A -A];
lb=zeros(2*n,1);
x1 = linprog(f,[],[],Aeq,y,lb,[],[],[]);
x1 = x1(1:n)-x1(n+1:2*n);
figure
bar(x1/1000,0.2) %参数中y表示数据,0.2表示柱状图中柱子的宽度
legend('稀疏系数','WestOutside');
nn = No_Files_In_Class_Folder;
nn = cumsum(nn);
tmp_var = 0;
k1 = Class_Count-1;
for i = 1:k1
    delta_xi = zeros(length(x1),1);
    if i == 1
        delta_xi(1:nn(i)) = x1(1:nn(i));
    else
        tmp_var = tmp_var + nn(i-1);
        begs = nn(i-1)+1;
        ends = nn(i);
        delta_xi(begs:ends) = x1(begs:ends);
    end
    tmp(i) = norm(y-A*delta_xi,2);
    tmp1(i) = norm(delta_xi,1)/norm(x1,1);
end

三、运行结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、备注

版本:2014a