Search code examples
pythonopencvcolorsopencv3.0hsv

How to get threshold to recognize skin-ish color?


I was altering an OpenCV 3.0 Python code in order to recognize hand gestures by drawing a contour around the fingers using convex-hull to recognize the points on fingertips.

Anyway, the code works but it just works with dark (blackish) backgrounds. The code uses threshold to binarize the image, so the brightest shape will be the hand (so the background is black and the hand shape white).

How can I alter threshold in order to binarize the image to just pick the skin color and not the brightest colors?

For example, when finished binarizing, the black part of the video stream image would be all of the colors that aren't skin-ish and the white part of the binarized image would be the skin-ish color.

Here's the code:

def readCamera(self):
    _, self.original = self.cap.read()
    self.original = cv2.flip(self.original, 1)

def threshold(self):

    hsv = cv2.cvtColor(self.original, cv2.COLOR_BGR2HSV)

    value = (31, 31)
    blurred = cv2.GaussianBlur(hsv, value, 0)
    _, self.thresholded = cv2.threshold(hsv[:,:,0], 0, 255,
                                        cv2.THRESH_BINARY+cv2.THRESH_OTSU)

def extractContours(self):
    _, self.contours, _ = cv2.findContours(self.thresholded.copy(),
                                        cv2.RETR_TREE,
                                        cv2.CHAIN_APPROX_SIMPLE)

Solution

  • Once you convert your frame to HSV, the skin colour gets a more greenish tinge. Apply an RGB filter on this image to filter out that skin portion. Use trackbars if necessary, as shown below:

    import cv2
    
    def nothing(x): #needed for createTrackbar to work in python.
        pass    
    
    cap = cv2.VideoCapture(0)
    cv2.namedWindow('temp')
    cv2.createTrackbar('bl', 'temp', 0, 255, nothing)
    cv2.createTrackbar('gl', 'temp', 0, 255, nothing)
    cv2.createTrackbar('rl', 'temp', 0, 255, nothing)
    cv2.createTrackbar('bh', 'temp', 255, 255, nothing)
    cv2.createTrackbar('gh', 'temp', 255, 255, nothing)
    cv2.createTrackbar('rh', 'temp', 255, 255, nothing)
    while true
            ret,img=cap.read()#Read from source
            hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
            bl_temp=cv2.getTrackbarPos('bl', 'temp')
            gl_temp=cv2.getTrackbarPos('gl', 'temp')
            rl_temp=cv2.getTrackbarPos('rl', 'temp')
            bh_temp=cv2.getTrackbarPos('bh', 'temp')
            gh_temp=cv2.getTrackbarPos('gh', 'temp')
            rh_temp=cv2.getTrackbarPos('rh', 'temp')
            thresh=cv2.inRange(hsv,(bl_temp,gl_temp,rl_temp),(bh_temp,gh_temp,rh_temp))
            if(cv2.waitKey(10) & 0xFF == ord('b')):
            break #break when b is pressed 
            cv2.imshow('Video', img)
            cv2.imshow('thresh', thresh)