【问题标题】:Computer Vision: Masking a human hand计算机视觉:掩盖人的手
【发布时间】:2013-01-23 00:07:18
【问题描述】:

我想从实时视频流中检测我的手并创建我手的蒙版。但是,正如您从图片中看到的那样,我的结果很差。

我的目标是跟踪手部运动,所以我所做的是将视频流从 BGR 转换为 HSV 颜色空间,然后我对图像进行阈值化以隔离我手的颜色,然后我试图找到轮廓我的手,虽然最终的结果并不是我想要达到的。

如何改进最终结果?

import cv2
import numpy as np

cam = cv2.VideoCapture(1)
cam.set(3,640)
cam.set(4,480)
ret, image = cam.read()

skin_min = np.array([0, 40, 150],np.uint8)
skin_max = np.array([20, 150, 255],np.uint8)    
while True:
    ret, image = cam.read()

    gaussian_blur = cv2.GaussianBlur(image,(5,5),0)
    blur_hsv = cv2.cvtColor(gaussian_blur, cv2.COLOR_BGR2HSV)

#threshould using min and max values
    tre_green = cv2.inRange(blur_hsv, skin_min, skin_max)
#getting object green contour
    contours, hierarchy = cv2.findContours(tre_green,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

#draw contours
    cv2.drawContours(image,contours,-1,(0,255,0),3)

    cv2.imshow('real', image)
    cv2.imshow('tre_green', tre_green)   

    key = cv2.waitKey(10)
    if key == 27:
        break

这里是图片链接:https://picasaweb.google.com/103610822612915300423/February7201303。 带有图像加轮廓、蒙版和原件的新链接。 https://picasaweb.google.com/103610822612915300423/February7201304

这是上面的示例图片:

【问题讨论】:

  • 包括您遇到问题的示例视频,否则尝试猜测您实际使用的是什么是毫无意义的。
  • 我无法上传图片,因为我没有足够的声望点:(
  • 只包含一个链接。并包含指向 /video/ 的链接,而不是单个帧。
  • 这是一个直播。你想要它的样本吗?
  • 我不知道那是什么,只是提供一个你正在使用的样本。

标签: python opencv computer-vision


【解决方案1】:

一个简单而强大的选项是直方图反投影。例如,使用来自您手的不同训练图像的像素,使用 H 和 S(来自 HSV 颜色空间)或 a* 和 b*(来自 La*b* 颜色空间)创建 2D 直方图。然后使用 [cv2.calcBackProject][1] 对流中的像素进行分类。它非常快,我猜你应该很容易达到 25 到 30 fps。请注意,这是一种了解您感兴趣的对象的颜色分布的方法。其他情况也可以使用同样的方法。

【讨论】:

    【解决方案2】:

    有许多方法可以执行逐像素阈值以将“皮肤像素”与“非皮肤像素”区分开来,并且几乎有基于任何色彩空间(即使是 RGB)的论文。所以,我的回答只是基于 Chai 和 Ngan 的论文 Face Segmentation Using Skin-Color Map in Videophone Applications。他们使用 YCbCr 颜色空间并获得了相当不错的结果,论文还提到了一个对他们来说效果很好的阈值:

    (Cb in [77, 127]) and (Cr in [133, 173])
    

    Y 通道的阈值没有指定,但是有论文提到了Y > 80。对于您的单个图像,整个范围内的Y 都可以,即实际上区分皮肤并不重要。

    这是输入,根据提到的阈值得到的二值图像,以及丢弃小分量后的结果图像。

    import sys
    import numpy
    import cv2
    
    im = cv2.imread(sys.argv[1])
    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.imwrite(sys.argv[2], 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.imwrite(sys.argv[3], im)         # Final image
    

    最后,有相当数量的论文不依赖于单个像素分类来完成这项任务。相反,它们从已知包含皮肤像素或非皮肤像素的标记图像的基础开始。例如,他们从中训练一个 SVM,然后根据该分类器区分其他输入。

    【讨论】:

    • @mmpg 哇,这真的非常好用!谢谢。我在使用cv2.inRange() 时遇到了一些麻烦,但使用min_YCrCb = numpy.array([0,133,77],numpy.uint8)max_YCrCb = numpy.array([255,173,127],numpy.uint8) 解决了这个问题
    • @samkhan13 :- 在 iOS 语言中实现此目的的任何参考
    猜你喜欢
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 2018-11-07
    • 2013-02-07
    • 2011-10-18
    • 2017-08-26
    • 1970-01-01
    相关资源
    最近更新 更多