Search code examples
pythonmediapipe

How to show the wrist of the left or right hand?


I would like to show the coordinates of the left hand wrist if I show my left hand or the coordinates of the right hand wrist if I show my right hand. Ive implemented it, but it will only show if my webcam can see both hands. What is wrong in my code? I'm using mediapipe and opencv as Framework.

with mp_holistic.Holistic(min_detection_confidence=0.5, min_tracking_confidence=0.5) as holistic:
    while cap.isOpened():
        ret, frame = cap.read()

        image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        image.flags.writeable = False
        results = holistic.process(image)
        image.flags.writeable = True
        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

        mp_drawing.draw_landmarks(image, results.right_hand_landmarks, mp_holistic.HAND_CONNECTIONS )
        mp_drawing.draw_landmarks(image, results.left_hand_landmarks, mp_holistic.HAND_CONNECTIONS)

        try:
            wrist_left_x = results.left_hand_landmarks.landmark[0].x
            wrist_left_y = results.left_hand_landmarks.landmark[0].y

            wrist_right_x = results.right_hand_landmarks.landmark[0].x
            wrist_right_y = results.right_hand_landmarks.landmark[0].y

            if results.left_hand_landmarks:
                text = wrist_left_x
                text2 = wrist_left_y

            if results.right_hand_landmarks:
                text = wrist_right_x
                text2 = wrist_right_y

            cv2.putText(image, str(text), (30, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1,
                        cv2.LINE_AA)
            cv2.putText(image, str(text2), (30, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1,
                        cv2.LINE_AA)
        except:
            pass

Solution

  • You should generally try to avoid using a bare except clause whenever possible, as you will invisibly catch any error that occurs in the try block. Instead, you should catch only the exceptions that you expect may arise in normal execution.

    I suspect, based on looking at the MediaPipe source, that what is happening here is that when there is only one hand detected, the value of results.{left|right}_hand_landmarks for the hand that is not detected is None. Since None is a falsey value, your if results.left_hand_landmarks: and if results.right_hand_landmarks: guards are good practice*, but the problem is that you are attempting to access attributes of those objects outside of the guards, namely here:

            try:
                wrist_left_x = results.left_hand_landmarks.landmark[0].x
                wrist_left_y = results.left_hand_landmarks.landmark[0].y
    
                wrist_right_x = results.right_hand_landmarks.landmark[0].x
                wrist_right_y = results.right_hand_landmarks.landmark[0].y
    

    In Python, if these objects are None, this will raise an error:

    AttributeError: 'NoneType' object has no attribute 'left_hand_landmarks'
    

    Try rewriting the code to this:

            try:
                if results.left_hand_landmarks:
                    text = results.left_hand_landmarks.landmark[0].x
                    text2 = results.left_hand_landmarks.landmark[0].y
    
                if results.right_hand_landmarks:
                    text = results.right_hand_landmarks.landmark[0].x
                    text2 = results.right_hand_landmarks.landmark[0].y
    

    *Best practice would be to explicitly use a None check: if x is not None:. Since each type in Python can have a different way of determining its truth value, relying on just if x: to ascertain the existence of an object can be a pitfall.