肤色检测 - OpenCV2.0
来源:互联网 发布:特朗普再喷朝鲜 知乎 编辑:程序博客网 时间:2024/04/28 00:11
#include "stdafx.h"
#include <cv.h>
#include <highgui.h>
#include <cvaux.h>
#include <cxcore.h>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <Windows.h>
#include <fstream>
#include <cmath>
using namespace std;
#pragma comment(lib,"cv200d")
#pragma comment(lib,"cvaux200d")
#pragma comment(lib,"cxcore200d")
#pragma comment(lib,"highgui200d")
#define SIN sin(2.53)
#define COS cos(2.53)
#define CrRows 65
#define CbRows 65 // 每个颜色分量的级数
int maxof3(int x, int y, int z)
{
int ret = -1000000;
if( ret < x ) ret = x;if( ret < y ) ret = y;if( ret < z ) ret = z;
return ret;
}
int minof3(int x, int y, int z)
{
int ret = 1000000;
if( ret > x ) ret = x;if( ret > y ) ret = y;if( ret > z ) ret = z;
return ret;
}
int _tmain(int argc, char* argv[])
{
CvCapture *cap = cvCreateFileCapture( "data/Lucero.avi" ) ;
IplImage *imgmask;
IplImage *imgsrc;
IplImage *imgYCrCb;
char path[20] = "data/a.bmp";
int crPerLen , cbPerLen, i, j, k;
int SkinArea = 0;
double Pskin = 0, NPskin = 0;
double Pc_skin[CrRows][CbRows], NPc_skin[CrRows][CbRows]; // P(c|skin)
char pathsrc[20] = "data/1.bmp";
crPerLen = cbPerLen = (235-16) / (CbRows); // 段长
int cr, y, cb, r, g, b;
memset(Pc_skin, 0, sizeof(Pc_skin)), memset(NPc_skin, 0, sizeof(NPc_skin));
CvFont font;
double hScale=1.0;double vScale=1.0;int lineWidth=3;
cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC, hScale,vScale,0,lineWidth);
// 获取先验知识`
for( i = 0; i < 4; i ++)
{
imgmask = cvLoadImage(path, 1);
imgsrc = cvLoadImage(pathsrc, 1);
imgYCrCb = cvCreateImage(cvGetSize(imgsrc), imgmask->depth, imgmask->nChannels);
cvCvtColor(imgsrc, imgYCrCb,CV_BGR2YCrCb);
for( j = 0; j < imgmask->height; j++) for( k = 0; k < imgmask->width; k ++)
{
r=CV_IMAGE_ELEM(imgmask,uchar,j,(k)*3+2);
g=CV_IMAGE_ELEM(imgmask,uchar,j,(k)*3+1);
b=CV_IMAGE_ELEM(imgmask,uchar,j,(k)*3); // 从Ycrcb颜色空间的原图中取出来,并且摒弃Y分量
cb=CV_IMAGE_ELEM(imgYCrCb,uchar,j,(k)*3+2);
cr=CV_IMAGE_ELEM(imgYCrCb,uchar,j,(k)*3+1);
y = CV_IMAGE_ELEM(imgYCrCb,uchar,j,(k)*3);
if( r == g && r == b && r == 0 )
{
SkinArea ++; //累计皮肤区域面积,有多少个点是皮肤颜色就是面积
Pc_skin[int(cr/crPerLen)][int(cb/cbPerLen)] += 1; // 统计在对应区间的颜色的拥有的个数,即直方图CrCb;
}
else
{
NPc_skin[int(cr/crPerLen)][int(cb/cbPerLen)] += 1;
}
}
pathsrc[5]++;
path[5]++;
if(imgsrc) cvReleaseImage( &imgsrc );
if(imgmask) cvReleaseImage( &imgmask);
if(imgmask) cvReleaseImage( &imgYCrCb);
}
imgmask = cvLoadImage("data/a.bmp", 1);
CvSize sz;
sz.height = 64, sz.width = 64;
double shit = 0;
IplImage *x = cvCreateImage(sz, 8, 3);
Pskin = double(SkinArea)/double(4*imgmask->height*imgmask->width); // P(skin)
NPskin = 1 - Pskin; // P(-skin)
CvScalar d;
for( j = 0; j < CrRows; j++) for( k = 0; k < CbRows; k ++)
{
Pc_skin[j][k] /= double(SkinArea), NPc_skin[j][k] /= double(SkinArea);
}
// P(skin): Pskin;
// P(-skin): NPskin;
// P(c|skin): Pc_skin;
// P(c|-skin): NPc_skin;
double theta, Bayesclsfy; //门限
if(Pskin != 0 ) theta = NPskin/Pskin;
else theta = 10000000000;
int crs, cbs;
cvNamedWindow("SkinDetect_Bayes");
cvNamedWindow("SkinDetect_RGB");
int cnt = 0;
while ( imgsrc = cvQueryFrame(cap) )
{
cvCvtColor(imgsrc, imgYCrCb,CV_BGR2YCrCb);
cvCopyImage(imgsrc, imgmask);
Sleep(1000);
for( j = 0; j < imgsrc->height; j++) for( k = 0; k < imgsrc->width; k ++)
{
// 贝叶斯方法肤色区域检测
cb=CV_IMAGE_ELEM(imgYCrCb,uchar,j,(k)*3+2);
cr=CV_IMAGE_ELEM(imgYCrCb,uchar,j,(k)*3+1);
y = CV_IMAGE_ELEM(imgYCrCb,uchar,j,(k)*3);
crs = int(cr/crPerLen), cbs = int(cb/cbPerLen);
Bayesclsfy = (Pc_skin[crs][cbs]*Pskin)/(NPc_skin[crs][cbs]*NPskin);
if(Pc_skin[crs][cbs]/NPc_skin[crs][cbs] > theta * 0.095 )
{
}
else
{
CV_IMAGE_ELEM(imgsrc,uchar,j,(k)*3+2) = 0;
CV_IMAGE_ELEM(imgsrc,uchar,j,(k)*3+1)= 0;
CV_IMAGE_ELEM(imgsrc,uchar,j,(k)*3) = 255;
}
r = CV_IMAGE_ELEM(imgmask,uchar,j,(k)*3+2) ;
g = CV_IMAGE_ELEM(imgmask,uchar,j,(k)*3+1);
b = CV_IMAGE_ELEM(imgmask,uchar,j,(k)*3) ;
//RGB量化检测肤色
if( r > 95 && g > 40 && b > 20 && maxof3(r,g,b) - minof3(r,g,b) > 15 && abs(r-g) > 15 && r > b )
{
CV_IMAGE_ELEM(imgmask,uchar,j,(k)*3+2) = 0;
CV_IMAGE_ELEM(imgmask,uchar,j,(k)*3+1)= 0;
CV_IMAGE_ELEM(imgmask,uchar,j,(k)*3) = 255;
}
}
cvPutText (imgmask,"JiangRuiYing, 20921069",cvPoint( 10,23 ), &font, cvScalar(0,0,255));
cvPutText (imgsrc,"JiangRuiYing, 20921069",cvPoint( 10,23 ), &font, cvScalar(0,0,255));
cvShowImage("SkinDetect_Bayes", imgsrc);
cvShowImage("SkinDetect_RGB", imgmask);
cvWaitKey(300);
}
if(imgsrc) cvReleaseImage( & imgsrc );
if(imgYCrCb) cvReleaseImage( &imgYCrCb );
if(imgmask) cvReleaseImage( &imgmask );
return 0;
}
// 主要是用了bayes方法的统计,统计处肤色大致的在cbcr这个二维空间上聚集的一些地方,另外照片的选取和mask的处理也比较的重要,和结果直接挂钩的.
其方法主要是这样的:
王东辉 老师入市说到:
P(skin)的计算方法:
任意挑选N幅图片,手工标注(比如利用photoshop软件)其中的皮肤区域和非皮肤区域,并另存为mask图像文件。然后编写程序,读取该mask文件。统计N幅图片中皮肤区域的总面积与所有图片总面积的比值,得到皮肤先验P(skin)。非皮肤先验P(~skin)=1-P(skin)。
P(c|skin)的计算方法:
对于N幅图片,根据相应的mask文件,读取每幅图片中皮肤区域的像素点RGB颜色值。转换RGB到合适的颜色坐标系统(比如HSV、YCbCr等),舍弃亮度维(V、Y等),在剩下的两维颜色空间中(HS、CbCr等)统计皮肤区域像素点的分布。假设你量化每个颜色坐标为64级,那么你可以得到P(c|skin)为一个64*64的两维数组。注意P(c|skin)需要归1化处理!
恩, 结果还是比较不错的比较起那个RGB量化方法的好的太多了. 贴图如下:
输入图片:
- 肤色检测 - OpenCV2.0
- opencv2肤色检测代码
- 肤色检测
- 肤色检测
- 肤色检测
- 肤色检测
- 肤色检测
- 肤色图像检测
- 肤色检测opencv
- OpenCV肤色检测
- matlab-肤色检测
- OpenCV中的肤色检测
- OpenCV编程->肤色检测
- java 肤色检测
- OpenCV肤色检测
- 利用OpenCV检测肤色
- 肤色检测合集
- 肤色检测代码示例
- 转 常见的几种c++的错误
- 离职表
- 富客户端开发框架:ExtJS
- Axis2 POJO WebService 测试
- 包容使生命更有宽度
- 肤色检测 - OpenCV2.0
- 求救 疑似木马
- 给查询增加一个序列
- How to use Bootstrap Manifest Generator tools
- c#之透明png图像窗体
- 请教高手,汇编动态分配内存原理
- 关于CPSR_cxsf
- SOAP or REST
- 运行SimpleDict例子编译出错,解决办法如下。