网上也有很多的资料,讲述怎么提取肤色的,大致有5种方法。这几种方法转载http://blog.csdn.net/augusdi/article/details/8865275

第一种:RGB color space

第二种:RG color space

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

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

第五种:HSV中 7<H<29

我来讲述一下提取肤色的原理。

这几种方法都不外乎一种操作,首先将图像的各个通道分离出来,如RGB  RG Ycrcb以及HSV几种单通道,然后对在各种通道上的数据分析,数据在一定范围内的图像提取出来,其余的数据都赋值0,这其实就是所谓的阈值处理,然而这个阈值会对光照,背景甚至摄像头的性能的影响,需要自己调整参数。

示例1:使用了opencv的cvInRangeS函数处理各个通道的数据,因为摄像头不好所以使用了高斯模糊以平滑图像,最后各处理后的通道图像按位与,合成一个图像。

void CAIGesture::SkinDetect(IplImage* src,IplImage* dst)
{
    IplImage* hsv = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);//用于存图像的一个中间变量,是用来分通道用的,分成hsv通道
    IplImage* tmpH1 = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1);//通道的中间变量,用于肤色检测的中间变量
    IplImage* tmpS1 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* tmpH2 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* tmpS3 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* tmpH3 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* tmpS2 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* H = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* S = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* V = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1);   
    IplImage* src_tmp1=cvCreateImage(cvGetSize(src),8,3);
    cvSmooth(src,src_tmp1,CV_GAUSSIAN,3,3);    //高斯模糊
    cvCvtColor(src_tmp1, hsv, CV_BGR2HSV );//颜色转换
    cvCvtPixToPlane(hsv,H,S,V,0);//分为3个通道
/*********************肤色检测部分**************/
    cvInRangeS(H,cvScalar(0.0,0.0,0,0),cvScalar(20.0,0.0,0,0),tmpH1);
    cvInRangeS(S,cvScalar(75.0,0.0,0,0),cvScalar(200.0,0.0,0,0),tmpS1);
    cvAnd(tmpH1,tmpS1,tmpH1,0);
    // Red Hue with Low Saturation
    // Hue 0 to 26 degree and Sat 20 to 90
    cvInRangeS(H,cvScalar(0.0,0.0,0,0),cvScalar(13.0,0.0,0,0),tmpH2);
    cvInRangeS(S,cvScalar(20.0,0.0,0,0),cvScalar(90.0,0.0,0,0),tmpS2);
    cvAnd(tmpH2,tmpS2,tmpH2,0);

// Red Hue to Pink with Low Saturation
    // Hue 340 to 360 degree and Sat 15 to 90
    cvInRangeS(H,cvScalar(170.0,0.0,0,0),cvScalar(180.0,0.0,0,0),tmpH3);
    cvInRangeS(S,cvScalar(15.0,0.0,0,0),cvScalar(90.,0.0,0,0),tmpS3);
    cvAnd(tmpH3,tmpS3,tmpH3,0);

// Combine the Hue and Sat detections
    cvOr(tmpH3,tmpH2,tmpH2,0);
    cvOr(tmpH1,tmpH2,tmpH1,0);

cvCopy(tmpH1,dst);

}

示例2:

主要原理就是通过在Cb Cr空间上找到一个可以拟合常规肤色分布的椭圆形,然后把在椭圆形区域内的像素点标记为肤色。

其实代码很简单,就是把Y Cb Cr三个通道分开,然后用指针分别对这三个通道的每一个像素进行处理。

需要作修改的就是if(y<100) (*pMask)=(value<700) ? 255:0; else (*pMask)=(value<850)? 255:0; 这条做阈值判断的命令

  1. void cvSkinSegment(IplImage* img, IplImage* mask){
  2. CvSize imageSize = cvSize(img->width, img->height);
  3. IplImage *imgY = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
  4. IplImage *imgCr = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
  5. IplImage *imgCb = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
  6. IplImage *imgYCrCb = cvCreateImage(imageSize, img->depth, img->nChannels);
  7. cvCvtColor(img,imgYCrCb,CV_BGR2YCrCb);
  8. cvSplit(imgYCrCb, imgY, imgCr, imgCb, 0);
  9. int y, cr, cb, l, x1, y1, value;
  10. unsigned char *pY, *pCr, *pCb, *pMask;
  11. pY = (unsigned char *)imgY->imageData;
  12. pCr = (unsigned char *)imgCr->imageData;
  13. pCb = (unsigned char *)imgCb->imageData;
  14. pMask = (unsigned char *)mask->imageData;
  15. cvSetZero(mask);
  16. l = img->height * img->width;
  17. for (int i = 0; i < l; i++){
  18. y  = *pY;
  19. cr = *pCr;
  20. cb = *pCb;
  21. cb -= 109;
  22. cr -= 152
  23. ;
  24. x1 = (819*cr-614*cb)/32 + 51;
  25. y1 = (819*cr+614*cb)/32 + 77;
  26. x1 = x1*41/1024;
  27. y1 = y1*73/1024;
  28. value = x1*x1+y1*y1;
  29. if(y<100)    (*pMask)=(value<700) ? 255:0;
  30. else        (*pMask)=(value<850)? 255:0;
  31. pY++;
  32. pCr++;
  33. pCb++;
  34. pMask++;
  35. }
  36. cvReleaseImage(&imgY);
  37. cvReleaseImage(&imgCr);
  38. cvReleaseImage(&imgCb);
  39. cvReleaseImage(&imgYCrCb);
  40. }

提取肤色信息原理及操作——opencv的更多相关文章

  1. 论文系统Step1:从日志记录中提取特定信息

    论文系统Step1:从日志记录中提取特定信息 前言 论文数据需要,需要实现从服务器日志中提取出用户的特定交互行为信息.日志内容如下: 自己需要获取"请求数据包一行的信息"及&quo ...

  2. python调用mediainfo工具批量提取视频信息

    写了2个脚本,分别是v1版本和v2版本 都是python调用mediainfo工具提取视频元数据信息 v1版本是使用pycharm中测试运行的,指定了视频路径 v2版本是最终交付给运营运行的,会把v2 ...

  3. 从APNIC提取IP信息

    从APNIC提取IP信息 https://blog.csdn.net/nullzeng/article/details/17538009 Apnic介绍简而言之,Apnic是全球5个地区级的Inter ...

  4. Logstash:Data转换,分析,提取,丰富及核心操作

    Logstash:Data转换,分析,提取,丰富及核心操作 Logstash plugins Logstash是一个非常容易进行扩张的框架.它可以对各种的数据进行分析处理.这依赖于目前提供的超过200 ...

  5. tika提取pdf信息异常

    org.apache.tika.sax.WriteOutContentHandler$WriteLimitReachedException: Your document contained more ...

  6. java 反射提取类信息, 动态代理 和过滤某些方法演示

    java 反射提取类信息, 动态代理 和过滤某些方法演示 package org.rui.classts.reflects; import java.lang.reflect.Constructor; ...

  7. JDBC程序优化--提取配置信息放到属性文件中

    JDBC程序优化--提取配置信息放到属性文件中 此处仅仅优化JDBC连接部分,代码如下: public class ConnectionFactory { private static String ...

  8. extract_by_one 根据二维数组中某字段来提取数组信息,查看有无重复信息

    public function tt(){ $param = array( array ( 'hykno' => '2222222-CB', 'tcdk_fid' => '458B6D70 ...

  9. 【BioCode】Elm格式中提取位点信息

    说明: ①Elm格式: PLMD ID    Uniprot Accession    Position     Type     Sequence   Species    PMIDsPlMD编号 ...

随机推荐

  1. Coins(hdu 2844 多重背包)

    Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  2. Hdu1001(1到100的和)

    常规算法: #include <stdio.h> int main() { // 常规算法 int a; while(scanf("%d",&a)!=EOF){ ...

  3. 【Xamarin挖墙脚系列:打造独特的Xamarin.IOS开发环境】

    苹果的产品,依赖特定的开发环境. Mac  +  Xcode  不可缺少.所以,必须有Mac系统. 1-虚拟机搭建 2-土豪有Mac电脑设备 但是我觉得还是顺带上Visual Studio才是完美.. ...

  4. Android EditText setOnClickListener事件 只有获取焦点才能响应 采用setOnTouchListener解决

    最近在学习Android开发,在编写程序的过程中,发现EditText setOnClickListener事件响应中,只有获取焦点的时候才会响应, 如当焦点在别的控件上时,只能先点击获取焦点,第二次 ...

  5. Cocos2d-x 2.1.5 简单动画

    Cocos2d新版本函数更改了一些. 下面的代码可以产生一个简单动画. //第一步:生成动画需要的数据 CCTexture2D *texture=CCTextureCache::sharedTextu ...

  6. 国际化标签 <fmt:bundle>&<fmt:message>的使用

    国际化标签 <fmt:bundle>&<fmt:message>的使用 Message.properties文件: name=www.gis520.com #info= ...

  7. Linux删除乱码文件或者目录

    Linux删除乱码文件或者目录 有时在Linux下面解压一些zip或者rar文件后会产生乱码文件或者目录,这个时候使用rm不能成功删除,需要使用一些特别的方法 来进行删除,下面是我经常使用的两种方法. ...

  8. iframe父子页面互调方法和属性

    1.iframe子页面调用 父页面js函数 子页面调用父页面函数只需要写上window.praent就可以了.比如调用a()函数,就写成: window.parent.a(); 子页面取父页面中的标签 ...

  9. 回归分析:非线性nlinfi

    今天测试.这首题,真的很头疼,第一次看到这个题,就知道要用nlinefit函数做,但是我一个地方没搞清楚, 花了我40多分钟还没做也来. 最后终于是调用的函数出错了.主要是没有将一个列抽出来.一个二维 ...

  10. Binary Tree Level Order Traversal 解答

    Question Given a binary tree, return the level order traversal of its nodes' values. (ie, from left ...