最近搞色彩认知计算,对于肤色检测也是兴趣使然。
我们在处理图像时,首先考虑的就是去噪,但是去噪不仅是去掉噪声,也需要考虑光照对图像造成的噪声,所以如果硬件跟得上的话,可以引入颜色恒常性计算来去噪,之后开始正题吧。
肤色检测说起来很简单,只要是色彩的空间分离,在这个过程中难免有误检,如果对目标能进行有监督的框定,再进行肤色检测,效果应该好很多。
接下来贴代码:
void SkinDetect(IplImage* src,IplImage* dst)
{
// 创建图像头
IplImage* hsv = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);//用于存图像的个中间变量,是用来分通道用的,分成hsv通道
IplImage* tmpH1 = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1);//通道的中间变量,用于肤色检测的中D间变量
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); //高斯模糊
// hue色度saturation饱和度value纯度
cvCvtColor(src_tmp1, hsv, CV_BGR2HSV );//颜色转换
cvSplit(hsv,H,S,V,0);//分为3个通道
/*********************肤色检测部分·**************/
cvInRangeS(H,cvScalar(26.0,0.0,0,0),cvScalar(34.0,0.0,0,0),tmpH1);
cvInRangeS(S,cvScalar(43.0,0.0,0,0),cvScalar(255.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(11.0,0.0,0,0),cvScalar(25.0,0.0,0,0),tmpH2);
cvInRangeS(S,cvScalar(43.0,0.0,0,0),cvScalar(255.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);
int avg,white=0,black=0;
CvScalar s;
for(int i=0;i<dst->height;i++)
{
for (int j = 0;j<dst->width;j++)
{
s = cvGet2D(dst,i,j);
if(s.val[0]==255)
white++;
else
black++;
}
}
printf("white = %dn",white);
printf("black = %dn",black);
cvReleaseImage(&hsv);
cvReleaseImage(&tmpH1);
cvReleaseImage(&tmpS1);
cvReleaseImage(&tmpH2);
cvReleaseImage(&tmpS2);
cvReleaseImage(&tmpH3);
cvReleaseImage(&tmpS3);
cvReleaseImage(&H);
cvReleaseImage(&S);
cvReleaseImage(&V);
cvReleaseImage(&src_tmp1);
}
测试图像:
得到的图像虽然不好,相信从代码里面能看到原因。