肤色的检测可以利用肤色的HSV模型,通过计算图像的HSV模型中肤色的H和S分量中的一个或两个的直方图,再用该直方图反向投影至原图像,定位出肤色。

HSV颜色模型:



RGB模型是图像处理中常用的颜色模型,多用于颜色显示和图像处理,三维坐标中H(Hue)代表色调,S(Saturation)代表饱和度,V代表(Value)明度,理解起来很容易,是一种针对用户观感的一种颜色模型,侧重于色彩表示,什么颜色、深浅如何、明暗如何,跟人眼的直观感受很契合。

对于肤色的直方图,只计算H和S分量的直方图,所以肤色的明暗度对检测结果影响很小,提高了对不同灰度的鲁棒性。


检测的基本步骤:

1.截取一部分肤色区域,作为检测目标的样本;
2.对样本做直方图计算,并归一化直方图;
3.利用归一化后的直方图,通过calcBackProject函数在原图像中检索,与样本具有表现一致的直方图区域将会被作为肤色检测出来;


关键函数:calcHist、normalize 、calcBackProject

calcHist函数之前已经做过介绍,函数原型及参数说明可以ca见:直方图该怎么画


void normalize( InputArray src, OutputArray dst, double alpha=1, double beta=0,
                             int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray());


normalize函数作用是归一化计算出来的直方图。

第一个参数:InputArray类型的Src,输入的直方图数组;

第二个参数:OutputArray类型的dst,输出的归一化后的数组;

第三个参数:double型的alpha,归一化数组的最小值;

第四个参数:double型的beta,归一化数组的最大值;                                                                                            

第五个参数:int(枚举)型的norm_type,归一化方法;

第六个参数:int型的deype,值为-1, 指示归一化后的输出数组与输入数组类型相同

第七个参数:Mat(): 可选的掩码


calcBackProject函数原型:

calcBackProject(&image,       //目标图像  
                1,            // 图像个数  
                channels,     // 通道数量  
                histogram,    // 进行反投影的直方图  
                result,       // 结果图像  
                ranges,       // 每个维度的阈值  
                255.0         // 放缩因子  
                );  


代码实现:

#include "core/core.hpp"
#include "highgui/highgui.hpp"
#include "imgproc/imgproc.hpp"

using namespace cv;

Mat image,imageHSV,imageHist,imageNorm,imagecalcBack;
Mat imagegirl,imagegirlHSV;

int histSize=1;
float histR[]={0,255};
const float *histRange=histR;

int channels[]={0,1};

void TrackBarFun(int ,void(*));

int main(int argc,char *argv[])
{
	image=imread(argv[1]);
	imagegirl=imread(argv[2]);
	cvtColor(imagegirl,imagegirlHSV,CV_RGB2HSV);
	if(!image.data)
	{
		return -1;
	}
	cvtColor(image,imageHSV,CV_RGB2HSV);
	namedWindow("HSV");
	createTrackbar("bins控制","HSV",&histSize,100,TrackBarFun);	
	TrackBarFun(0,0);
	waitKey();
}
void TrackBarFun(int ,void(*))
{
	if(histSize==0)
	{
		histSize=1;
	}
	calcHist(&imageHSV,2,channels,Mat(),imageHist,1,&histSize,&histRange,true,false);
	normalize(imageHist,imageNorm,0,255,NORM_MINMAX,-1,Mat());
	calcBackProject(&imagegirlHSV,2,channels,imageNorm,imagecalcBack,&histRange,1,true);	
	imshow("Source",imagegirl);
	imshow("HSV",imagegirlHSV);
	imshow("CalcBack",imagecalcBack);
}

效果如下,拖动滑动条,在bins数目为7的时候,效果比较好:


 




posted on 2016-07-28 22:38  未雨愁眸  阅读(281)  评论(0编辑  收藏  举报