一个简单有趣的皮肤检测代码

Cite From: http://www.cnblogs.com/tornadomeet/archive/2012/12/05/2802428.html

前言

  最近课题研究上想采用皮肤信息,但是个人总是对皮肤信息应用在目标检测和目标识别上有排斥,认为皮肤信息完全不足以胜任这个工作。其实计算机视觉的最终实现是一个长期的过程,是AI领域一个经典的问题,所以在AI完全突破之前,任何对CV有用的信息都值得去深入研究,除非有一种算法能够在所有情况下都工作。好了,废话不扯了,进入正题,有偏见但是还是得使用它。皮肤模型中有单高斯,混合高斯,贝叶斯模型和椭圆模型等。经过前人学者大量的皮肤统计信息可以知道,如果将皮肤信息映射到YCrCb空间,则在CrCb二维空间中这些皮肤像素点近似成一个椭圆分布。因此如果我们得到了一个CrCb的椭圆,下次来一个坐标(Cr, Cb)我们只需判断它是否在椭圆内(包括边界),如果是,则可以判断其为皮肤,否则就是非皮肤像素点。

  开发环境:OpenCV2.4.3+QtCreator2.5.1

  实验基础

  本实验是参考小短文A super-simple skin detector in OpenCV,该文章里面首先直接给出了一个比较合理的椭圆,即该椭圆能够代表大部分人的皮肤信息CrCb的分布。椭圆的分布如下:

  

  说它比较有趣是因为我们是用一副图像来存储上面的椭圆的,而不是直接采用椭圆数学方程。该图像是二值图像,即椭圆区域内部为白色,其它地方为黑色。所以当其需要判断其它像素点时,只需将该像素点转换成Cr,Cb两个坐标,然后在上面的椭圆中找到该坐标的值,如果非0,则为皮肤,反之亦然。

  在实际代码中,该椭圆是采用绘画函数绘制到图片上的,一句代码而已:

ellipse(skinCrCbHist, Point(113, 155.6), Size(23.4, 15.2), 43.0, 0.0, 360.0, Scalar(255, 255, 255), -1);

  void ellipse(Mat& img, Point center, Size axes, double angle, double startAngle, double endAngle, const Scalar&color, int thickness=1, int lineType=8, int shift=0)

  该函数是用来在指定图片上绘制椭圆弧线的。

  参数image为需要绘制椭圆的图像;

  参数center是该椭圆的中心点坐标;

  参数axes是该椭圆的长半轴和短半轴;

  参数angle是该椭圆和水平方向上的旋转夹角;

  参数startAngle表示绘制椭圆弧线相对该椭圆自己的水平轴的起始角度;

  参数endAngel表示绘制椭圆弧线相对该椭圆自己的水平轴的终止角度;

  后面的参数比较普通就不介绍了。

  绘制椭圆曲线的示意图如下所示:

  

  实验结果

  检测前的图像:

  

  利用该算法进行皮肤检测后的二值图:

  

  实验代码及注释

  main.cpp:

#include <cv.h> #include <cxcore.h> #include <highgui.h>

#include <iostream> #include <iomanip> #include <algorithm> using namespace std; using namespace cv;

int main() {   char * ImageName = "f.jpg";    //椭圆皮肤模型  Mat skinCrCbHist = Mat::zeros(Size(256,256),CV_8UC1);  ellipse(skinCrCbHist,Point(113,155.6),Size(23.4,15.2),43.0,0.0,360.0,   Scalar(255,255,255),-1);  IplImage * inputimage = cvLoadImage(ImageName,CV_LOAD_IMAGE_COLOR);  if(!inputimage)   return -1;  CvSize imgSize = cvSize(inputimage->width,inputimage->height);  Mat output = Mat::zeros(cvSize(inputimage->width,inputimage->height),CV_8UC1);  IplImage *imgY = cvCreateImage(imgSize,IPL_DEPTH_8U,1);  IplImage *imgCr = cvCreateImage(imgSize,IPL_DEPTH_8U,1);  IplImage *imgCb = cvCreateImage(imgSize,IPL_DEPTH_8U,1);

 IplImage * imgYCrCb = cvCreateImage(imgSize,inputimage->depth,inputimage->nChannels);  cvCvtColor(inputimage,imgYCrCb,CV_BGR2YCrCb);  cvSplit(imgYCrCb,imgY,imgCr,imgCb,0);//获得图像的每个分量  CvScalar ycrcb;  for(int i =0;i<imgYCrCb->width;i++)   for(int j=0;j<imgYCrCb->height;j++)   {    ycrcb = cvGet2D(imgYCrCb,j,i);    if(skinCrCbHist.at<uchar>(ycrcb.val[1],ycrcb.val[2])>0)     output.at<uchar>(j,i) = 255;   }  cvShowImage("orig",inputimage);  imshow("tem",output);  while(1)  {   if(cvWaitKey(100) == 27)    break;  }  //fingerTip(ImageName);  cvReleaseImage(&inputimage);  return 0; }

  实验总结: 皮肤的椭圆模型确实可以用来做皮肤检测,一旦确定好了该椭圆就可以用来做皮肤检测了。

  参考文献:

A super-simple skin detector in OpenCV

皮肤检测与克服光线影响的连通域寻找

 http://docs.opencv.org/modules/core/doc/drawing_functions.html?highlight=ellipse#cv.Ellipse

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值