본문 바로가기
Projects/Face Toy Project

GUI 기반 Face Toy Project -2

by apsdfjoi 2023. 4. 5.
728x90
반응형

지난 시간에 PyQt5를 이용해서 간단한 baseline을 만들고 스마트폰 카메라를 웹캠처럼 사용해보았다.

 

GUI 기반 Face Toy Project - 1

더보기 PyQt5와 다양한 라이브러리 경험을 위한 Toy 프로젝트이다. Baseline PyQt5를 처음 사용하므로 ChatGPT의 도움을 받자. 이 코드를 복사하기 이전에 아나콘다를 통해 가상 환경을 만든다. python==3.9.

yeeca.tistory.com

버튼 1과 2가 클릭 됐을 때, 이벤트 실행을 체크하기 위해 아무 기능을 추가해보았다.

def button1_clicked(self):

    print('btn1 clk')
    self.frame_handler = 0

def button2_clicked(self):
    print('btn2')
    self.frame_handler = 1

MainWindow class의 frame_handler 변수는 실시간으로 화면을 출력하는 update_frame 함수에서 image(frame) processing 기능의 종류를 바꾸기 위해 존재한다.

update_frame 함수는 다음과 같다.

def update_frame(self):
        pTime = 0
        # Read a frame from the video capture
        while True:
            ret, frame = self.video.read()

            # Read a frame and apply method
            if ret:
                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                
                # Image Processing
                frame = self.processing(self.frame_handler,frame)

                # FPS
                cTime = time.time()
                fps = 1/(cTime-pTime)
                pTime = cTime
                cv2.putText(frame,f'FPS: {int(fps)}',(40,80),cv2.FONT_HERSHEY_PLAIN,1,(255,0,0),1)

                image = QImage(frame, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
                pixmap = QPixmap.fromImage(image)
                self.label.setPixmap(pixmap)

            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        self.video.release()
        cv2.destroyAllWindows()

카메라로부터 읽어드린 frame은 self.processing를 통해 frame에 대한 어떤 작업이 수행된다. self.frame_handler는 그 작업의 종류를 의미한다.

# bounding box test
def test_m1(self,frame):
    height, width = 100,20

    thickness = 5  # 바운딩 박스 두께
    color = (0, 255, 0)  # 바운딩 박스 색상
   
    cv2.rectangle(frame, (100, 180+height - thickness), (width, height), color, thickness)  # 아래쪽 모서리

    return frame

# lib test
def test_m2(self,frame):
    faces, confidences = cvlib.detect_face(frame)
    for face in faces:
        # 바운딩 박스 좌표
        (startX, startY) = face[0], face[1]
        (endX, endY) = face[2], face[3]
        
        # 바운딩 박스 그리기
        cv2.rectangle(frame, (startX,startY), (endX,endY), (0,255,0), 2)
    return frame

def processing(self,frame_handler,frame):
		methods = [self.test_m1,self.test_m2]
		return methods[frame_handler](frame)

test_m1 함수는 임의로 지정한 좌표의 bounding box를 그린 것 이며, test_m2 함수는 cvlib 패키지를 사용하여 얼굴들을 detection하고 그 좌표들을 이용하여 bounding box를 그린다.

faces 변수의 shape는 (n, 4)이다.

실행 결과는 다음과 같다.

face detection

얼굴 detection, alignment 등을 수행하는 모델을 제안한 논문의 구현 코드가 있는 github 레포지토리를 복사하여 사용 하려다 더 편리하게 작업하기 위해 mediapipe 패키지를 사용하여 기능들을 추가할 것이다.

mediapipe는 구글이 배포한 비디오 및 오디오 처리, 컴퓨터 비전 및 머신 러닝 모델 추론 및 통합, 모델 및 데이터 프로덕션화, 웹 기술 등을 포함한 종합적인 머신 러닝 프레임워크 이다.

라이선스는 Apache 라이선스 2.0이다.

test_m3 함수를 만들어 추가했다.

mpFaceMesh = mp.solutions.face_mesh
faceMesh = mpFaceMesh.FaceMesh(max_num_faces=10,min_detection_confidence=0.7)
mpDraw = mp.solutions.drawing_utils
drawSpec = mpDraw.DrawingSpec(thickness=1,circle_radius=2)
def test_m3(self,frame):
    re = faceMesh.process(frame)
    if re.multi_face_landmarks:
        for faceLms in re.multi_face_landmarks:
            mpDraw.draw_landmarks(frame, faceLms, mpFaceMesh.FACEMESH_TESSELATION,
                                  drawSpec,drawSpec)

    return frame

실행 결과는 다음과 같다.

face mesh

INFO: Created TensorFlow Lite XNNPACK delegate for CPU.

CPU기반으로 Tensorflow Lite 모델이 실행된다.

reference : https://www.youtube.com/watch?v=01sAkU_NvOY

 

728x90
반응형

댓글