1. 程式人生 > >Win8 Metro(C#)數字影象處理--2.35影象膚色檢測演算法

Win8 Metro(C#)數字影象處理--2.35影象膚色檢測演算法



[函式名稱]

膚色檢測函式SkinDetectProcess(WriteableBitmap src)

[演算法說明]

  這個演算法是一篇學術論文演算法的實現,論文名字為“基於韌臉檢測和顏色分析的紅眼自動消除”(作者金秋明,王朔中),主要是採集並統計膚色畫素,得到膚色畫素在RGB顏色空間中的分佈範圍,以此作為畫素是否為膚色畫素的判斷標準及約束條件。具體內容大家可以在網路中搜索,由統計結果得到的膚色範圍如下公式2-(45),2-(46)所示:

<strong><span style="font-size:14px;">[函式程式碼]</span></strong>
        /// <summary>
        /// Skin detection.
        /// </summary>
        /// <param name="src">The source image.</param>
        /// <returns></returns>
        public static WriteableBitmap SkinDetectProcess(WriteableBitmap src)////36膚色檢測 
        {
            if (src != null)
            {
                int w = src.PixelWidth;
                int h = src.PixelHeight;
                WriteableBitmap srcImage = new WriteableBitmap(w, h);
                byte[] temp = src.PixelBuffer.ToArray();
                byte[] tempMask = (byte[])temp.Clone();
                int R, G, B, S;
                double r, g, b;
                for (int i = 0; i < temp.Length; i += 4)
                {
                    B = tempMask[i];
                    G = tempMask[i + 1];
                    R = tempMask[i + 2];
                    S = R + G + B;
                    r = (double)R / (double)(R + G + B + 1.0);
                    g = (double)G / (double)(R + G + B + 1.0);
                    b = (double)B / (double)(R + G + B + 1.0);
                    if (S != 0)
                    {
                        if ((r > (double)(95.0 / (double)S)) && (r < 1 - (double)(90.0 / (double)S)) && (g > (double)(50.0 / (double)S)) && ((r - g) > (double)(30.0 / (double)S)) && (r - g < 0.2))
                        {
                            temp[i] = (byte)B;
                            temp[i+1] = (byte)G;
                            temp[i+2] = (byte)R;
                        }
                        else
                        {
                            temp[i] = 0;
                            temp[i + 1] = 0;
                            temp[i + 2] = 0;
                        }
                    }
                    else
                    {
                        temp[i] = 0;
                        temp[i + 1] = 0;
                        temp[i + 2] = 0;
                    }
                }
                Stream sTemp = srcImage.PixelBuffer.AsStream();
                sTemp.Seek(0, SeekOrigin.Begin);
                sTemp.Write(temp, 0, w * 4 * h);
                return srcImage;
            }
            else
            {
                return null;
            }
        }