zoukankan      html  css  js  c++  java
  • OpenCV——肤色检测

    一、RGB color space

    检测代码如下:

    void SkinRGB(IplImage* src,IplImage* dst)
    {
        //RGB颜色空间
        //均匀照明:R>95,G>40,B>20,R-B>15,R-G>15,R>B%R
        //侧向照明:R>200,G>210,B>170,R-B<=15,R>B,G>B
            
        int height = src->height, width = src->width, channel = src->nChannels, step = src->widthStep;
        int b = 0, g = 1, r = 2;
    
        cvZero(dst);
        unsigned char* p_src = (unsigned char*)src->imageData;
        unsigned char* p_dst = (unsigned char*)dst->imageData;
            
        for(int j = 0; j < height; j++){
            for(int i = 0; i < width; i++){
                if((p_src[j*step+i*channel+r] > 95 && p_src[j*step+i*channel+g] > 40 && p_src[j*step+i*channel+b] > 20 && 
                    (p_src[j*step+i*channel+r] - p_src[j*step+i*channel+b]) > 15 && (p_src[j*step+i*channel+r] - p_src[j*step+i*channel+g]) > 15) || 
                    (p_src[j*step+i*channel+r] > 200 && p_src[j*step+i*channel+g] > 210 && p_src[j*step+i*channel+b] > 170 && 
                    (p_src[j*step+i*channel+r] - p_src[j*step+i*channel+b]) <= 15 && p_src[j*step+i*channel+r] > p_src[j*step+i*channel+b] && 
                    p_src[j*step+i*channel+g] > p_src[j*step+i*channel+b]))
                    p_dst[j*width+i]=255;
            }
        }
    }

    二、二次多项式模式检测(RG color space)

    void cvSkinRG(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; } } }

    三、Ycrcb之cr分量+otsu阈值化

    原理:       a.将RGB图像转换到YCrCb颜色空间,提取Cr分量图像           

                    b.对Cr做自适应二值化处理(Ostu法)

    void cvSkinOtsu(IplImage* src, IplImage* dst)  
    {  
        //Cr自适应阈值法  
        //  
      
        IplImage* img_ycrcb=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3);  
        IplImage* img_cr=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);  
      
        cvCvtColor(src,img_ycrcb,CV_BGR2YCrCb);  
        cvSplit(img_ycrcb,0,img_cr,0,0);  
        cvThresholdOtsu(img_cr,img_cr);  
        cvCopy(img_cr,dst);  
      
        cvReleaseImage(&img_ycrcb);  
        cvReleaseImage(&img_cr);  
    }  
    
    
    
    void cvThresholdOtsu(IplImage* src, IplImage* dst)  
    {  
        int height=src->height,width=src->width,threshold=0;  
        double histogram[256]={0};  
        double average=0.0,max_variance=0.0,w=0.0,u=0.0;  
        IplImage* temp=cvCreateImage(cvGetSize(src),src->depth,1);  
        if(src->nChannels!=1)cvCvtColor(src,temp,CV_BGR2GRAY);  
        else cvCopy(src,temp);  
      
        unsigned char* p_temp=(unsigned char*)temp->imageData;  
      
        //计算灰度直方图  
        //  
        for(int j=0;j<height;j++) {  
            for(int i=0;i<width;i++) {  
                histogram[p_temp[j*width+i]]++;  
            }  
        }  
        for(int i=0;i<256;i++)histogram[i]=histogram[i]/(double)(height*width);  
      
        //计算平局值  
        for(int i=0;i<256;i++)average+=i*histogram[i];  
      
        for(int i=0;i<256;i++) {  
            w+=histogram[i];  
            u+=i*histogram[i];  
      
            double t=average*w-u;    
            double variance=t*t/(w*(1-w));    
            if(variance>max_variance) {    
                max_variance=variance;    
                threshold=i;    
            }    
        }  
        cvThreshold(temp,dst,threshold,255,CV_THRESH_BINARY);  
      
        cvReleaseImage(&temp);  
    }

    四、OpenCV自带肤色检测类——CvAdaptiveSkinDetector

     通过颜色阈值分割肤色部分,皮肤检测算法是在HSV空间进行。流程如下:

    //构造函数
    CvAdaptiveSkinDetector(int samplingDivider = 1, int morphingMethod = MORPHING_METHOD_NONE);
    
    /*
    参数1:样本采样的间隔,默认情况下为1,即表示不进行降采样
    参数2:图形学操作方式,即对用皮肤检测后的图像进行图形学操作。其取值有3种可能——MORPHING_METHOD_ERODE(只进行一次腐蚀操作);MORPHING_METHOD_ERODE_ERODE(连续进行2次腐蚀操作);MORPHING_METHOD_ERODE_DILATE(先进行一次腐蚀操作,后进行一次膨胀操作)
    */
    virtual void process(IplImage *inputBGRImage, IplImage *outputHueMask);
    
    /*
    参数1:需要进行皮肤检测的输入图像
    参数2:输出皮肤的掩膜图像——值为1代表该像素为皮肤,值为0代表非皮肤。
    */

    PS:这个函数只有opencv的c版本的,因为CvAdaptiveSkinDetector这个类放在opencv源码里的contrib目录里,即表示比较新的但不成熟的算法。

    #include <opencvcv.h>  
    #include <opencvhighgui.h>  
    #include <contribcontrib.hpp>  
    #include <corecore.hpp>  
    #include <imgprocimgproc.hpp>  
    #include<time.h>  
      
    int main()  
    { 
    CvCapture
    * capture=cvCreateCameraCapture(0); cvNamedWindow("Input Video",1); cvNamedWindow("Output Video",1); IplImage* img_src=NULL; IplImage* input_img=NULL; IplImage* output_mask=NULL; IplImage* output_img=NULL; clock_t start,finish; double duration; CvAdaptiveSkinDetector skin_detector(1,CvAdaptiveSkinDetector::MORPHING_METHOD_ERODE_DILATE); //定义肤色检测算子 while(1)
    { img_src
    =cvQueryFrame(capture); if(!img_src) break; cvShowImage("Input Video",img_src); if(input_img==NULL){ input_img=cvCreateImage(cvGetSize(img_src),img_src->depth,img_src->nChannels); } cvCopy(img_src,input_img); output_img=cvCreateImage(cvGetSize(img_src),img_src->depth,img_src->nChannels); cvZero(output_img); if(output_mask==NULL){ output_mask=cvCreateImage(cvGetSize(img_src),img_src->depth,1); } //肤色检测 // start=clock(); skin_detector.process(input_img,output_mask); finish=clock(); duration=(double)(finish-start)/CLOCKS_PER_SEC; printf("elapsed time :%.0f 毫秒 ",duration*1000); cvCopy(img_src,output_img,output_mask); cvShowImage("Output Video",output_img); char c=cvWaitKey(33); if(c==27)break; } cvReleaseCapture(&capture); cvDestroyWindow("Video"); }

    五、HSV检测

    void cvSkinHSV(IplImage* src,IplImage* dst)    
    {    
        IplImage* hsv=cvCreateImage(cvGetSize(src),8,3);    
        //IplImage* cr=cvCreateImage(cvGetSize(src),8,1);     
        //IplImage* cb=cvCreateImage(cvGetSize(src),8,1);     
        cvCvtColor(src,hsv,CV_BGR2HSV);    
        //cvSplit(ycrcb,0,cr,cb,0);     
        
        static const int V=2;    
        static const int S=1;    
        static const int H=0;    
        
        //IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);     
        cvZero(dst);    
        
        for (int h=0;h<src->height;h++) {    
            unsigned char* phsv=(unsigned char*)hsv->imageData+h*hsv->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 (phsv[H]>=7&&phsv[H]<=29)    
                {    
                        memcpy(pdst,psrc,3);    
                }    
                phsv+=3;    
                psrc+=3;    
                pdst+=3;    
            }    
        }    
        //cvCopyImage(dst,_dst);     
        //cvReleaseImage(&dst);     
    }    
  • 相关阅读:
    第一章 数据集散地:数据库
    第六章 使用ADO.NET查询和操作数据
    第五章 使用ADO.NET访问数据库
    第四章 深入C#的String类
    IOS框架和服务
    一步步调试解决iOS内存泄漏
    app跳转
    iOS 视频直播
    学习心得
    iOS中FMDB的使用
  • 原文地址:https://www.cnblogs.com/farewell-farewell/p/6010816.html
Copyright © 2011-2022 走看看