簡單的基於YCrCb顏色空間的人臉檢測(膚色)

環境:Windows XP+MATLAB 2010b

基本思路:

1)將基於彩色空間的RGB模型轉換爲YCbCr模型(考慮到人臉的生理特徵,只採取了Cr分量作爲輔助)

2)閾值分割,根據多次實驗發現,正常黃種人的Cr分量大約在140~·160之間

3)濾波,本實驗採用性能較好的中值濾波

4)特徵區域提取,利用matlab的bwlabel函數

5)對標記的特徵區域利用高寬度之比和麪積兩個指數來進一步簡化特徵區域

 

具體實驗代碼及原理講解

1)rgb->ycbcr

%公式 Y = 0.2990*R + 0.5780*G + 0.1140*B + 0
%公式 Cr = 0.5000*R - 0.4187*G - 0.0813*B + 128
%公式 Cb = -0.1687*R - 0.3313*G + 0.5000*B + 128

(參見http://en.wikipedia.org/wiki/YCbCr)

本實驗直接採用mtalab自帶函數rgb2ycbcr()轉換就OK了。

I1=imread('blue_lg.jpg');
si=size(I1);
m=si(1);n=si(2);
img1=rgb2ycbcr(I1);
cr1=img1(:,:,3);%大小爲mxn的二維矩陣

  

2)閾值分割

cr3=cr1;
for i=1:m
for j=1:n
if(cr3(i,j)>140&&cr3(i,j)<160)%140~160爲本人實驗多次得到的合理值
      cr3(i,j)=255;
else
      cr3(i,j)=0;
end
end
end

3)中值濾波器(本實驗採用的是5x5的子模板)

c_r=cr3;
for i=3:m-2
    for j=3:n-2;
        temp=cr3(i-2:i+2,j-2:j+2);%提取5x5區域
        temp1=sort(temp);%排序
        c_r(i,j)=temp1(13);%中值
    end
end

4)利用bwlabel進行特徵區域提取

關於matlab函數bwlabel:[L, num] = bwlabel(BW, n);

根據領域的鏈接性質,將整個區域分爲num個子區域,L爲一矩陣,其中每個子區域在此矩陣中的值爲子區域的序號。值得注意的是,序號爲0的情況(我理解爲背景,直接棄之不用)。n指的是領域性質,4鄰域or8鄰域。

舉個例子,

BW = logical ([1     1     1     0     0     0     0     0
               1     1     1     0     1     1     0     0
               1     1     1     0     1     1     0     0
               1     1     1     0     0     0     1     0
               1     1     1     0     0     0     1     0
               1     1     1     0     0     0     1     0
               1     1     1     0     0     1     1     0
               1     1     1     0     0     0     0     0]);
3種背景顏色分別表示3個子區域,剩下的即爲區域0,理解爲背景吧。
對應生成的L矩陣即爲
% L = bwlabel(BW,4);

L =

     1     1     1     0     0     0     0     0
     1     1     1     0     2     2     0     0
     1     1     1     0     2     2     0     0
     1     1     1     0     0     0     3     0
     1     1     1     0     0     0     3     0
     1     1     1     0     0     0     3     0
     1     1     1     0     0     3     3     0
     1     1     1     0     0     0     0     0
(參考mtlab自帶文檔)

我的做法是在當前路徑下重新定義了一個子函數findlimit()。

function [l,kk]=findlimit(I)
%l爲已分類有序矩陣
%kk爲特徵區域的序號

tt=size(size(I));
if tt(2)==3  %若I爲3維矩陣,則需要轉換爲灰度圖像
    J=rgb2gray(I);
else        %I爲3維矩陣
    J=I;
end

%[m,n]=size(J);

[l,num]=bwlabel(J,8);
area=zeros(1,num+1);%面積
zhonghengbi=zeros(1,num+1);%比例
%re=zeros(num+1,4);
re1=zeros(num+1,2);
for k=0:num
    [r,c]= find(l==k);
     % re(k+1,1)=min(r);     %垂直方向最小值(上)
     % re(k+1,2)=max(r);    %垂直方向最大值(下)
     % re(k+1,3)=min(c);     %水平方向最小值(左)
     % re(k+1,4)=max(c);    %水平方向最大值(右)
     re1(k+1,1)=max(r)-min(r);%高度
     re1(k+1,2)=max(c)-min(c);%寬度
     zhonghengbi(k+1)=re1(k+1,1)/re1(k+1,2);%高寬比
     if(re1(k+1,2)==0) zhonghengbi(k+1)=0;end%防止出現單條垂直線的情況
     area(k+1)=re1(k+1,1)*re1(k+1,2);
end

j=1;
for i=1:num+1
    if zhonghengbi(i)>0.2&&zhonghengbi(i)<3.0&&area(i)>1000
%高寬比設置爲0.2~3.0之間,面積認爲大於1000,注意面積爲隨機項,與圖片大小有很大的關係
       kk(j)=i-1;
       j=j+1;
    end
end

5)把特徵區域整個提取出來

在此之前定義了一個判斷序號是否在提取出的特徵區域內的isson()函數,如下:

function x=isson(y,I)
x=0;
z=size(I);
for i=1:z(2)
    if(y==I(i))
        x=1;
        break;
    end
end

  

[l,kk]=findlimit(c_r);
J=l;
for i=1:m
    for j=1:n
    if(l(i,j)~=0&&isson(l(i,j),kk)==1)
        J(i,j)=255;
    else
        J(i,j)=0;
    end
    end
end
figure;imshow(J,[]);

然後就可以達到最後的人臉頭像了。

原始圖像:

處理後

 

2原始圖像

處理後:

 

到這裏,本文即將完結,但是可能大家都注意到,許多圖像之中,由於手臂的膚色與人臉一致,以及背景不可避免的顏色巧合,導致最終的效果不是特別理想。

這裏主要討論手與臉的區分問題(考慮使用類圓相似度來解決,可能在下一篇中解決,當然這是後話)。

 

轉載請標明http://www.cnblogs.com/blue-lg/archive/2011/12/07/2279879.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章