【问题标题】:Skin detection from hue-saturation histogram - OpenCV Python从色相饱和度直方图检测皮肤 - OpenCV Python
【发布时间】:2013-05-15 09:35:30
【问题描述】:

我正在用 python 编写一个小程序,用来自单目相机的 2D 图片估计指向手势的方向,我正在使用 OpenCV 2.3。 我知道这有点棘手,但我有动力! :) 我的方法是首先使用面部检测来检测我确定有很多皮肤的区域:

img = cv2.imread("/home/max/recordings/cameras/imageTEST.jpg",1)
img_hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hc1 = cv2.CascadeClassifier("/home/max/haarcascade_frontalface_alt.xml")
faces1 = hc1.detectMultiScale(img)
for (x,y,w,h) in faces1:
  cv2.rectangle(img, (x,y), (x+w,y+h), 255)
crop_img = img[y+2:y+w, x+2:x+h]

我真的很想使用这种方法,因为我希望我的检测对光线变化具有鲁棒性。然后我计算检测到的人脸图片的色相饱和度直方图做一个反投影:

roihist = cv2.calcHist([crop_img],[0,1], None, [180, 256], [0, 180, 0, 256] )
dst = cv2.calcBackProject([img],[0,1],roihist,[0,180,0,256],1)

最后,我将能够使用阈值对图片进行二值化,并跟踪头部和手部的斑点以估计指向的方向。 我的代码没有问题,但未检测到皮肤... 我究竟做错了什么? 感谢您的帮助!

最大

【问题讨论】:

  • 这可能对你有帮助.. shervinemami.info/blobs.html
  • 感谢链接!不幸的是,即使我在 S 和 V 上应用了一些阈值,我的检测仍然很差。看起来 ROI(即人脸)的直方图没有正确用于反投影......

标签: python opencv computer-vision histogram


【解决方案1】:

您是否尝试过使用 YCbCr 格式的 Cr 频道?当我以前使用肤色进行手部检测时,我对 Cr 有一些运气。此外,还有this paper,它使用了一种很好的方法来检测手部。但请记住,只要您使用肤色,检测将不适用于所有手,但可以针对给定用户或一群用户进行调整。

【讨论】:

    【解决方案2】:

    我最近一直在研究网络上可用的 opencv 示例(只是为了好玩的基本内容)。我已经从人脸识别(有趣,但我不喜欢黑框)转移到手动选择 HSV 空间中的 roi,然后使用“camshift”进行跟踪。我仍然得到我不理解的可变结果,所以我还绘制了所有中间处理窗口,例如 hsv 图像和 backproject 图像,还绘制了跨窗口的直方图。突然间一切都清楚了 - 您可以准确地看到计算机正在尝试使用什么。

    这是我的 python3.4,opencv3 的工作代码。您可以手动选择皮肤。主要归功于我在网上找到的其他示例。

    “cv2.calcBAckProject”函数很好地阈值了皮肤特征。

    import numpy as np
    import cv2
    
    roiPts = []
    track_mode = False
    termination = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)
    roiBox = None
    kernel = np.ones((5, 5), np.uint8)
    frame_width_in_px = 640
    number_of_histogram_elements=16
    
    def selectROI(event, x,y,flags,param):
        global track_mode, roiPts
    
        if (event == cv2.EVENT_LBUTTONDOWN) and (len(roiPts)==4): #reselecting ROI points so take out of tracking mode and empty current roipoints
            roiPts=[]
            track_mode = False
        if (event==cv2.EVENT_LBUTTONDOWN) and (len(roiPts) < 4): #ROI point selection
            roiPts.append([x, y])
    
    cap = cv2.VideoCapture(0)
    cv2.namedWindow("frame")
    cv2.setMouseCallback("frame", selectROI)
    
    while True:
        ret, frame = cap.read()
    
        if len(roiPts)<=4 and len(roiPts)>0:
            for x,y in roiPts:
                cv2.circle(frame, (x,y), 4, (0, 255, 0), 1)  # draw small circle for each roi click
    
        if len(roiPts)==4 and track_mode==False: #initialize the camshift
            # convert the selected points to a box shape
            roiBox = np.array(roiPts, dtype=np.int32)
            s = roiBox.sum(axis=1)
            tl = roiBox[np.argmin(s)]
            br = roiBox[np.argmax(s)]
    
            #extract the roi from the image and calculate the histograme
            roi = frame[tl[1]:br[1], tl[0]:br[0]]
            roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) #
            roiHist = cv2.calcHist([roi], [0], None, [number_of_histogram_elements], [0, 180])
            roiHist = cv2.normalize(roiHist, roiHist, 0, 255, cv2.NORM_MINMAX)
            roiBox = (tl[0], tl[1], br[0], br[1])
            track_mode = True #ready for camshift
    
        if track_mode == True: #tracking mode
            hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
            backProj = cv2.calcBackProject([hsv], [0], roiHist, [0, 180], 1)
            #perfrom some noise reduction and smoothing
            erosion = cv2.erode(backProj, kernel, iterations=2)
            dilate = cv2.dilate(erosion, kernel, iterations=2)
            (r, roiBox) = cv2.CamShift(dilate, roiBox, termination) #this takes prev roiBox and calculates the new roiBox
            pts = np.int0(cv2.boxPoints(r))
            cv2.polylines(frame, [pts], True, (0, 255, 0), 2) #tracking box
            cv2.polylines(backProj, [pts], True, (0, 255, 0), 2) #tracking box
            cv2.polylines(dilate, [pts], True, (0, 255, 0), 2) #tracking box
            cv2.polylines(hsv, [pts], True, (0, 255, 0), 2) #tracking box
    
            # plot histogram polyline across the windows
            x = np.linspace(0,640,number_of_histogram_elements,dtype=np.int32)
            y = roiHist.flatten().astype(np.int32, copy=False)-255 #note frame height needs to be greater than 255 which is the max histo value
            y=np.absolute(y)
            pts2 = np.stack((x, y), axis=1)
            cv2.polylines(frame, [pts2], False, (0, 255, 0), 2)
            cv2.polylines(hsv, [pts2], False, (0, 255, 0), 2)
    
            cv2.imshow("backproject", backProj)
            cv2.imshow("dilate", dilate)
            cv2.imshow("hsv", hsv)
    
        cv2.imshow("frame", frame)
    
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    
    # When everything done, release the capture
    cap.release()
    cv2.destroyAllWindows()

    【讨论】:

    • 天哪。我迟到了 3 年。
    猜你喜欢
    • 2012-10-09
    • 2011-12-19
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    • 2015-12-03
    相关资源
    最近更新 更多