学习OpenCV——皮肤检测类:CvAdaptiveSkinDetector

OpenCV原来自带的皮肤检测类CvAdaptiveSkinDetector,可以通过颜色阈值分割肤色部分,皮肤检测算法是在HSV空间进行,没什么技术含量。

 

OpenCV自带是算法的参考文献有网友说是An adaptive real-time skin detector based on Hue thresholding: A comparison on two motion tracking methods,主要是把皮肤阈值分割和运动检测相结合。该算法的流程图如下所示:

  

程序的流程图如下所示:

  

  

 

 

下面来看看CvAdaptiveSkinDetector类中的2个比较重要的函数:

CvAdaptiveSkinDetector(int samplingDivider = 1, int morphingMethod = MORPHING_METHOD_NONE);

该函数为类的构造函数,

参数1表示的是样本采样的间隔,默认情况下为1,即表示不进行降采样;

参数2为图形学操作方式,即对用皮肤检测后的图像进行图形学操作。其取值有3种可能:MORPHING_METHOD_ERODE,则表示只进行一次腐蚀操作;MORPHING_METHOD_ERODE_ERODE,则表示连续进行2次腐蚀操作;MORPHING_METHOD_ERODE_DILATE,则表示先进行一次腐蚀操作,后进行一次膨胀操作。

 

virtual void process(IplImage *inputBGRImage, IplImage *outputHueMask);

该函数为皮肤检测的核心函数,

参数1为需要进行皮肤检测的输入图像;

参数2为输出皮肤的掩膜图像,如果其值为1,代表该像素为皮肤,否则当其为0时,代表为非皮肤。

 

另外需要注意的是,这个函数只有opencv的c版本的,因为CvAdaptiveSkinDetector这个类放在opencv源码里的contrib目录里,即表示比较新的但不成熟的算法,所以暂时没有提供c++版本的opencv。因此参数1和参数2的图像数据类型都是IplImage,如果要使用Mat,就得先进行一个小小的转换。

*IplImage与Mat的转换:

src_img = &src_mat.operator IplImage();   //convert mat to IplImage;

Mat dst_mask = 255*Mat(dst_img);  //convert IplImage to Mat;

 

关于CvAdaptiveSkinDetector类的内容具体细节可以参考:http://www.cnblogs.com/tornadomeet/archive/2012/11/28/2793532.html

 

代码

Mat skin(const Mat& src_mat)
{
	IplImage *src_img, *dst_img;
	Mat dst_mat;
	CvAdaptiveSkinDetector skin_detector(1,CvAdaptiveSkinDetector::MORPHING_METHOD_NONE);//定义,初始化
	src_img = &src_mat.operator IplImage();//convert mat to IplImage
	dst_img = cvCreateImage(cvSize(src_img->width, src_img->height), IPL_DEPTH_8U,1);
	skin_detector.process(src_img,dst_img);//操作
	Mat dst_mask = 255*Mat(dst_img);
	src_mat.copyTo(dst_mat,dst_mask);
	return dst_mat;
}


 

由图像可见,实验效果实在不尽如人意。还不如以前自己写的皮肤检测函数的效果好

(学习OpenCV——hand tracking手势跟踪,学习OpenCV——肤色检测),只不过这个已经被OpenCV集成,以后可以方便的调用,而且据说跟运动的物体结合效果会好一些。