zoukankan      html  css  js  c++  java
  • 图像直方图和反向投影的肤色检测

    肤色的检测可以利用肤色的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的时候,效果比较好:


     




  • 相关阅读:
    对svn分支合并类型和深度的理解
    SVN中trunk,branches,tags用法详解
    如何从dump中查找ASP.NET Session的数据【转】
    c++学习笔记
    柳永教授嫖娼案庭审记录
    C++资源之不完全导引(转载)
    不讨老婆之“不亦快哉”(三十三则)(李敖)
    在一个ajax extender 工程中实现多个 ajax extender 控件的方法
    Creating a new extender(zz)
    打标签
  • 原文地址:https://www.cnblogs.com/mtcnn/p/9412002.html
Copyright © 2011-2022 走看看