Python cv2中的皮肤检测和背景扣除

时间:2016-05-21 07:20:05

标签: python opencv gesture-recognition

在过去的几天里,我一直在使用OpenCV Python开展手势识别程序。理想情况下,我希望拥有一个像this video中所示的系统。我已经阅读了视频说明中描述的算法,我对它的全部了解。但是,我在复制背景减法和肤色检测方面的成功时遇到了麻烦。我的所有尝试都非常嘈杂和/或非常依赖于照明,这两种情况都使我的代码暂时无用。

我尝试了以下内容:

  • BackgroundSubtractorMOG和BackgroundSubtractorMOG2应用于彩色框架
  • 将图像分割为Y Cr Cb,在重新组合成单​​个图像之前将MOG或MOG2应用于每个图像
  • 过滤范围以删除不是肤色的颜色(应用于彩色图像)

到目前为止,我还没有成功。我已经能够挑选出一些轮廓,但这些都是嘈杂和不稳定的(根据框架来来去去)。他们是我应该使用的另一种方法吗?

2 个答案:

答案 0 :(得分:5)

我编写了一个fingerspelling解释器应用程序,因此我遇到了许多您遇到的健壮性问题。经过几周的实验,我找到了一个包含几种不同方法的解决方案,但最重要的方法是基于颜色的分割。

基于颜色(肤色)的分割可能非常强大,但简单的实现必然缺乏您正在寻找的稳健性。首先,每个人的肤色都不同。因此,通过其他机制识别基线肤色非常重要。一种方法是使用面部检测器(例如级联分类器)来找到主体的面部,然后相应地“调整”过滤器范围。

我个人使用级联分类器首先找到闭合的拳头形状,然后我对1)一个仅包括拳头的紧定边界框和2)整个图像之间的HSV直方图进行归一化和差异化。然后我设置了一个查找表(LUT),将每个通道的每个值映射到0到25​​5之间的值,表示像素代表皮肤的概率。

根据我的经验,改善我的手部跟踪逻辑性能的大多数重要因素是当我想到不丢弃信息时。为了生成二进制图像,您将很容易使用一些最佳范围进行阈值处理,但是知道一个像素有40%的可能性是皮肤而另一个像素有60%的几率是有价值的。一旦达到阈值,你只需要1和0。

当然,如果您打算使用基于轮廓的姿势分类,可能需要在某个时刻进行阈值处理。但是,如果您真的想要构建强大的手势识别软件,您可能需要使用Convolutional Neural Net (CNN)进行调查以执行分类。预测可以非常快速地进行,并且它对背景噪声,翻译等非常强大......希望这有帮助!

编辑:让我澄清一下我对“HSV直方图的归一化和差分”的评论。首先,这样做的理由是能够使用OpenCV的LUT (lookup table)而不是使用基于范围的阈值。 LUT非常有效,并且比基于范围的阈值处理更灵活。例如,假设您想要的色调包含两个不同范围内的值(例如:0-30和150-180)。基于LUT的方法很容易处理,因为每个单独的值都可以独立映射。

因此,一旦建立了LUT,您只需要在每个帧的HSV图像上运行LUT。这是一个非常有效的解决方案。

就我而言,为了构建LUT,我采取了以下步骤:

  • 转换为HSV色彩空间。
  • 获得拳头周围紧密边界框的投资回报率。
  • 为ROI和整个图像构建每个通道的直方图。
  • 缩小(标准化)完整图像通道直方图,使刻度与ROI直方图的刻度匹配(即:将每个完整图像直方图乘以ROI_area / full_image_area)。
  • 从ROI直方图中减去(差异)完整图像直方图。 (具有大正值的条目将对应于ROI中常见的通道值,但不是完整图像。)
  • 然后我平滑差异直方图以减少噪音和“过度拟合”。
  • 最后,我使用OpenCV的normalize函数和NORM_MINMAX将差异直方图规范化为0.0到1.0之间的值。
  • 然后可以将差异直方图合并在一起以产生3通道LUT。

我个人不会在使用LUT后对值进行阈值处理。相反,我只是使用结果数据计算各种类型的“颜色质量中心”,我用它来保持ROI以手为中心。然后,我可以将相同的基于LUT的值发送到CNN进行分类。

请注意,虽然这种方法适用于我的目的,但如果你执行阈值处理,它仍然不会是完美的;将检测到一些前景作为背景,反之亦然。我结合了一些基于边缘检测的逻辑来帮助减少由米色墙壁造成的误报(我家常见的故障模式),但实际情况是,如果有一种真正强大的方法可以将手从背景中干净地分割出来改变背景和照明条件,我还没有找到它。所以我的建议是从视觉皮层中获取提示,并允许来自更高抽象级别的信息来帮助滤除噪声。 (换句话说,调查有线电视新闻网 - 它们确实非常了不起。)

答案 1 :(得分:0)

背景减法往往会留下很多重影。你应该从基于HSV的皮肤检测开始,以排除非皮肤区域。这将消除背景扣除的需要。

然后,您可以应用面部检测来遮盖脸部,然后,当您只剩下手部轮廓时,可以使用approxPolyDP()来获得简化的多边形。计算此多边形的矩和凸性将为您提供手势识别的基础