提取肤色信息原理及操作——opencv
网上也有很多的资料,讲述怎么提取肤色的,大致有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; 这条做阈值判断的命令
- void cvSkinSegment(IplImage* img, IplImage* mask){
- CvSize imageSize = cvSize(img->width, img->height);
- IplImage *imgY = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
- IplImage *imgCr = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
- IplImage *imgCb = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
- IplImage *imgYCrCb = cvCreateImage(imageSize, img->depth, img->nChannels);
- cvCvtColor(img,imgYCrCb,CV_BGR2YCrCb);
- cvSplit(imgYCrCb, imgY, imgCr, imgCb, 0);
- int y, cr, cb, l, x1, y1, value;
- unsigned char *pY, *pCr, *pCb, *pMask;
- pY = (unsigned char *)imgY->imageData;
- pCr = (unsigned char *)imgCr->imageData;
- pCb = (unsigned char *)imgCb->imageData;
- pMask = (unsigned char *)mask->imageData;
- cvSetZero(mask);
- l = img->height * img->width;
- for (int i = 0; i < l; i++){
- y = *pY;
- cr = *pCr;
- cb = *pCb;
- cb -= 109;
- cr -= 152
- ;
- x1 = (819*cr-614*cb)/32 + 51;
- y1 = (819*cr+614*cb)/32 + 77;
- x1 = x1*41/1024;
- y1 = y1*73/1024;
- value = x1*x1+y1*y1;
- if(y<100) (*pMask)=(value<700) ? 255:0;
- else (*pMask)=(value<850)? 255:0;
- pY++;
- pCr++;
- pCb++;
- pMask++;
- }
- cvReleaseImage(&imgY);
- cvReleaseImage(&imgCr);
- cvReleaseImage(&imgCb);
- cvReleaseImage(&imgYCrCb);
- }
提取肤色信息原理及操作——opencv的更多相关文章
- 论文系统Step1:从日志记录中提取特定信息
论文系统Step1:从日志记录中提取特定信息 前言 论文数据需要,需要实现从服务器日志中提取出用户的特定交互行为信息.日志内容如下: 自己需要获取"请求数据包一行的信息"及&quo ...
- python调用mediainfo工具批量提取视频信息
写了2个脚本,分别是v1版本和v2版本 都是python调用mediainfo工具提取视频元数据信息 v1版本是使用pycharm中测试运行的,指定了视频路径 v2版本是最终交付给运营运行的,会把v2 ...
- 从APNIC提取IP信息
从APNIC提取IP信息 https://blog.csdn.net/nullzeng/article/details/17538009 Apnic介绍简而言之,Apnic是全球5个地区级的Inter ...
- Logstash:Data转换,分析,提取,丰富及核心操作
Logstash:Data转换,分析,提取,丰富及核心操作 Logstash plugins Logstash是一个非常容易进行扩张的框架.它可以对各种的数据进行分析处理.这依赖于目前提供的超过200 ...
- tika提取pdf信息异常
org.apache.tika.sax.WriteOutContentHandler$WriteLimitReachedException: Your document contained more ...
- java 反射提取类信息, 动态代理 和过滤某些方法演示
java 反射提取类信息, 动态代理 和过滤某些方法演示 package org.rui.classts.reflects; import java.lang.reflect.Constructor; ...
- JDBC程序优化--提取配置信息放到属性文件中
JDBC程序优化--提取配置信息放到属性文件中 此处仅仅优化JDBC连接部分,代码如下: public class ConnectionFactory { private static String ...
- extract_by_one 根据二维数组中某字段来提取数组信息,查看有无重复信息
public function tt(){ $param = array( array ( 'hykno' => '2222222-CB', 'tcdk_fid' => '458B6D70 ...
- 【BioCode】Elm格式中提取位点信息
说明: ①Elm格式: PLMD ID Uniprot Accession Position Type Sequence Species PMIDsPlMD编号 ...
随机推荐
- 在Qt中怎样显示ASCII码大于127的字符
前段时间要显示“≤”符号找了挺久没找到方法,后面发现用以下方法可以解决: ushort gd[]={8805,0}; QString gteq=QString::fromUtf16(gd); 得 ...
- TrimPath - Js模板引擎
当页面中引用template.js文件之后,脚本将创建一个TrimPath对象供你使用. parseDOMTemplate(elementId,optionalDocument) //获得模板字符串代 ...
- SQL Server 2008空间数据应用系列三:SQL Server 2008空间数据类型
原文:SQL Server 2008空间数据应用系列三:SQL Server 2008空间数据类型 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server ...
- JDBC的使用——Statement
JDBC是Java最基本的数据库操作途径,虽然现在有了更高端的Hibernate和JPA,但是其实它们的底层还是用的这些最基本的JDBC.而且,如果开发一个小型的应用程序,使用Hibernate不免有 ...
- dp 46(再做一遍)
Robberies http://acm.hdu.edu.cn/showproblem.php?pid=2955 背包;第一次做的时候把概率当做背包(放大100000倍化为整数):在此范围内最多能抢多 ...
- hdu1556 Color the ball
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> ...
- Linux —— Shell编程之变量赋值和引用
Linux的shell编程是一种非常成熟的编程语言,它支持各种类型的变量.有三种主要的变量类型:环境变量.内部变量和用户变量. 环境变量(environment variable)是系统环境的一部分, ...
- Can you solve this equation?(二分)
Can you solve this equation? Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Ja ...
- VC2010 Working Directory
VC project setting --〉debug中的working directory指的是工作文件夹在哪里? project属性下,Debug以下的 Working Directory 是为了 ...
- 两分钟让你明白cocos2dx的屏幕适配策略
闲来无事,整理了一下cocos2dx的屏幕适配策略,本文适用于想快速理解cocos2dx适配的开发者. 我们先假设:以854 * 480 的屏幕为标准进行开发,当然,这也就是cocos2dx所说的设计 ...