天天看點

五種基于RGB色彩空間統計的皮膚檢測算法

最近一直在研究多臉譜識别以及如何分辨多個皮膚區域是否是人臉的問題

網上找了很多資料,看了很多篇文章,将其中基于rgb色彩空間識别皮膚

的統計算法做了一下總結,統計識别方法主要是簡單相比與很多其它基于

機器學習的算法,本人總結了五種rgb色彩空間的統計算法源碼如下:

skin filter1:

public class skinfilter1 extends abstractbufferedimageop {  

    @override  

    public bufferedimage filter(bufferedimage src, bufferedimage dest) {  

        int width = src.getwidth();  

        int height = src.getheight();  

        if ( dest == null )  

            dest = createcompatibledestimage( src, null );  

        int[] inpixels = new int[width*height];  

        int[] outpixels = new int[width*height];  

        getrgb( src, 0, 0, width, height, inpixels );  

        int index = 0;  

        for(int row=0; row<height; row++) {  

            int ta = 0, tr = 0, tg = 0, tb = 0;  

            for(int col=0; col<width; col++) {  

                index = row * width + col;  

                ta = (inpixels[index] >> 24) & 0xff;  

                tr = (inpixels[index] >> 16) & 0xff;  

                tg = (inpixels[index] >> 8) & 0xff;  

                tb = inpixels[index] & 0xff;  

                // detect skin method...  

                double sum = tr + tg + tb;  

                if (((double)tr/(double)tb > 1.185) &&   

                    ((double)(tr*tb)/(double)(sum*sum)>0.107) &&  

                    ((double)(tr*tg)/(double)(sum*sum)>0.112))  

                {  

                    tr = tg = tb = 0; // black - skin detected!!  

                } else {  

                    tr = tg = tb = 255; // white color means non-skin pixel  

                }  

                outpixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;  

            }  

        }  

        setrgb( dest, 0, 0, width, height, outpixels );  

        return dest;  

    }  

}  

skin filter2:

public class skinfilter2 extends abstractbufferedimageop {  

                if(((double)3*tb*tr*tr/(double)(sum*sum*sum)>0.1276)&&  

                    ((double)(tr*tb+tg*tg)/(double)(tg*tb)>2.14)&&  

                    ((double)(sum)/(double)(3*tr)+(double)(tr-tg)/(double)(sum)<2.7775))  

                    tr = tg = tb = 0;  

                    tr = tg = tb = 255;  

skin filter3:

public class skinfilter3 extends abstractbufferedimageop {  

                if (((double)tg / (double)tg - (double)tr / (double)tb <= -0.0905) &&  

                    ((double)(sum) / (double)(3 * tr) + (double)(tr - tg) / (double)(sum) <= 0.9498))  

skin filter4:

import java.awt.image.bufferedimage;  

/** 

 * this skin detection is absolutely good skin classification, 

 * i love this one very much 

 *  

 * this one should be always primary skin detection  

 * from all five filters 

 * @author zhigang 

 * 

 */  

public class skinfilter4 extends abstractbufferedimageop {  

                if (((double)tb/(double)tg<1.249) &&  

                    ((double)sum/(double)(3*tr)>0.696) &&  

                    (0.3333-(double)tb/(double)sum>0.014) &&  

                    ((double)tg/(double)(3*sum)<0.108))  

        setrgb(dest, 0, 0, width, height, outpixels);  

skin filter5:

 * this is very good skin detection 

 * get real skin segmentation correctly.... 

 * ohh... cool 

public class skinfilter5 extends abstractbufferedimageop {  

                if (((double)tg/(double)tb - (double)tr/(double)tg<=-0.0905)&&  

                ((double)(tg*sum)/(double)(tb*(tr-tg))>3.4857)&&  

                ((double)(sum*sum*sum)/(double)(3*tg*tr*tr)<=7.397)&&  

                ((double)sum/(double)(9*tr)-0.333 > -0.0976))  

總結一下:

似乎filter3的效果與filter1的效果不是很好,filter5, filter4的效果感覺

還是很好的,基本上可以符合實際要求。