• 图像肤色初步检測实现


    版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/utimes/article/details/24836341

    肤色检測输出结果中有很多瑕疵,待于进一步处理(如:滤波操作.....)。在此贴出几种图像肤色检測相关代码。供大家參考。

    第一种:RGB color space

    // skin region location using rgb limitation  
    void ImageSkin::ImageSkinRGB(IplImage* rgb,IplImage* _dst)  
    {  
        assert(rgb->nChannels==3&& _dst->nChannels==3);  
      
        static const int R=2;  
        static const int G=1;  
        static const int B=0;  
      
        IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);  
        cvZero(dst);  
      
        for (int h=0;h<rgb->height;h++) {  
            unsigned char* prgb=(unsigned char*)rgb->imageData+h*rgb->widthStep;  
            unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;  
            for (int w=0;w<rgb->width;w++) {  
                if ((prgb[R]>95 && prgb[G]>40 && prgb[B]>20 &&  
                    prgb[R]-prgb[B]>15 && prgb[R]-prgb[G]>15)||//uniform illumination   
                    (prgb[R]>200 && prgb[G]>210 && prgb[B]>170 &&  
                    abs(prgb[R]-prgb[B])<=15 && prgb[R]>prgb[B]&& prgb[G]>prgb[B]) 
                    ) {  
                        memcpy(pdst,prgb,3);  
                }             
                prgb+=3;  
                pdst+=3;  
            }  
        }  
        cvCopyImage(dst,_dst);  
        cvReleaseImage(&dst);  
    }  
    

    另外一种:RG color space

    // skin detection in rg space  
    void ImageSkin::ImageSkinRG(IplImage* rgb,IplImage* gray)  
    {  
        assert(rgb->nChannels==3&&gray->nChannels==1);  
          
        const int R=2;  
        const int G=1;  
        const int B=0;  
      
        double Aup=-1.8423;  
        double Bup=1.5294;  
        double Cup=0.0422;  
        double Adown=-0.7279;  
        double Bdown=0.6066;  
        double Cdown=0.1766;  
        for (int h=0;h<rgb->height;h++) {  
            unsigned char* pGray=(unsigned char*)gray->imageData+h*gray->widthStep;  
            unsigned char* pRGB=(unsigned char* )rgb->imageData+h*rgb->widthStep;  
            for (int w=0;w<rgb->width;w++)   
            {  
                int s=pRGB[R]+pRGB[G]+pRGB[B];  
                double r=(double)pRGB[R]/s;  
                double g=(double)pRGB[G]/s;  
                double Gup=Aup*r*r+Bup*r+Cup;  
                double Gdown=Adown*r*r+Bdown*r+Cdown;  
                double Wr=(r-0.33)*(r-0.33)+(g-0.33)*(g-0.33);  
                if (g<Gup && g>Gdown && Wr>0.004)  
                {  
                    *pGray=255;  
                }  
                else  
                {   
                    *pGray=0;  
                }  
                pGray++;  
                pRGB+=3;  
            }  
        }  
      
    }  
    

    第三种:otsu阈值化

    // reference: Rafael C. Gonzalez. Digital Image Processing Using MATLAB  
    void ImageSkin::ImageThresholdOtsu(IplImage* src, IplImage* dst)  
    {  
        int height=src->height;  
        int width=src->width;  
      
        //histogram  
        float histogram[256]={0};  
        for(int i=0;i<height;i++) {  
            unsigned char* p=(unsigned char*)src->imageData+src->widthStep*i;  
            for(int j=0;j<width;j++) {  
                histogram[*p++]++;  
            }  
        }  
        //normalize histogram  
        int size=height*width;  
        for(int i=0;i<256;i++) {  
            histogram[i]=histogram[i]/size;  
        }  
      
        //average pixel value  
        float avgValue=0;  
        for(int i=0;i<256;i++) {  
            avgValue+=i*histogram[i];  
        }  
      
        int threshold;    
        float maxVariance=0;  
        float w=0,u=0;  
        for(int i=0;i<256;i++) {  
            w+=histogram[i];  
            u+=i*histogram[i];  
      
            float t=avgValue*w-u;  
            float variance=t*t/(w*(1-w));  
            if(variance>maxVariance) {  
                maxVariance=variance;  
                threshold=i;  
            }  
        }  
      
        cvThreshold(src,dst,threshold,255,CV_THRESH_BINARY);  
    }  

    第四种:Ycrcb之cr分量+otsu阈值化

    void ImageSkin::ImageSkinOtsu(IplImage* src, IplImage* dst)  
    {  
        assert(dst->nChannels==1&& src->nChannels==3);  
      
        IplImage* ycrcb=cvCreateImage(cvGetSize(src),8,3);  
        IplImage* cr=cvCreateImage(cvGetSize(src),8,1);  
        cvCvtColor(src,ycrcb,CV_BGR2YCrCb);  
        cvSplit(ycrcb,0,cr,0,0);  
      
    	ImageThresholdOtsu(cr,cr);  
        cvCopyImage(cr,dst);  
        cvReleaseImage(&cr);  
        cvReleaseImage(&ycrcb);  
    }  
    
    

    第五种:YCrCb中133<=Cr<=173 77<=Cb<=127

    void ImageSkin::ImageSkinYUV(IplImage* src,IplImage* dst)  
    {  
        IplImage* ycrcb=cvCreateImage(cvGetSize(src),8,3);  
        //IplImage* cr=cvCreateImage(cvGetSize(src),8,1);  
        //IplImage* cb=cvCreateImage(cvGetSize(src),8,1);  
        cvCvtColor(src,ycrcb,CV_BGR2YCrCb);  
        //cvSplit(ycrcb,0,cr,cb,0);  
      
        static const int Cb=2;  
        static const int Cr=1;  
        static const int Y=0;  
      
        //IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);  
        cvZero(dst);  
      
        for (int h=0;h<src->height;h++) {  
            unsigned char* pycrcb=(unsigned char*)ycrcb->imageData+h*ycrcb->widthStep;  
            unsigned char* psrc=(unsigned char*)src->imageData+h*src->widthStep;  
            unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;  
            for (int w=0;w<src->width;w++) {  
                if (pycrcb[Cr]>=133&&pycrcb[Cr]<=173&&pycrcb[Cb]>=77&&pycrcb[Cb]<=127)  
                {  
                        memcpy(pdst,psrc,3);  
                }  
                pycrcb+=3;  
                psrc+=3;  
                pdst+=3;  
            }  
        }  
        //cvCopyImage(dst,_dst);  
        //cvReleaseImage(&dst);  
    }  
    

    主程序測试

    IplImage* img= cvLoadImage("test.jpg");      
    IplImage* dstRGB=cvCreateImage(cvGetSize(img),8,3);    
    IplImage* dstRG=cvCreateImage(cvGetSize(img),8,1);    
    IplImage* dst_crotsu=cvCreateImage(cvGetSize(img),8,1);    
    IplImage* dst_YUV=cvCreateImage(cvGetSize(img),8,3);     
        
    cvNamedWindow("Original WIN", CV_WINDOW_AUTOSIZE);    
    cvShowImage("Original WIN", img); 
    cvWaitKey(0);    
    
    ImageSkin ImgS;
    ImgS.ImageSkinRGB(img,dstRGB);    
    cvNamedWindow("ImageSkin WIN", CV_WINDOW_AUTOSIZE);    
    cvShowImage("ImageSkin WIN", dstRGB);
    cvWaitKey(0);
    
    ImgS.ImageSkinRG(img,dstRG);  
    cvNamedWindow("ImageSkinRG WIN", CV_WINDOW_AUTOSIZE);    
    cvShowImage("ImageSkinRG WIN", dstRG);    
    cvWaitKey(0); 
       
    ImgS.ImageSkinOtsu(img,dst_crotsu);    
    cvNamedWindow("ImageSkinOtsu WIN", CV_WINDOW_AUTOSIZE);    
    cvShowImage("ImageSkinOtsu WIN", dst_crotsu);    
    cvWaitKey(0);
    
    ImgS.ImageSkinYUV(img,dst_YUV);    
    cvNamedWindow("ImageSkinYUV WIN", CV_WINDOW_AUTOSIZE);    
    cvShowImage("ImageSkinYUV WIN", dst_YUV);        



    探讨OpenCV》专栏QQ群:195358461

    关于Image Engineering & Computer Vision很多其它讨论与交流,敬请关注本博客和新浪微博songzi_tea.





  • 相关阅读:
    SpringBoot项目启动与关闭脚本
    springboot mybatis启动初始化数据库
    springboot mybatis多数据库支持
    Tomcat配置https访问
    Oracle批量生成版本
    Oracle创建用户表空间
    OracleServiceXE服务没有了
    IDEA离线升级
    js过滤并校验XSS
    docker命令
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/9946884.html
Copyright © 2020-2023  润新知