MATLAB人脸检测算法

MATLAB人脸检测算法

人脸检测是将人脸从复杂的背景图像中检测出来,它是实现人脸识别的基础和前提。

肤色重建

使用人脸肤色模板对灰度图像进行肤色重建,使其变成彩色图像,效果如下:
MATLAB人脸检测算法_第1张图片
在函数function R=gray2rgb1(img1,img2)中,img1代表需要彩色重建的灰度图像,img2代表彩色人脸模板。

function R=gray2rgb1(img1,img2)
% img1 - Source Image  (gray image)   
% img2 - Selected color image for coloring the gray image. 
 imt=rgb2gray(im);
% imt=img1;
ims=img2;
 [sx sy sz]=size(imt);
 [tx ty tz]=size(ims);
 if sz~=1
     imt=rgb2gray(imt);
 end
 if tz~=3
     disp ('img2 must be a color image (not indexed)');
 else
     imt(:,:,2)=imt(:,:,1);
     imt(:,:,3)=imt(:,:,1);

 % Converting to ycbcr color space
     nspace1=rgb2ycbcr(ims);
     nspace2= rgb2ycbcr(imt);

    ms=double(nspace1(:,:,1));
     mt=double(nspace2(:,:,1));
     m1=max(max(ms));
     m2=min(min(ms));
     m3=max(max(mt));
     m4=min(min(mt));
     d1=m1-m2;
     d2=m3-m4;
 % Normalization
     dx1=ms;
     dx2=mt;
     dx1=(dx1*255)/(255-d1);
     dx2=(dx2*255)/(255-d2);
     [mx,my,mz]=size(dx2);
 %Luminance Comparison
     disp('Please wait..................');
     for i=1:mx
         for j=1:my
              iy=dx2(i,j);
              tmp=abs(dx1-iy);
              ck=min(min(tmp));
              [r,c] = find(tmp==ck);
              ck=isempty(r);
              if (ck~=1)            
                  nimage(i,j,2)=nspace1(r(1),c(1),2);
                  nimage(i,j,3)=nspace1(r(1),c(1),3);
                  nimage(i,j,1)=nspace2(i,j,1);           
             end
          end
      end
     rslt=ycbcr2rgb(nimage);
     figure,imshow(uint8(imt));
     figure,imshow(uint8(rslt));
     R=uint8(rslt);
     toc
 end  

非线性光照补偿

由于图像在取像时,人脸很容易受到周围环境中的关照影响,包括光源的方向,明暗等,这可能造成人脸区域的一些有效信息的丢失,从而导致人脸漏检和错检现象。为了解决人脸因为光照造成人脸检测率降低的问题,因此有必要对输入的图像光照补偿处理,下面使用非线性光照补偿。代码如下:

function [Dst]=nolinetransaction(Scr)
img_ycbcr=rgb2ycbcr(Scr);
img_y=img_ycbcr(:,:,1);
Dim=size(img_y);
Num=Dim(1)*Dim(2);
Pixsum=0.05*Num;
sum=0;
Sum=0;
[count,level]=imhist(img_y);
for i=1:256
    sum=sum+count(i);
    if sum>Pixsum
        B=i-1;
        break;
    end
end
for i=256:-1:1
    Sum=Sum+count(i);
    if Sum>Pixsum
        E=i+1;
        break;
    end
end
for i=1:Dim(1)
    for j=1:Dim(2)
        if img_y(i,j)<B
            img_y(i,j)=0;
        elseif img_y(i,j)>=B && img_y(i,j)<=E
            img_y(i,j)=255*(log(double(img_y(i,j))-log(B)))/(log(E)-log(B));
        else
            img_y(i,j)=255;
        end
    end
end
Dst=ycbcr2rgb(img_ycbcr);

    

人脸检测算法

根据人脸肤色在YCbCr空间上类似呈现高斯分布,因此可以根据这一特征,将一幅图像中的人脸和背景分开,实现二值化,高斯人脸检测代码如下:
MATLAB人脸检测算法_第2张图片

function p=gaosi(x1)
 I=rgb2ycbcr(x1);        %颜色空间转换 
 
% I=T_YCbCr(I);
% figure;
% imshow(I);

[a,b,c]=size(I); %得到图像的像素点个数
cb=double(I(:,:,2));
cr=double(I(:,:,3));
for i=1:a
    for j=1:b
        w=[cb(i,j),cr(i,j)];
        m=[117.4316 148.5599];
        n=[260.1301 12.1430;12.1430 150.4574];
        p(i,j)=exp((-0.5)*(w-m)*inv(n)*(w-m)');%算某象素点的概率
        if (p(i,j)<0.5) 
            p(i,j)=0;
        else 
            p(i,j)=1;
        end
    end
end 

人脸框

通过对高斯人脸检测得到的二值图像进行形态学操作进一步确定人脸的位置并使用矩形框进行标记,在函数function []=kuang(p,x1)中,p代表二值图像,x1代表二值图像对应的RGB图像,具体代码如下:

function []=kuang(p,x1)
% SE = strel('disk',5); 
% imf=imopen(p,SE);         %开运算(即先腐蚀再膨胀),消除杂散点 
% imf=medfilt2(imf,[3,3]);%中值滤波
se=strel('disk',3);
 se1=strel('disk',1);
 imf=imerode(p,se);
 imf=imdilate(imf,se1);
 [w,h]=size(imf);
 imf=bwareaopen(imf,round(w*h/900));
%  imf=bwareaopen(imf,1000);%开运算,去除像素点少于1000的区域
figure;
imshow(imf);
[L,num]=bwlabel(imf,4);     %连通区域标记 
B=zeros(size(imf));
for i=1:num
    Area(i)=bwarea(L==i);%计算每个皮肤区域的面积
end
for i=1:num
    [r,c] = find(L==i) ;
    left(i)=min(c);
    right(i)=max(c);
    up(i)=min(r);
    down(i)=max(r);
end
for i=1:num 
    %计算各矩形区域面积
    Rect_Area(i)=(down(i)-up(i))*(right(i)-left(i));
end
%计算各区域的填充率
Ratio=Area./Rect_Area;
for i=1:num 
   if Ratio(i)>=0.5%若相应区域的填充率大于0.5则保留该区域
       [x,y]=find(L==i);%第i块区域的坐标值
       B=B+bwselect(imf,y,x,4);%把填充率大于0.5皮肤区域叠加起来   
   end      
end

% B=bwareaopen(B,1000);%开运算,去除像素点少于1000的区域
figure;
imshow(B);

%%%%%%%%%%%%%%%%%%%%%%%%%%根据面积比来进一步除去一些较小的非人脸区域%%%%%%%%%%%%%%%%%%%%%%%%%%
[L1,num1]=bwlabel(B,4);     %连通区域标记
B1=zeros(size(B));
for i=1:num1
    Area(i)=bwarea(L1==i);%计算每个皮肤区域的面积
end
maxarea=max(Area);%取最大值
q=Area/maxarea;%每块区域的面积与最大区域面积的比值   
for i=1:num1 
   if q(i)>=0.3%若相应区域的面积比值大于0.3则保留该区域
       [x,y]=find(L1==i);%第i块区域的坐标值
       B1=B1+bwselect(B,y,x,4);%把面积比值大于0.3皮肤区域叠加起来   
   end      
end
figure;
imshow(B1);

%%%%%%%%%%%%%%%%%%%%%%%%%%根据肤色区域的长宽比来除去一些非人脸区域%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[L2,num2]=bwlabel(B1,4);     %连通区域标记 
B2=zeros(size(B1));
for i=1:num2
    [r,c] = find(L2==i);  
    left(i)=min(c);
    right(i)=max(c);
    up(i)=min(r);
    down(i)=max(r);
end
for i=1:num2
    if ((down(i)-up(i))/(right(i)-left(i)))>0.8&&((down(i)-up(i))/(right(i)-left(i)))<2
        [x,y]=find(L2==i);
        B2=B2+bwselect(B1,y,x,4);%%%把满足长宽比在0.8到2的区域留下
    end
end
figure,
imshow(B2);

figure,
imshow(x1);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%把人脸框出来%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[L3 num3]=bwlabel(B2,8);     %连通区域标记
for i=1:num3
    [r,c] = find(L3==i);  
    left(i)=min(c);
    right(i)=max(c);
    up(i)=min(r);
    down(i)=max(r);
end

hold on;
for i=1:num3
    if(down(i)>(up(i)+(right(i)-left(i))*1.2))     %人脸长宽比限制1.2
       down(i)=up(i)+(right(i)-left(i))*1.2;
    end
    x=[left(i);left(i);right(i);right(i);left(i)];
    y=[up(i);down(i);down(i);up(i);up(i)];
    plot(x,y,'g','LineWidth',2);      %画框
%     drawnow;
end
hold off;

主函数测试检测效果

clc
close all
I1=imread("需要检测的灰度图像地址");
I2=imread("人脸彩色图像模板地址");
R=gray2rgb1(I1,I2);%肤色重建
DST=nolinetransaction(Scr);%光照补偿
p=gaosi(DST);%高斯人脸检测二值化
kuang(p,R);%将图像中所有人脸使用矩形框进行标记,并显示

你可能感兴趣的:(IT技术,1024程序员节,人脸识别,边缘检测)