비전

[MediaPipe] 얼굴 인식

왕초보코딩러 2024. 8. 23. 15:10
728x90

미디어파이프란 구글에서 제공하는 AI 오픈소스이다

 

미디어파이프 설치

pip install mediapipe

 

필요 라이브러리 임포트

import mediapipe as mp
import cv2

 

 

mp.solutions: 미디어파이프 솔루션들이 포함되어 쉽게 사용할 수 있다

 

 

- 얼굴 인식

mp.solutions.face_detection

- 얼굴 메시

mp.solutions.face_mesh

- 손 추적

mp.solutions.hands

- 포즈 추정

mp.solutions.pose

- 신체 전체 추적

mp.solutions.holistic

- 랜드마크 시각화 툴

mp.solutions.drawing_utils

- 미리 정의된 스타일 툴

mp.solutions.drawing_styles

- 인물과 배경 분리

mp.solutions.selfie_segmentation

 

 

https://github.com/google-ai-edge/mediapipe/blob/master/docs/solutions/face_detection.md

 

mediapipe/docs/solutions/face_detection.md at master · google-ai-edge/mediapipe

Cross-platform, customizable ML solutions for live and streaming media. - google-ai-edge/mediapipe

github.com

 


얼굴 인식

face_detection을 사용합니다

mp_facedetection = mp.solutions.face_detection
mp_drawing = mp.solutions.drawing_utils

face_detection = mp_facedetection.FaceDetection()

 

 

미디어파이프에 적용하기 위해 이미지를 rgb로 변환해줍니다

그 후 face_detection.process(이미지) 를 하여 결과를 반환합니다.

img = cv2.imread('data/karina.jpg')
    
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    
# 결과
result = face_detection.process(img_rgb) # rgb로 넣어줘야 한다

 

 

print(result.detections)

출력 결과

 

6개의 좌표를 인식합니다.

['LEFT_EAR_TRAGION', 'LEFT_EYE', 'MOUTH_CENTER', 'NOSE_TIP', 'RIGHT_EAR_TRAGION', 'RIGHT_EYE']

[label_id: 0
score: 0.943828046
location_data {
  format: RELATIVE_BOUNDING_BOX
  relative_bounding_box {
    xmin: 0.362439603
    ymin: 0.277495772
    width: 0.291663319
    height: 0.233330518
  }
  relative_keypoints {
    x: 0.437948346
    y: 0.357101202
  }
  relative_keypoints {
    x: 0.558209419
    y: 0.346372902
  }
  relative_keypoints {
    x: 0.500902534
    y: 0.416154385
  }
  relative_keypoints {
    x: 0.512111783
    y: 0.45437628
  }
  relative_keypoints {
    x: 0.38407588
    y: 0.36842072
  }
  relative_keypoints {
    x: 0.638756156
    y: 0.34334442
  }
}
]

 

 

drawing_utils를 사용해서 시각화를 해보겠습니다

# 얼굴 인식이 됐다면
if result.detections:
    for detection in result.detections:
        # 그려라
        mp_drawing.draw_detection(img, detection)

 

 

 

이제 이미지 출력을 해보겠습니다.

cv2.imshow('face_detection', img)
    
cv2.waitKey() 
cv2.destroyAllWindows()

 

 

 


저는 drawing_utils를 사용해서 시각화의 바운딩 박스를 이용해서 새롭게 표시를 해보고 싶은데요

그럴 때

detection.location_data.relative_bounding_box

를 사용하면 됩니다.

 

 

출력해보니

xmin: 0.362439603
ymin: 0.277495772
width: 0.291663319
height: 0.233330518

이렇게 나오는데요.

width와 height를 1로 봤을 때 얼만큼 위치했는지, 얼만큼 차지하는지 비율로 나오는 것이기 때문에

*width, *height하면 실제 좌표가 나옵니다.

 

# 얼굴 인식이 됐다면
if result.detections:
    for detection in result.detections:
        # bbox 알려줌: 좌표가 width와 height를 1로 봤을 때 얼만큼 위치했는지, 얼만큼 차지하는지(*width, *height하면 실제 좌표 나온다)        
        # print(detection.location_data.relative_bounding_box) 

        img_height, img_width, _ = img.shape
        bbox = detection.location_data.relative_bounding_box # xmin: 0.362439603 ymin: 0.277495772 width: 0.291663319 height: 0.233330518
        xmin = int(bbox.xmin * img_width)
        ymin = int(bbox.ymin * img_height)
        width = int(bbox.width * img_width)
        height = int(bbox.height * img_height)
        cv2.rectangle(img, (xmin,ymin,width,height), (0,0,255), 3)

 

이미지 출력을 하면

cv2.imshow('face_detection', img)
    
cv2.waitKey() 
cv2.destroyAllWindows()

 

 

이쁘게 됐습니다~

 

 

 

이제 좌표를 받아보겠습니다.

# 얼굴 인식이 됐다면
if result.detections:
    for detection in result.detections:
        # 두 방식이 같다
        print(detection.location_data.relative_keypoints[mp_facedetection.FaceKeyPoint.NOSE_TIP])
        
        print(mp_facedetection.get_key_point(
          detection, mp_facedetection.FaceKeyPoint.NOSE_TIP))

 

이 좌표는 좌표가 width와 height를 1로 봤을 때 얼만큼 위치했는지 보여주기 때문에 width와 height를 곱하면 실제 좌표 나옵니다.

코의 좌표를 받아볼게요

nose = detection.location_data.relative_keypoints[mp_facedetection.FaceKeyPoint.NOSE_TIP]

# 실제 좌표
nose_x = int(nose.x * img_width)
nose_y = int(nose.y * img_height)

 

그리고 이미지에 nose라고 텍스트를 넣어주겠습니다

cv2.putText(img, 'nose', (nose_x, nose_y), cv2.FONT_HERSHEY_COMPLEX, 2, (0,0,0), 2)
cv2.imshow('face_detection', img)
    
cv2.waitKey() 
cv2.destroyAllWindows()

 


웹캠에서도 해볼까요??

 

# 웹캠
cap = cv2.VideoCapture(0)
   
while cap.isOpened():
    ret, frame = cap.read()
   
    if not ret:
        break    
   
    frame.flags.writeable = False
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    # 얼굴 인식 결과
    result = face_detection.process(frame_rgb) # rgb로 넣어줘야 한다
    # print(result.detections)
    frame.flags.writeable = True
   
    # 얼굴 인식이 됐다면
    if result.detections:
        for detection in result.detections:
            # 그려라
            mp_drawing.draw_detection(frame, detection)
           
       
    cv2.imshow('face_detection', frame)
   
    if cv2.waitKey(1) == 27:
        break

이미지 처리와 똑같지만

상태가 바뀌지 않도록

frame.flags.writeable = False

체크를 해줘야 합니다.

 


https://github.com/stonegyoung/OpenCV/blob/main/mp_face_detection_video.py

 

OpenCV/mp_face_detection_video.py at main · stonegyoung/OpenCV

컴퓨터 비전 공부. Contribute to stonegyoung/OpenCV development by creating an account on GitHub.

github.com

 

'비전' 카테고리의 다른 글

[MediaPipe] 얼굴 매쉬1  (1) 2024.09.02
[MediaPipe] 포즈 인식  (0) 2024.08.25
[OpenCV] 특정 색 검출  (0) 2024.08.20
[OpenCV] 그리기 함수  (0) 2024.08.19
[OpenCV] 마스킹  (0) 2024.08.18