Exemple #1
0
    fnames = [f for f in fnames if f.find('image_') >= 0]
    n = len(fnames)/2

    # Store some values in order to keep track of FPS
    if (showFPS):
        startTime = time()
        FPS = 0
        lastI = 0

    # Get our plot points ready
    timePoints = [[], []]
    plotPoints = [[[], [], []], [[], [], []]]

    # Create the mask and table model
    mask = ~np.bool8(cv2.imread(os.path.join(folder, 'mask.png'), -1))
    tablemodel = util.buildMinMap(os.path.join(folder, 'table'))

    i = 0
    waitAmount = 5
    
    handList = None
    camShifter = None
    colors = None

    # Loop until we are out of images
    while (i < n):
        
        print "Processing Frame ", i

        # Show the FPS if desired
        if (showFPS):
def getHands(image, depth, camShifter = None, colors = None, mask = None, tablemodel = None, showImages = False):

    # Make sure the mask and table model are available.  Otherwise, try to create them
    if (mask is None or tablemodel is None):
        mask = ~np.bool8(cv2.imread(os.path.join(folder, 'mask.png'), -1))
        tablemodel = util.buildMinMap(os.path.join(folder, 'table'))

    # If there is not camShifter currently running, we create a new one and start from scratch
    if (camShifter is None):
        camShifter = []
        colors = []
        for i in range(NUM_HANDS):
            camShifter.append(CamShiftTracker())
            colors.append((random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))

    # Same for colors... choose random colors if there are not passed in
    if (colors is None):
        colors = []
        for i in range(NUM_HANDS):
            colors.append((random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))

    # Make copies of the original image
    originalImage = image.copy()
    original = image.copy()
    shp = (image.shape[0], image.shape[1])

    # Split into HSV
    hue = np.zeros(shp, dtype='uint8')
    sat = np.zeros(shp, dtype='uint8')
    val = np.zeros(shp, dtype='uint8')
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    cv2.split(hsv, (hue, sat, val))

    hands = np.zeros(shp, dtype='uint8')

    # If we have debug enabled, show the images
    if DEBUG:
        cv2.imshow('Hue', hue)
        cv2.imshow('Saturation', sat)
        cv2.imshow('Value', val)

    # Find the contours of the depth segmentation that intersect the top of the screen
    # This is a bit of a slow process unfortunately
    newDep = cv2.convertScaleAbs(cv2.absdiff(depth, tablemodel))
    ret, depThresh = cv2.threshold(newDep, 12, 255, cv2.THRESH_BINARY)
    depConts, depHier = cv2.findContours(depThresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

    depRects = []
    for cont in depConts:
        rect = cv2.boundingRect(cont)
        newRect = (rect[1], rect[0], rect[0] + rect[2], rect[1] + rect[3])
        if (area((rect[0], rect[1], rect[0] + rect[2], rect[1] + rect[3])) > 2000):
            depRects.append(newRect)
    depRects.sort()

    im = np.zeros(shp + (3,), dtype = "uint8")
    for j in range(NUM_HANDS):
        if (len(depRects) > j and depRects[j][0] < 20):
            depHand = (depRects[j][1], 0, depRects[j][2], depRects[j][3])
            cv2.rectangle(image, (depHand[0], depHand[1]), (depHand[2], depHand[3]), (255, 0, 0))

            im[depHand[1] : depHand[3], depHand[0] : depHand[2], :] = 1

    # Multiply the image by the binary depth segment
    outputOld = cv2.multiply(image, im)
    ret, output = cv2.threshold(outputOld, 0, 255, cv2.THRESH_BINARY)
    output1 = np.zeros(shp, dtype='uint8')
    output2 = np.zeros(shp, dtype='uint8')
    output3 = np.zeros(shp, dtype='uint8')
    cv2.split(output, (output1, output2, output3))

    meanVal = int(round(cv2.mean(val)[0])) - 30

    # Segment by HSV within acceptable ranges of human skin color
    sat = cv2.inRange(sat, np.array((68)), np.array((200)))
    hue = cv2.inRange(hue, np.array((0)), np.array((22)))
    val = cv2.inRange(val, np.array((meanVal)), np.array((255)))

    # Multiply all the thresholds to obtain our final hand image
    one = cv2.multiply(hue, sat)
    two = cv2.multiply(one, val)
    hands = cv2.multiply(two, output1)

    # Smooth + threshold to filter noise
    hands = cv2.blur(hands, (13, 13))
    ret, hands = cv2.threshold(hands, 200, 255, cv2.THRESH_BINARY)

    original[hands == 0] = 0

    # Show the thresholds if debug is enabled
    if DEBUG:
        cv2.imshow('Saturation threshold', sat)
        cv2.imshow('Hue threshold', hue)
        cv2.imshow('Val threshold', val)
        cv2.imshow('Depth threshold', depThresh * 100)
        cv2.imshow('Hands', original)
    
    # Find the hands by selecting the two largest blobs
    handContours = findHands(hands)
    rects = []
    factor = 20

    # Loop over each of the two blobs
    for j in range(len(handContours)):
        handCnt = handContours[j]

        # Bound a rectangle to the blob
        # Note that we make the rectangle a bit larger to make camshift work a little better
        rect = cv2.boundingRect(handCnt)
        newRect = (max(rect[0] - factor, 0), max(rect[1] - factor, 0), min(rect[0] + rect[2] + factor, shp[1]), min(rect[1] + rect[3] + factor, shp[0]))

        # As long as the area of the rectangle meets a threshold, and it is not too similar to another, append it
        # if debug is enabled, we draw the rectangle
        if (area(newRect) > 2000 and (len(rects) == 0 or not sameRect(newRect, rects[0]))):
            rects.append(newRect)
            if DEBUG:
                cv2.rectangle(originalImage, (max(rect[0] - factor, 0), max(rect[1] - factor, 0)), (min(rect[0] + rect[2] + factor, shp[1]), min(rect[1] + rect[3] + factor, shp[0])), (255, 255, 0))

    # Initialize a camshift tracker for each hand.
    # Note that if one is already tracking, initialize does nothing useful
    rects.sort()
    for j in range(len(rects)):

        # Filter out all pixels outside the rectangle found above
        im = np.zeros(shp + (3,), dtype = "uint8")
        im[rects[j][1] : rects[j][3], rects[j][0] : rects[j][2], :] = 1
        out = cv2.multiply(image, im)
        val = j
        if (len(rects) == 1 and not camShifter[val].tracking):
            val = (0 if rects[0][0] < 270 else 1)
            
        camShifter[val].initialize(original, out, rects[j], colors[val], meanVal)

    if DEBUG:
        print "#### Rects ####"
        print rects
        print "#### ####"

    # For each of the camshift trackers, run the algorithm (does nothing if there is no selection)
    for j in range(len(camShifter)):
        camShift = camShifter[j]
        camShift.run()

        # If we retrieved something useful, draw the ellipse and print information
        if (len(rects) > 0 and (camShift.tracking or camShift.reDraw)):
            try: cv2.ellipse(originalImage, camShift.track_box, camShift.color, 2)
            except: 
                print ""
            if DEBUG:
                print "#### RotatedRect TrackBox 1 ####"
                try: print camShifter[j].track_box
                except: print "Could not print trackbox"
                print "#### ####"

            whichHand = "Left" if j == 1 else "Right"
            print "#### {hand} Hand ####".format(hand = whichHand)
            try: 
                point = worldPoint(camShift.track_box[0][0], camShift.track_box[0][1], depth[camShift.track_box[0][1], camShift.track_box[0][0]])
                print "Position: ", camShift.track_box[0]
                print "Size: ", camShift.track_box[1]
                print "Orientation: ", camShift.track_box[2]
                print "World Point: ", point

            except: print ""
            print "#### ####"

    # Store the points to return
    handList = [None, None]
    for j in range(NUM_HANDS):
        if (camShifter[j].track_box is not None):
            handList[(j + 1) % 2] = camShifter[j].track_box[0]

    return handList, camShifter, colors, originalImage