1. 程式人生 > >人臉識別雜談和膚色概率建模程式碼

人臉識別雜談和膚色概率建模程式碼

本文內容出自於《人臉識別原理與實戰》

人臉檢測只是人臉識別的準備工作。要準確的識別人臉,不僅需要檢測到人臉(檢測到人臉可採用膚色概率的高斯分佈建模方法),而且需要將檢測到的人臉與資料儲存器的人臉特徵進行對比,並在此基礎上快速地完成人臉匹配。因此,人臉識別演算法的摸索不妨從特徵臉建庫開始,在人臉檢測的基礎上進行面部特徵定位。眼睛、鼻子和嘴巴的特徵是人最主要的三個面部輪廓特徵,可作為面部特徵定位的著手點。可以用haar-like特徵實現面部關鍵部位檢測,將這些關鍵部位的邊緣特徵、線性特徵、中心特徵和對角線特徵進行組合,生成特徵模板。

具體請參考該部落格https://blog.csdn.net/lg1259156776/article/details/48677637#t3

在生成模板的基礎上,我們可以藉助主成分分析(PCA)建立人的面部模型,這就是特徵臉建庫了。將一批人臉影象轉換成一個特徵向量集即可。這些特徵向量集被稱為“Eigenfaces”,這就是“特徵臉”的由來。

特徵臉資料庫是構建機器學習的基礎資料庫,主成分分析是一種經典演算法,我們比較熟悉其模型原理。雖然從實戰而言,我們都不太關注模型細節,但是鑑於特徵臉建庫的重要性,還是需瞭解基於主成分分析的人臉識別原理——總的來說就是先將檢測到的所有人臉都投影到特徵臉子空間,然後通過每張人臉投影點所在的位置及投影線的長度進行判定和識別。

進而初步理解PCA人臉識別演算法的核心思想了。

附膚色概率提取人臉輪廓的MATLAB程式碼

clc
clear all
close all

x=imread('1.jpg');
y=rgb2ycbcr(x);
[a b c]=size(y);
cb=double(y(:,:,2));
cr=double(y(:,:,3));
%% 下面開始計算每個畫素點的膚色概率
for i=1:a
    for j=1:b
        w=[cb(i,j) cr(i,j)];%色度矩陣
        m=[110.4516 150.5699];%膚色均值,可以理解成離散高斯分佈的期望值
        %這個均值需要提前確定,這個是膚色概率模型的明顯不足之處;大家換圖片測試,會發現可能需要修改此引數
        n=[97.0916 23.37;23.37 137.9966];%協方差矩陣,對應此處離散高斯分佈
        p(i,j)=exp((-0.5)*(w-m)*inv(n)*(w-m)');%計算膚色概率,即相似度
    end
end
z=p./max(max(p));%歸一化結果
%下面開始閾值化
%figure
th=0.5;
for i=1:a
    for j=1:b
        if(z(i,j)>th)
            z(i,j)=1;
        else 
            z(i,j)=0;
        end
    end
end
figure;%一邊處理一邊出圖!
subplot(2,2,1);
imshow(z);
title('Set threshold')%閾值化結果

%% 下面做數學形態學處理,先後進行開運算、閉運算、填洞、腐蝕及膨脹操作
se=strel('square',3);
f=imopen(z,se);%開運算
f=imclose(f,se);%閉運算
f=imfill(f,'holes');%填洞
sel=strel('square',8);
%構造結構元素(strel是Structuring element的簡寫)
f=imerode(f,sel);%腐蝕
f=imdilate(f,sel);%膨脹
%至此得到了一個較純淨的膚色區域

%% 下面嘗試將人臉區域與其他膚色區域分割開來
[L,num]=bwlabel(f,4);
%返回一個和f大小相同的L矩陣,包含標記了f中每個連通區域的類別標籤,這些標籤的值為1,2,...,num(連通區域的個數)
for i=1:num
    [r,c]=find(L==i);%第i個連通區域
    len=max(r)-min(r)+1;%區域長度
    wid=max(c)-min(c)+1;%區域寬度
 	area_sq=len*wid;%區域面積
    area=size(r,1);%區域大小,即畫素點的個數
    %開始判定第i個連通區域是不是人臉區域
    for j=1:size(r,1)
        if(len/wid<.8)|(len/wid>2.4)|size(r,1)<200|area/area_sq<0.55
            L(r(j),c(j))=0;%如果不是人臉區域,則通過賦值將其融入背景色
        else
            continue;
        end
    end
end

subplot(2,2,2);
imshow(L);
title('Face Region')%人臉區域顯示

w=L&z;
%通過邏輯運算,檢測面部特徵點;程式碼開始設定的膚色均值,顯然也會影響這個特徵點的檢測,大家從程式執行結果中也不難看出;請大家試著調整膚色均值,看看執行結果的變化
subplot(2,2,3);
imshow(w);
title('Features points')%人臉特徵點顯示

%% 開始標記人臉區域,這裡用矩形標記,讀者也可以嘗試用
[r c]=find(L~=0);
r_min=min(r);
r_max=max(r);
c_min=min(c);
c_max=max(c);
subplot(2,2,4);
imshow(x); 
title('Detection result')
rectangle('Position',[c_min r_min c_max-c_min r_max-r_min],'EdgeColor','r');
%以矩形區域為人臉檢測的結果