图像的给定像素的皮肤概率

时间:2015-02-27 16:34:39

标签: image-processing computer-vision

给定图像所有像素的RGB值,我们如何找到给定像素的肤色概率以及图像的肤色百分比。

1 个答案:

答案 0 :(得分:5)

Google上的Noodling告诉我,白种人的肤色经常,或者通常,或者有时可能符合以下规则:

Blue channel:  140-180
Green channel: Blue * 1.15
Red channel:   Blue * 1.5

因此,考虑到这一点,我使用此命令行制作了一些与ImageMagick相对应的颜色样本:

#!/bin/bash
for b in $(seq 140 5 180); do
  g=$(echo "$b * 1.15/1" | bc)
  r=$(echo "$b * 1.5/1"  | bc)
  convert -label "R:$r,G:$g,B:$b" -size 200x200 xc:"rgb($r,$g,$b)" miff:-
done | montage - -frame 5 -tile 3x swatches.png

得到了这个:

enter image description here

好的,那些看起来很合理,现在我尝试使用它们来检测肤色,再次使用ImageMagick。就目前而言,只有这样你才能看到它,我将把我发现的石灰绿色变为肤色,使用它正好在上面确定的色调范围的中间:

convert -fuzz 5% face1.jpg -fill lime -opaque "rgb(240,184,160)" out.jpg

enter image description here

嗯,不是很好。可能会增加模糊性?

enter image description here

嗯,还是很垃圾 - 只捡起部分皮肤和一些白衬衫领。不同的面孔可能?

enter image description here

好吧,在检测到他时并不坏,虽然注意到它完全无法检测到他的右侧,但是我们可以从粉红色的凯迪拉克身上看到一些问题:

enter image description here

和Piggy小姐下面......

enter image description here

也许我们可以在搜索中更有针对性,虽然我无法在3-D中绘制它,但我可以在2-D中解释。我们不是在我们的范围中间瞄准单个大圆(实际上是三维空间中的球体),也许我们可以定位沿着我们的范围扩展的一些较小的圆,从而包含更少的外来颜色......洋红色代表模糊的程度。所以不是这样:

enter image description here

我们可以这样做:

enter image description here

使用此命令:

convert -fuzz 13% face1.jpg -fill lime \
   -opaque "rgb(219,168,146)"          \
   -opaque "rgb(219,168,146)"          \
   -opaque "rgb(255,198,172)" out.jpg

enter image description here

所以,你可以看到仅使用RGB值很难找到肤色,我甚至还没有开始处理不同的种族,不同的灯光等。

另一种方法可能是使用不同的色彩空间,例如HSL - 色调饱和度和亮度。我们对Lightness不太感兴趣,因为这只是曝光的一个功能,因此我们寻找与皮肤相匹配的色调和一定程度的饱和度以避免褪色。您可以使用ImageMagick这样做:

#!/bin/bash
convert face1.jpg -colorspace hsl -separate          \
   \( -clone 0 -threshold 7% -negate +write h.png \) \
   \( -clone 1 -threshold 30% +write s.png        \) \
   -delete 0-2 -evaluate-sequence min out.png

这就是说...取图像face1.jpg并将其转换为HSL颜色空间,然后分层,这样我们现在在堆栈中有3个图像。 image 0是Hue,image 1是饱和度,image 2是亮度。下一行。取Hue图层并将其阈值设置为7%,这意味着小红色,将其反转并保存(只有这样你才能看到它)为h.png。下一行。取饱和度图层,然后说" 任何超过30%的饱和度对我来说都足够",然后保存为文件s.png。下一行。从原始图像中删除3个原始图层(HS& L),只留下阈值色调和阈值饱和度图层。现在把它们放在彼此的顶部并选择最小的那个并保存它。关键是可以使用Hue或Saturation层来gate选择哪些像素。

以下是文件,首先是Hue(h.png):

enter image description here

接下来的饱和度(s.png):

enter image description here

现在是合并的输出文件。

enter image description here

一旦你的算法被整理出来以决定哪些像素是肤色的,你需要计算它们以计算你寻找的百分比。这很简单......我们所做的就是将所有非石灰绿色变为黑色(因此在平均值中计为零),然后将图像调整为单个像素,并将其颜色设置为文本:

convert -fuzz 13% face1.jpg -fill lime      \
    -opaque "rgb(219,168,146)"              \
    -opaque "rgb(219,168,146)"              \
    -opaque "rgb(255,198,172)"              \
    -fill black +opaque lime -resize 1x1! txt:

# ImageMagick pixel enumeration: 1,1,255,srgb
0,0: (0,92,0)  #005C00  srgb(0,92,0)

我们可以看到,毫无疑问,没有红色和没有蓝色,绿色像素的平均颜色是92/255,因此36%的像素符合我们对肤色的描述。

如果你想变得更复杂,你可能需要查看形状,纹理和上下文,或者训练一个皮肤分类器并在OpenCV中编写一大堆东西或者某些......