肤色检查

来源:互联网 发布:开淘宝店后要怎么操作 编辑:程序博客网 时间:2024/05/16 18:08

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 <opencv\cv.h>  #include <opencv\highgui.h>  #include <contrib\contrib.hpp>  #include <core\core.hpp>  #include <imgproc\imgproc.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 毫秒\n",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);     }    
0 0