hyeongrokheo / mediapipe-public

mediapipe 강의 기본소스
0 stars 1 forks source link

김민석, 김호현 #4

Open Girey0211 opened 1 year ago

Girey0211 commented 1 year ago
import cv2
import mediapipe as mp
import math

FRAME_DELAY = 15

mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles

mp_hands = mp.solutions.hands

mp_fingers = mp_hands.HandLandmark

def run():
    cap = cv2.VideoCapture(0)
    save = []
    save2 = []
    init = 1
    n = 0
    j = 0
    state = 0
    with mp_hands.Hands(
        max_num_hands=1,
        model_complexity=0,
        min_detection_confidence=0.5,
        min_tracking_confidence=0.5
    ) as hands:

        while cap.isOpened():
            success, image = cap.read()
            if not success:
                print('Ignoring empty camera frame.')
                continue

            image = cv2.flip(image, 1)

            image.flags.writeable = False
            image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

            results = hands.process(image)

            image.flags.writeable = True
            image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
            width, height, _ = image.shape

            if results.multi_hand_landmarks:
                # print(len(results.multi_hand_landmarks))
                for hand_landmarks in results.multi_hand_landmarks:

                    index_finger_tip = hand_landmarks.landmark[
                        mp_fingers.INDEX_FINGER_TIP
                    ]

                    if init:
                        for i in range(21):
                            save.insert(i, hand_landmarks)
                        init = 0

                    angle1 = get_angle(
                            hand_landmarks.landmark[mp_fingers.THUMB_CMC],
                            hand_landmarks.landmark[mp_fingers.THUMB_TIP],
                            hand_landmarks.landmark[mp_fingers.INDEX_FINGER_TIP]
                            )
                    if angle1 > 25:
                        angle2 = get_angle(
                                hand_landmarks.landmark[mp_fingers.THUMB_TIP],
                                hand_landmarks.landmark[mp_fingers.MIDDLE_FINGER_TIP],
                                hand_landmarks.landmark[mp_fingers.RING_FINGER_TIP]
                                )
                        if angle2 < 10:
                            angle3 = get_angle(
                                    hand_landmarks.landmark[mp_fingers.THUMB_TIP],
                                    hand_landmarks.landmark[mp_fingers.RING_FINGER_TIP],
                                    hand_landmarks.landmark[mp_fingers.PINKY_TIP]
                                    )
                            if angle3 < 10:
                                side11 = get_side(
                                    hand_landmarks.landmark[0],
                                    hand_landmarks.landmark[mp_fingers.MIDDLE_FINGER_TIP]
                                )
                                side12 = get_side(
                                    hand_landmarks.landmark[0],
                                    hand_landmarks.landmark[mp_fingers.MIDDLE_FINGER_MCP]
                                )
                                if side11 < side12:
                                    side21 = get_side(
                                        hand_landmarks.landmark[0],
                                        hand_landmarks.landmark[mp_fingers.RING_FINGER_TIP]
                                    )
                                    side22 = get_side(
                                        hand_landmarks.landmark[0],
                                        hand_landmarks.landmark[mp_fingers.RING_FINGER_MCP]
                                    )
                                    if side21 < side22:
                                        side31 = get_side(
                                            hand_landmarks.landmark[0],
                                            hand_landmarks.landmark[mp_fingers.PINKY_TIP]
                                        )
                                        side32 = get_side(
                                            hand_landmarks.landmark[0],
                                            hand_landmarks.landmark[mp_fingers.PINKY_MCP]
                                        )
                                        if side31 < side32:
                                            side41 = get_side(
                                                hand_landmarks.landmark[0],
                                                hand_landmarks.landmark[mp_fingers.INDEX_FINGER_TIP]
                                            )
                                            side42 = get_side(
                                                hand_landmarks.landmark[0],
                                                hand_landmarks.landmark[mp_fingers.INDEX_FINGER_MCP]
                                            )
                                            if side41 > side42:
                                                cv2.putText(
                                                    image,
                                                    text=f'{int(index_finger_tip.x * width)} , {int(index_finger_tip.y * height)}',
                                                    org=(100, 100),
                                                    fontFace=cv2.FONT_HERSHEY_SIMPLEX,
                                                    fontScale=1,
                                                    color=(0, 0, 0),
                                                    thickness=2
                                                )
                                                state = 1
                                            else : state = 0
                                        else : state = 0
                                    else : state = 0
                                else : state = 0
                            else : state = 0
                        else : state = 0
                    else : state = 0
                    # print('---------')

                    # print(f'{index_finger_tip.x}, {index_finger_tip.y}')
                    # print(hand_landmarks.landmark[mp_fingers.INDEX_FINGER_TIP])
                    # print('---------')

                    mp_drawing.draw_landmarks(
                        image,
                        hand_landmarks,
                        mp_hands.HAND_CONNECTIONS,
                        mp_drawing_styles.get_default_hand_landmarks_style(),
                        mp_drawing_styles.get_default_hand_connections_style()
                    )

                    for i in range(1, 20):
                        save[i] = save[i-1]
                    save[0] = hand_landmarks

                    for i in range(1, 20):
                        angle = get_angle(
                            save[0].landmark[mp_fingers.INDEX_FINGER_MCP],
                            save[0].landmark[mp_fingers.INDEX_FINGER_TIP],
                            save[i].landmark[mp_fingers.INDEX_FINGER_TIP]
                        )

                        if angle > 70 and not n and state:
                            n = 100
                            j = i
                            #save2.insert(0, save[i].landmark[mp_fingers.INDEX_FINGER_TIP].x)
                            save2.insert(0, int(save[i].landmark[mp_fingers.INDEX_FINGER_TIP].x * width) + 50)
                            save2.insert(1, int(save[i].landmark[mp_fingers.INDEX_FINGER_TIP].y * height) - 130)
                            print(save2)
                            # print(save[0]*width)
                            break

                    if n:
                        n -= 1
                        cv2.putText(
                            image,
                            text='breathe',
                            org=(10, 30),
                            fontFace=cv2.FONT_HERSHEY_SIMPLEX,
                            fontScale=1,
                            color=(0, 0, 0),
                            thickness=2
                        )

                        x, y = get_last(save[j].landmark[mp_fingers.INDEX_FINGER_MCP], save[j].landmark[mp_fingers.INDEX_FINGER_TIP], width, height)

                        cv2.line(
                            image,
                            (save2[0], save2[1]),
                            (int(x), int(y)),
                            (0, 0, 255),
                            48
                        )

            cv2.imshow('MediaPipe Hands', image)
            cv2.waitKey(FRAME_DELAY)
        cap.release()

def get_angle(ps, p1, p2):
    angle1 = (math.atan((p1.y - ps.y) / (p1.x - ps.x)))
    angle2 = (math.atan((p2.y - ps.y) / (p2.x - ps.x)))

    angle = abs(angle1 - angle2) * 180 / math.pi
    return angle

def get_side(p1, p2):
    side = math.sqrt(((p1.x - p2.x) ** 2) + ((p1.y - p2.y) ** 2) + ((p1.z - p2.z) ** 2))
    side *= 1000
    return side

def get_last(p1, p2, width, height):
    ex = (p1.y - p2.y) / (p1.x - p2.x)
    a = (p1.y * height) - (ex * (p1.x * width))
    if p1.x > p2.x:
        if a > 480:
            temp = int((480 - a) / ex)
            return int(temp), 480
        if a < 0:
            temp = int((0 - a) / ex)
            return int(temp), 0
        return 0, a
    if p1.x < p2.x:
        result = ex * width + a
        if result > 480:
            temp = int((480 - a) / ex)
            return int(temp), 480
        if result < 0:
            temp = int((0 - a) / ex)
            return int(temp), 0
        return int(width), int(result)

run()