基本 hsb 皮肤检测,霓虹灯照明

信息处理 图像处理 计算机视觉
2021-12-30 05:30:12

我希望这是问的正确地方。否则对我的错误感到抱歉,请给我一个更好的网站建议。

我正在尝试使用某些范围的 hsb 图像来实现一个超级简单的皮肤检测器。我正在使用此处此处描述的方法。

我正在尝试使用来自我的网络摄像头的视频源。如果我使用太阳照明,它会很好地工作(不是很好,但很好),但是使用霓虹灯......它是一团糟。检测到很多白色区域,到处都有很多噪音。

为什么?

我正在使用第二个来源中描述的算法:

  1. 转换图像 ho HSV 颜色空间
  2. 将白色放在 0 < H < 38 的范围内
  3. 扩张过滤器
  4. 侵蚀过滤器
  5. 模糊滤镜

在此处输入图像描述

4个回答

使用 RGB 而不是 HSV 中的简单生成模型,这实际上可能会更好。

  1. 获取一张或几张带有一些皮肤的训练图像。
  2. 手动选择皮肤像素(例如通过创建二进制蒙版)
  3. 计算 RGB 中肤色的均值和协方差(每个都应该是 3 元素向量)
  4. 对于未知像素,使用协方差计算其与平均值的马氏距离。
  5. 如果距离小于阈值,则将其分类为皮肤。
  6. 调整阈值以获得最佳性能。

编辑: 我不知道 OpenCV 是否有计算协方差的功能,但我可以告诉你如何自己做。假设您有RGB 像素。您将它们放入一个 x 3 矩阵中,我们称之为然后通过计算列的平均值计算,这是平均 RGB 向量。 将是一个 1 x 3 向量。的每一行中减去并调用生成的矩阵现在要计算协方差,您所要做的就是将乘以自身的转置:确保为 3 x 3。nnPmmmPQQC=QQC

Edit2: 你得到的值似乎太大了。要获得最大协方差,请创建以下矩阵:

255 255 255
 0   0   0

并计算它的协方差。您应该得到一个矩阵,其中每个值都大约为 32513。因此,请确保您的像素值范围从 0 到 255,并确保将它们正确复制到浮点数或双精度数中。Mahalanobis 距离以方差为单位,因此数字应该很小。您的皮肤分类阈值可能应该小于 4。

考虑使用霓虹灯时在 HSV 颜色中获得的不同值:此处是其偏差的示例。尝试调整您的算法,使其适应这些值。

这里还有另一种检测皮肤的算法,对于检测光照条件,您可以使用这个算法。

另一种算法,与皮肤检测有关,但与霓虹灯效果关系不大,就是这个

到目前为止,您得到的答案都指向了很好的替代方法,但是如果您对使用初始算法之类的东西感兴趣,那么修复它可能并不难。您只需要针对 OpenCV 的 HSV 特性进行调整。鉴于古怪的结果,我假设您在选择阈值和/或转换像素时可能使用了 HSV 更常见的数字表示之一?

OpenCV 表示 HSV 的方式与您可能发现的大多数其他来源不同:

  • 对您来说最大的区别是 w/r/t 色调:OpenCV 将色调表示为从 0 到 179,而几乎所有其他东西都利用悬挂位来保存更多信息,w/0-255。
  • 另一个区别:与标准相比,饱和度的测量是倒置的。所以 255 饱和度在 opencv 中意味着明亮,而不是白色(注意,我们回到 255 - 只有色调是 0-180,可能是因为“轮”表示?)

可能为时已晚,但这是一个有趣的问题,其他人可能会遇到同样的问题。

import sys
import numpy
import cv2

cap = cv2.VideoCapture(0)
while(1):
    _, im = cap.read()

    im_ycrcb = cv2.cvtColor(im, cv2.COLOR_BGR2YCR_CB)

    skin_ycrcb_mint = numpy.array((0, 133, 77))
    skin_ycrcb_maxt = numpy.array((255, 173, 127))
    skin_ycrcb = cv2.inRange(im_ycrcb, skin_ycrcb_mint, skin_ycrcb_maxt)

    cv2.imshow("Second Image", skin_ycrcb) # Second image
    contours, _ = cv2.findContours(skin_ycrcb, cv2.RETR_EXTERNAL, 
        cv2.CHAIN_APPROX_SIMPLE)
    for i, c in enumerate(contours):
        area = cv2.contourArea(c)
            if area > 1000:
                cv2.drawContours(im, contours, i, (255, 0, 0), 3)
    cv2.imshow("Final Image", im)         # Final image
    cv2.waitKey(1)