给定图像所有像素的RGB值,我们如何找到给定像素的肤色概率以及图像的肤色百分比。
答案 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
得到了这个:
好的,那些看起来很合理,现在我尝试使用它们来检测肤色,再次使用ImageMagick。就目前而言,只有这样你才能看到它,我将把我发现的石灰绿色变为肤色,使用它正好在上面确定的色调范围的中间:
convert -fuzz 5% face1.jpg -fill lime -opaque "rgb(240,184,160)" out.jpg
嗯,不是很好。可能会增加模糊性?
嗯,还是很垃圾 - 只捡起部分皮肤和一些白衬衫领。不同的面孔可能?
好吧,在检测到他时并不坏,虽然注意到它完全无法检测到他的右侧,但是我们可以从粉红色的凯迪拉克身上看到一些问题:
和Piggy小姐下面......
也许我们可以在搜索中更有针对性,虽然我无法在3-D中绘制它,但我可以在2-D中解释。我们不是在我们的范围中间瞄准单个大圆(实际上是三维空间中的球体),也许我们可以定位沿着我们的范围扩展的一些较小的圆,从而包含更少的外来颜色......洋红色代表模糊的程度。所以不是这样:
我们可以这样做:
使用此命令:
convert -fuzz 13% face1.jpg -fill lime \
-opaque "rgb(219,168,146)" \
-opaque "rgb(219,168,146)" \
-opaque "rgb(255,198,172)" out.jpg
所以,你可以看到仅使用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
):
接下来的饱和度(s.png
):
现在是合并的输出文件。
一旦你的算法被整理出来以决定哪些像素是肤色的,你需要计算它们以计算你寻找的百分比。这很简单......我们所做的就是将所有非石灰绿色变为黑色(因此在平均值中计为零),然后将图像调整为单个像素,并将其颜色设置为文本:
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中编写一大堆东西或者某些......