最近在做頭發檢測的算法研究,在此做個總結。
發色檢測目前主要的方法有:1,基于顏色空間統計的發色檢測;2,基于概率模型、高斯模型的發色檢測;3,基于神經網絡機器學習的發色檢測;
這三種方法中,最穩定的是第3種,但是該方法實現起來比較復雜,樣本量大;最簡單的是第1種,但是不精確;
說實在的,這三種方法,都沒辦法完美檢測發色,也就是沒辦法避開同色的干擾,不過,今天本人還是要介紹一種,相對來講,比較實用的方法:
本文的算法使用最簡單的顏色空間模型和概率模型,參考文獻為:《Hair color modeling and head detection》,在此文獻基礎上修改而成。
為了便于理解,本文直接介紹算法實現過程,相信大家對于沒用的也不太想看呵呵,因此,對于理論,大家沒興趣的可以跳過。
理論基礎:
1,基于YCbCr顏色空間,對N個頭發區域像素進行 采樣統計,結果如下圖:

2,將統計結果投影在Cb-Cr平面,結果如下:

3,采用高斯混合概率模型對發色的色度概率分布進行描述:


4,根據Cb和Cr的取值范圍對當前像素進行膚色判斷:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if(Cb=115&&Cr>=115&&Cr<=143)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? P(i,j)為發色
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?else
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? P(i,j)非發色
上面1-4的過程即論文《Hair color modeling and head detection》中所介紹的方法,測試效果如下:


經過我的測試,論文中的方法檢測準確率很低,這里簡單放上兩張測試圖,大家可以看到,誤檢率很高,把較多的背景和膚色都檢測成了發色。
因此,本人對這個算法進行了改進,添加了一個約束條件:
由于發色主要是黑色為主,偏黃或者偏白,這幾種情況都跟RGB三分量中的R分量關系最密切,因此,本人添加了R約束:R<Th
Th是經驗值,這里我們實際使用中可以使用Th=60,這個值是我測試N張圖的到的經驗值,同時,也可以使用動態調節Th來獲取發色區域,這里我
給出幾張測試效果:

大家可以從效果上看出,改進的方法效果很不錯,呵呵,最后改進后的判斷條件如下:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if(Cb=115&&Cr>=115&&Cr<=143&&R<Th)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? P(i,j)為發色
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?else
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? P(i,j)非發色
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 默認值Th = 60
這里,給出C#代碼如下:
~~~
public Bitmap HairD(Bitmap src, int k )
{
Bitmap a = new Bitmap(src);
Rectangle rect = new Rectangle(0, 0, a.Width, a.Height);
System.Drawing.Imaging.BitmapData bmpData = a.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
int stride = bmpData.Stride;
unsafe
{
byte* pIn = (byte*)bmpData.Scan0.ToPointer();
byte* p;
int R, G, B;
double Cr, Cb, BrightV;
for (int y = 0; y < a.Height; y++)
{
for (int x = 0; x < a.Width; x++)
{
p = pIn;
R = p[2];
G = p[1];
B = p[0];
Cb = 128 - 37.797 * R / 255 - 74.203 * G / 255 + 112 * B / 255;
Cr = 128 + 112 * R / 255 - 93.768 * G / 255 - 18.214 * B / 255;
if (!(Cb >= 115 && Cb <= 141 && Cr >= 115 && Cr <= 143&&R<k))
{
pIn[0] = (byte)255;
pIn[1] = (byte)255;
pIn[2] = (byte)255;
}
pIn += 3;
}
pIn += stride - a.Width * 3;
}
}
a.UnlockBits(bmpData);
return a;
}
~~~
最后,放上一個DEMO,下載地址:[點擊打開鏈接](http://download.csdn.net/detail/trent1985/9217947)