Python传统图像处理之皮肤区域检测详解

 更新时间:2021年12月01日 16:40:47   作者:watersink  
这篇文章主要介绍了在不同情景下对传统图像进行皮肤区域检测,文章中的代码具有一定的参考价值,感兴趣的小伙伴可以跟随小编一起来学习学习

1.RGB空间

肤色在RGB模型下的范围基本满足以下约束:

在均匀光照下应满足以下判别式:

R>95 AND G>40 B>20 AND MAX(R,G,B)-MIN(R,G,B)>15 AND ABS(R-G)>15 AND R>G AND R>B

在侧光拍摄环境下:

R>220 AND G>210 AND B>170 AND ABS(R-G)<=15 AND R>B AND G>B

代码:

def skinMask_rgb(image):
    b, g, r = cv2.split(image)
    mask_uniformity = (r>95)*(g>40)*(b>20)* (np.max(image, axis=2) -np.min(image,axis=2)>15)* (abs(r-g)>15)*(r>g)*(r>b)
    mask_side = (r>220)*(g>210)*(b>170)*(abs(r-g)<=15)*(r>b)*(g>b)
    mask = mask_uniformity|mask_side
    skin = np.array(mask, np.uint8)*255
    ratio = np.sum(skin/255)/(image.shape[0]*image.shape[1])
 
    return skin, ratio

效果:

2.Ycrcb空间

在RGB空间里人脸的肤色受亮度影响相当大,所以肤色点很难从非肤色点中分离出来,也就是说在此空间经过处理后,肤色点是离散的点,中间嵌有很多非肤色。如果把RGB转为YCrCb空间的话,可以忽略Y(亮度)的影响,因为该空间受亮度影响很小,肤色会产生很好的类聚。这样就把三维的空间降为二维的CrCb,肤色点会形成一定得形状。

133≤Cr≤173

77≤Cb≤127

代码:

def skinMask_YCrCb(image):
    YCrCb = cv2.cvtColor(image, cv2.COLOR_BGR2YCR_CB) #转换至YCrCb空间
    (y,cr,cb) = cv2.split(YCrCb) #拆分出Y,Cr,Cb值
    skin = np.zeros(cr.shape, dtype = np.uint8)
    (x,y) = cr.shape
    
    cr_mask1 = cr >= 133
    cr_mask2 = cr <= 173
    cr_mask = cr_mask1 * cr_mask2
 
    cb_mask1 = cb >= 77
    cb_mask2 = cb <= 127
    cb_mask = cb_mask1 * cb_mask2
    mask = cr_mask * cb_mask
    skin[mask] = 255
 
    ratio = np.sum(skin/255)/(x*y)
    return skin, ratio

效果:

3.Ycrcb空间+otsu

Y表示明亮度(Luminance或Luma),也就是灰阶值。Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异。而Cb反映的是RGB输入信号蓝色部分与RGB信号亮度值之间的差异。

将RGB图像转换到YCrCb颜色空间,提取Cr分量图像。对Cr做自二值化阈值分割处理(Otsu法)。

代码:

def skinMask_YCrCb_otsu(image):
    YCrCb = cv2.cvtColor(image, cv2.COLOR_BGR2YCR_CB) #转换至YCrCb空间
    (y,cr,cb) = cv2.split(YCrCb) #拆分出Y,Cr,Cb值
    
    ret, skin = cv2.threshold(cr, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
 
    ratio = np.sum(skin/255)/(image.shape[0]*image.shape[1])
    return skin, ratio

效果:

4.HSV空间

7<H<20

28<S<256

50<V<256

代码:

def skinMask_hsv(image):
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    h, s, v = cv2.split(hsv)
 
    mask = (h>7)*(h<20)*(s>28)*(v>50)
    skin = np.array(mask, np.uint8)*255
    ratio = np.sum(skin/255)/(image.shape[0]*image.shape[1])
    return skin, ratio

效果:

5.opencv自带肤色检测类AdaptiveSkinDetector

已经从opencv 3以上版本中移除,opencv 2中函数。

6.基于椭圆模型

将皮肤信息映射到YCrCb空间,则在CrCb二维空间中这些皮肤像素点近似成一个椭圆分布。因此如果我们得到了一个CrCb的椭圆,下次来一个坐标(Cr, Cb)我们只需判断它是否在椭圆内(包括边界),如果是,则可以判断其为皮肤,否则就是非皮肤像素点。

代码:

def skinMask_ellipse(image):
    YCrCb = cv2.cvtColor(image, cv2.COLOR_BGR2YCR_CB) #转换至YCrCb空间
    (y,cr,cb) = cv2.split(YCrCb) #拆分出Y,Cr,Cb值
 
    skinCrCbHist = np.zeros((256,256),np.uint8)
    skinCrCbHist = cv2.ellipse(skinCrCbHist, (113, 155), (23, 15), 43.0, 0.0, 360.0, (255, 255, 255), -1)
    cv2.imwrite("ww.jpg", skinCrCbHist)
 
    skin = cv2.remap(skinCrCbHist, cb.astype(np.float32), cr.astype(np.float32), interpolation=cv2.INTER_LINEAR)
    ratio = np.sum(skin/255)/(image.shape[0]*image.shape[1])
    return skin, ratio

效果:

椭圆模型

效果

7.直方图反向投影

反向投影可以用来做图像分割,寻找感兴趣区间。可以寻找任何的roi,这里将其用作寻找人体肤色。它会输出与输入图像大小相同的图像,每一个像素值代表了输入图像上对应点属于目标对象的概率,简言之,输出图像中像素值越高的点越可能代表想要查找的目标。直方图投影经常与camshift(追踪算法)算法一起使用。

操作步骤:

(1)截取若干张不同肤色的图片,最好覆盖常见的所有肤色(如下图)

(2)对所有肤色的图片一起做色彩直方图(利用OpenCV中的calcHist函数)

(3)新建一个与待检测图片同尺寸的灰度图片,找到待检测图片中每颗像素点的颜色在色彩直方图中对应栅格的数值(即统计中出现的次数),并将该数值赋值予新建灰度图片中与该检测像素同位置的像素(利用OpenCV中的calcBackProject函数)。图像中像素亮度越高,待检测图像该位置处是肤色的概率越大。

代码:

def skinMask_hist_backproject(target, roi_image):
    #roi图片,就想要找的的图片
    hsv = cv2.cvtColor(roi_image,cv2.COLOR_BGR2HSV)
 
    #目标搜索图片
    hsvt = cv2.cvtColor(target,cv2.COLOR_BGR2HSV)
 
    #计算目标直方图
    roihist = cv2.calcHist([hsv],[0,1],None,[180,256],[0,180,0,256])
    #归一化,参数为原图像和输出图像,归一化后值全部在2到255范围
    cv2.normalize(roihist,roihist,0,255,cv2.NORM_MINMAX)
    dst = cv2.calcBackProject([hsvt],[0,1],roihist,[0,180,0,256],1)
 
 
    #卷积连接分散的点
    disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
    dst = cv2.filter2D(dst,-1,disc)
 
    ret,skin = cv2.threshold(dst,50,255,0)
 
    ratio = np.sum(skin/255)/(target.shape[0]*target.shape[1])
return skin, ratio

效果: 

 

以上就是Python传统图像处理之皮肤区域检测详解的详细内容,更多关于Python 皮肤区域检测的资料请关注脚本之家其它相关文章!

相关文章

  • Python中三种命令行参数利用方式详解

    Python中三种命令行参数利用方式详解

    Python的命令行参数,提供了很多有用的功能,可以方便调试和运行,这篇文章主要给大家介绍了关于Python中三种命令行参数利用方式的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • Python将数据生成二维码的四种方法实例代码

    Python将数据生成二维码的四种方法实例代码

    二维码在日常生活中非常常见,广泛应用于支付、登录验证、信息分享等场景,下面这篇文章主要给大家介绍了关于Python将数据生成二维码的四种方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-09-09
  • Django 路由系统URLconf的使用

    Django 路由系统URLconf的使用

    这篇文章主要介绍了Django 路由系统URLconf的使用,详细的介绍了什么是URLconf以及如何使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • python周期任务调度工具Schedule使用详解

    python周期任务调度工具Schedule使用详解

    这篇文章主要为大家介绍了python周期任务调度工具Schedule的使用及示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2021-11-11
  • Python安装tar.gz格式文件方法详解

    Python安装tar.gz格式文件方法详解

    这篇文章主要介绍了Python安装tar.gz格式文件方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • python中星号变量的几种特殊用法

    python中星号变量的几种特殊用法

    不知道大家知不知道在Python中,星号除了用于乘法数值运算和幂运算外,还有一种特殊的用法"在变量前添加单个星号或两个星号",实现多参数的传入或变量的拆解,本文将详细介绍"星号参数"的用法。有需要的可以参考借鉴。
    2016-09-09
  • Python的进制转换和ASCLL转换你了解吗

    Python的进制转换和ASCLL转换你了解吗

    这篇文章主要为大家详细介绍了Python的进制转换和ASCLL转换,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • Python 含参构造函数实例详解

    Python 含参构造函数实例详解

    这篇文章主要介绍了Python 含参构造函数实例详解的相关资料,需要的朋友可以参考下
    2017-05-05
  • Python实现一键整理百度云盘中重复无用文件

    Python实现一键整理百度云盘中重复无用文件

    有没有头疼过百度云盘都要塞满了,可是又没有工具能剔除大量重复无用的文件?这里教你一个用Python实现的简单方法,通过整理目录的方式来处理我们云盘中无用的文件吧
    2022-08-08
  • python如何保证输入键入数字的方法

    python如何保证输入键入数字的方法

    今天小编就为大家分享一篇python如何保证输入键入数字的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-08-08

最新评论