数学建模 ①人脸识别

写在论文提交结束之后:
才开始建模不久举行的一次校赛。
感觉团队的想法很好,但是自己的程序实现一直有问题,所以就想在结束后认真弄懂问题。
这篇文章主要是在介绍代码,并且有可以成功运行的代码。

原题
(1)建立人脸位置判断的数学模型,判断人脸在照片中的大致位置,并在图 1 和 图 2 中用你设计的模型框出人脸的大致位置。
(2) 在问题(1)的基础上,建立人脸精确识别的数学模型,判断图 2 中各个人物 的脸型、鼻型、眼型、唇形等。(提示:如果你在 DIY 过程中遇到了困难,不妨降低要 求,比如说鼻型可以分为“大鼻子”和“小鼻子”。)
(3)在问题(2)的基础上,建立人脸匹配的数学模型,判断图 2、图 3 中是否有 人物与图 1 的人物是同一人,如果有,请在图片中框出具体是哪个人物与图 1 的人物一 样。

一、问题分析
1.预处理

预处理的作用:

  • 使图像去除干扰后续操作的因素,例如噪声等;
  • 使所有图像符合某种标准;
  • 在正式处理前进行处理,减少后续的运算量,加速收敛,提高可靠性。

2.问题一

所有图片可以均经过问题一得到相应的人脸图;
准备使用Viola-Jones 级联分类器人脸检测方法;
对于此题所给图片经测试这种方法精确度较高;

操作流程:

  • 光线补偿预处理
  • 灰度化
  • 中值滤波
  • 灰度变换增强
  • 小波增强
  • VJ算法
  • 将已检测出的人脸提取出来

3.问题二

使用Harris角点检测,基于图像像素灰度值的变化梯度,即通过一个矩形窗口在图像上移动已检测该区域的图像灰度值变化。
提取特征点,定位五官具体位置,再根据长宽比,面积占比等特征辨别形状;

操作流程:

  • 灰度化
  • 数值转化成double类型
  • 把图片放大
  • 寻找并标注特征点
4.问题三
二、代码部分
1.问题一

VJ算法直接调用系统已封装好的vision.CascadeObjectDetector
详细说明地址:
https://ww2.mathworks.cn/help/vision/ref/vision.cascadeobjectdetector-system-object.html

在这个部分经过所给图片的尝试,选择FrontalFaceLBP,即根据局部二进制模式(LBP)来编码面部特征

第一题完整代码如下:

function question_1()
    clear;
    clc;
    
    %% 读取图像
    I=imread('1.jpg');
    Ori=I;
    
    %% 预处理(输出为Img)
    %光线补偿
    Img=imadjust(I,[],[]);  %注意imadjust函数的用法
    %灰度
    Img=rgb2gray(Img);
    
    %% 中值滤波(去噪,输出为 I,入口需灰度) 
    I=medfilt2(Img);   %中值滤波的函数,第二个参数为二维矩阵,代表选取的 平滑窗口,一般为 3*3,可以进行调整(如果为灰度图像可不要第二个参数) 
    
    %% 灰度变换增强(选择后决定最佳,输出为 H) 
    %灰度 (可选择)
    judge=0;
    while (judge==0)
        judge=1;
        disp('基本的灰度变换(2-伽马变换;3-分段线性;4-直方图均衡)'); 
        choosen=input('请输入你的选择:'); 
        switch choosen 
	    %3.伽马变换     
            case 2         
                x=0:255;         
                a=80;
                b=1.8;
                c=0.009;         
                H=b.^(c.*(double(I)-a)-1);         
                y=b.^(c.*(x-a))-1;         
    %             figure 
    %             subplot(2,2,1),imshow(I);         
    %             subplot(2,2,3),imshow(H),title('伽马变换后的图像');         
    %             figure,plot(x,y),title('伽马变换折线图'); 
            %4.分段线性变换(入口需灰度)     
            case 3         
                f0=0;g0=0;         
                f1=10;g1=30;         
                f2=220;g2=255;         
                f3=255;g3=255;         
    %             figure,plot([f0,f1,f2,f3],[g0,g1,g2,g3]),title('分段线性折线图'); 
                r1=(g1-g0)/(f1-f0);         
                b1=r1*f0+g0;         
                r2=(g2-g1)/(f2-f1);         
                b2=r2*f1+g1;         
                r3=(g3-g2)/(f3-f2);         
                b3=r3*f2+g2;         
%                 axis([0 225 0 225]);         
                [m,n]=size(I);         
                h=double(I);         
                for i=1:m             
                    for j=1:n                 
                        t=h(i,j);                 
                        g(i,j)=0;                 
                        if((t>=f0)&&(t<=f1))                     
                            g(i,j)=r1*t+b1;                 
                        else
                            if((t>=f1)&&(t<=f2))                         
                                g(i,j)=r2*t+b2;                     
                            else
                                if((t>=f2)&&(t<=f3))                         
                                    g(i,j)=r3*t+b3;                         
                                end
                            end
                        end
                    end
                end
                H=mat2gray(g);   %归一化,使矩阵的每个元素的值都在 0 和 1 之间(其 源图像要求为二维的灰度图像)         
    %             figure,imshow(H),title('分段线性变换后的图像'); 
            %5.直方图均衡(入口需灰度)     
            case 4         
                H=histeq(I);        
                %输入为二维图,要先灰度;         
    %             figure         
    %             subplot(121),imshow(I);         
    %             subplot(122),imshow(H);     
            otherwise
                disp('无效!请重新输入!'); 
                judge=0;
        end
    end
    
    %% 小波增强(低频系数增强,高频系数衰减,输出为 HH)(可选择)
    judge=0;
    while(judge==0)
        judge=1;
        choosen=input('是否进行小波增强(1.是;0.否):'); 
        switch choosen 
            case 1
                HH=double(H);       %转换成 double,避免精度丢失 
                [c,s]=wavedec2(HH,2,'db3');     %多尺度一维小波分级(利用小波'db3'对信号 HH 进行 2 层分解) 
                cs=size(c); 
                for i=1:cs(2)    %对图像的分解系数做处理,以突出所需部分并弱化不需要的部分     
                    if(c(i)>350)         
                        c(i)=2*c(i);     
                    else
                        c(i)=0.5*c(i);    
                    end
                end
                H=waverec2(c,s,'db3');  %对图像进行小波重构(小波逆变换) 
    %           figure,imshow(H),title('小波重构后的图像');
            case 0
                break;
            otherwise
                disp('无效!请重新输入!');
                jugde=0;
        end     
    end
    
    %% 正式处理:VJ/Adaboost算法
    detector=vision.CascadeObjectDetector;   %使用Viola-Jones算法创建一个检测器来检测对象
    %检测面部
    detector.ClassificationModel='FrontalFaceLBP';  
    bboxes=step(detector,H);   %直接把detector当作函数使用
    %处理bboxes(因为不处理bboxes,即直接VJ算法算出来的坐标值,原图会在脸的范围之内,即没有全脸,不能判断脸型)
    for i=1:size(bboxes,1)
        bboxes(i,1)=bboxes(i,1)+9;
        bboxes(i,2)=bboxes(i,2)+9;
    end
    
    %%画框
    Face=insertObjectAnnotation(Ori,'rectangle',bboxes,'Face','Font','Comic Sans MS','TextBoxOpacity',0,'FontSize',25,'LineWidth',3,'Color','red','TextColor','white');
    figure,imshow(Face),title('检测到的人脸');
    
    %% 提取已检测到的人脸图像
    for i=1:size(bboxes,1) 
        pic=imcrop(I,[bboxes(i,:)]); 
        imwrite(pic,[num2str(i),'.png']);     %注意imwrite的用法
    end
end

值得注意的是,vision.CascadeObjectDetector算法的入口为RGB图像或者灰度图像,可以根据需要增加或者修改预处理部分,只需要能连接上vision.CascadeObjectDetector的接口即可。

2.问题二

寻找特征点时直接调用系统函数concer;

3.问题三
三、扩展
1.问题一扩展
  1. 此处主要指第一题中所用的vision.CascadeObjectDetector的扩展部分;
    因为题目所需,我们可以直接使用已训练好的vision.CascadeObjectDetector系统中的分类器,但在多数时候比如说对车牌号等的检测,需要我们重新寻找训练集取训练分类器,而在matlab中有已经写好的算法,可以直接导入训练集和数据
    详细说明地址:https://ww2.mathworks.cn/help/vision/ug/train-a-cascade-object-detector.html

  2. 这次因为时间关系直接调用matlab中的自带函数,希望后面自己能写出类似深度学习的函数。
    本来准备用基于肤色建立的高斯模型VJ算法结合的形式,但由于当前只能调用vision.CascadeObjectDetector实现VJ算法,而

  • vision.CascadeObjectDetector入口只能是RGB图像或者灰度化后的图像

  • 肤色高斯模型大多输出二值化后的图像

    两个函数的衔接有问题,所以只能采用精度更高的VJ算法。
    还有基于肤色建立的高斯模型:

2.问题二扩展

本题选用的是通过调用concer()函数实现Haar角点检测;
下面将介绍通过高斯卷积函数进行卷积滤波,提取特征,寻找特征点的方式实现Haar角点检测:

你可能感兴趣的:(数学建模)