4

I am using following code to detect hand landmarks using mediapipe

import cv2
import mediapipe as mp

mphands = mp.solutions.hands
hands = mphands.Hands()
mp_drawing = mp.solutions.drawing_utils
cap = cv2.VideoCapture(0)

while True:
    _, frame = cap.read()
    framergb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    result = hands.process(framergb)
    hand_landmarks = result.multi_hand_landmarks
    if hand_landmarks:
        for handLMs in hand_landmarks:
            mp_drawing.draw_landmarks(frame, handLMs, mphands.HAND_CONNECTIONS)
            print("\n\n\n")
    cv2.imshow("Frame", frame)

    cv2.waitKey(1)

I just want a rectangle around all the points returned by the detector Please tell if there is any way to do so built in mediapipe or using opencv

Parv Jain
  • 85
  • 2
  • 6

1 Answers1

4
  1. Before the while loop, determine the width and height each frame will be:
_, frame = cap.read()

h, w, c = frame.shape
  1. For each landLM detected, define the initial variables for smallest x and y coordinates, and the largest x and y coordinates. The first two variables will later act as the starting point of the rectangle, and the last two variables will later act as the last point of the rectangle:
            x_max = 0
            y_max = 0
            x_min = w
            y_min = h
  1. Loop through the handLM variable, and finding the x and y coordinates of each point of the hand:
            for lm in handLMs.landmark:
                x, y = int(lm.x * w), int(lm.y * h)
  1. Update the minimum and maximum x and y variables as new coordinates are being detected:
                if x > x_max:
                    x_max = x
                if x < x_min:
                    x_min = x
                if y > y_max:
                    y_max = y
                if y < y_min:
                    y_min = y
  1. Finally, draw the rectangle with the points:
            cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2)

Altogether:

import cv2
import mediapipe as mp

mphands = mp.solutions.hands
hands = mphands.Hands()
mp_drawing = mp.solutions.drawing_utils
cap = cv2.VideoCapture(0)

_, frame = cap.read()

h, w, c = frame.shape

while True:
    _, frame = cap.read()
    framergb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    result = hands.process(framergb)
    hand_landmarks = result.multi_hand_landmarks
    if hand_landmarks:
        for handLMs in hand_landmarks:
            x_max = 0
            y_max = 0
            x_min = w
            y_min = h
            for lm in handLMs.landmark:
                x, y = int(lm.x * w), int(lm.y * h)
                if x > x_max:
                    x_max = x
                if x < x_min:
                    x_min = x
                if y > y_max:
                    y_max = y
                if y < y_min:
                    y_min = y
            cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2)
            mp_drawing.draw_landmarks(frame, handLMs, mphands.HAND_CONNECTIONS)
    cv2.imshow("Frame", frame)

    cv2.waitKey(1)
Red
  • 26,798
  • 7
  • 36
  • 58
  • Curiously, this method doesn't quite work for multi_face_landmarks - the rectangle is centered around the chin. Any idea why? (Also adding (x_max-x_min)/2 and the same for y doesn't quite line up the box – user48956 Apr 28 '21 at 21:22
  • 2
    @user48956 Hmm... have you tried drawing the facial landmarks onto the face to make sure that they are detecting properly? If so, then I'm not rightly sure. If you still have the problem, you can post it and I'll find an answer. – Red Apr 29 '21 at 00:26
  • Actually, it looks like I just mixed up: `h, w, c = frame.shape` with `w, h, c = frame.shape`. Thanks! – user48956 Apr 29 '21 at 00:27
  • Legendary stuff – Gautam Chettiar Nov 18 '22 at 18:33