-
이미지 처리-4 얼굴 이미지 회전이미지 처리 2023. 6. 19. 18:00
1. 이미지 불러오기
import cv2 import numpy as np import matplotlib.pyplot as plt face_cascade = cv2.CascadeClassifier('../picture/haarcascade_frontalface_default.xml') eye_cascade = cv2.CascadeClassifier('../picture/haarcascade_eye.xml')
얼굴 이미지 처리를 위한 모듈을 불러온다. cv2에서는 cascade api를 사용하는데 얼굴 인식에 대해서 훈련된 데이터를 xml 파일로 삽입하여 여러 가지 작업을 할 수 있으며 frontalface와 eye를 인식할 수 있는 xml 파일을 아래 링크에서 다운할 수 있다. 얼굴 전면과
https://github.com/opencv/opencv/tree/master/data/haarcascades
face_img = cv2.imread('../picture/face01.jpg') face_image = cv2.cvtColor(face_img, cv2.COLOR_BGR2RGB) face_image_copy = face_image.copy() plt.imshow(face_image) plt.show()
얼굴 인식에 사용할 파일을 불러오고 잘 불러져 왔는지 확인한다.
2. 얼굴, 눈 인식
face_gray_image = cv2.cvtColor(face_image,cv2.COLOR_RGB2GRAY) face_box_info = face_cascade.detectMultiScale(face_gray_image,1.1) for(x,y,w,h) in face_box_info: print(x,y,w,h) cv2.rectangle(face_image, (x,y), (x+w,y+h),(0.255,0),2) plt.imshow(face_image) plt.show() 200 191 464 464
cascade는 그레이 스케일에서만 작동하기 때문에 이미지를 그레이스케일로 변환하고 위에서 저장한 CacadeClassifier 변수에 detectMultiScale 함수를 사용하여 얼굴 전면부를 인식한다. 영상 축소비율의 기본값은 1.1이다.
이제 face_box_info에는 검출된 사각형의 위치정보가 담겨 있고 이것을 for문으로 하나씩 꺼내서 cv2.rectangle 함수로 사각형을 그려준다.
roi_gray = face_gray_image[y:(y+h),x:(x+w)] roi_color = face_image_copy[y:(y+h),x:(x+w)] eyes_box_info = eye_cascade.detectMultiScale(roi_gray) print(eyes_box_info) for i, (ex, ey,ew,eh) in enumerate(eyes_box_info): print(i, ex,ew,eh) if i== 0: eye_1 = (ex ,ey,ew,eh) elif i ==3: eye_3 = (ex,ey,ew,eh) cv2.rectangle(roi_color, (ex,ey),(ex+ew, ey+eh), (0,0,255),2) plt.imshow(face_image_copy) plt.show() [[100 148 79 79] [268 139 67 67] [153 291 128 128]] 0 100 79 79 1 268 67 67 2 153 128 128
이제 눈을 인식하고 사각형을 그리기 위한 작업을 수행한다. cascade 함수를 실행하기 위해서는 그레이스케일로 변환해야 하기 때문에 그레이스케일로 변환한 이미지를 위에서 인식한 얼굴좌표로 잘라준다.
눈을 인식하고 나서 박스를 그리기 위해 위에서 복사한 rgb이미지를 얼굴좌표로 잘라서 gray스케일과 rgb스케일 두 개의 이미지를 준비한다.
이제 동일한 방식으로 이미지를 검출하여 eyes_box_info에 정보를 저장한다. 이때 좌표정보를 출력해 보면 눈의 정보는 얼굴처럼 하나이지 않고 3개의 배열을 담고 있다. 따라서 enumrate 함수로 각 배열에 번호를 매겨주며 박스를 그려서 출력한다.
출력한 그림을 확인해 보면 cascade 함수가 입까지 인식하였기 때문에 좌표에 따라 0번과 2번 배열이 눈 좌표인 것을 알 수 있고 이 좌표들을 각각 eye_1, eye_2 변수에 할당한다.
3. 각도를 구하기 위한 삼각형 그리기
print(eye_1[0], eye_2[0]) if eye_1[0] < eye_2[0] : left_eye = eye_1 right_eye = eye_2 else : left_eye = eye_2 right_eye = eye_1 print(left_eye, right_eye) 100 268 (100, 148, 79, 79) (268, 139, 67, 67)
eye_1 변수와 eye_2 변수의 첫 번째 값 즉 x좌표를 꺼내서 비교했을 때 더 큰 쪽이 right_eye 변수에 저장되고 작은 쪽이 lefr_eye 변수에 저장될 수 있도록 변수명을 바꾼다.
left_eye_center = (int(left_eye[0] + (left_eye[2] / 2)), int(left_eye[1] + (left_eye[3] / 2))) left_eye_center_x = left_eye_center[0] left_eye_center_y = left_eye_center[1] print("left eye center 좌표 : ", left_eye_center_x, left_eye_center_y) right_eye_center = (int(right_eye[0] + (right_eye[2] / 2)), int(right_eye[1] + (right_eye[3]/2))) right_eye_center_x = right_eye_center[0] right_eye_center_y = right_eye_center[1] print("right_eye center 좌표 : ", right_eye_center_x, right_eye_center_y) cv2.circle(roi_color,left_eye_center,7, (255,0,0),-1) cv2.circle(roi_color,right_eye_center,7, (255,0,0),-1) cv2.line(roi_color, left_eye_center,right_eye_center,(0,255,150,2)) plt.imshow(face_image_copy) plt.show() left eye center 좌표 : 139 187 right_eye center 좌표 : 301 172
오른쪽 눈과 왼쪽 눈의 좌표를 각각 너비, 높이에 x, y 좌표를 더한 후 나누기 2를 해서 중심점 좌표를 구하고 이것을 right, left_eye_center_x, y에 할당한다. cv2.circle 함수를 사용하여 눈의 중심점에 점을 그리고 cv2.line 함수로 점을 이어준다.
if left_eye_center_y > right_eye_center_y: A = (right_eye_center_x, left_eye_center_y) else : A = ( left_eye_center_x,right_eye_center_y) print(A) (301, 187) cv2.circle(roi_color,A,3, (255,0,150),2) cv2.line(roi_color,left_eye_center,A, (255,0,150),3) cv2.line(roi_color,right_eye_center ,A,(0,255,150,3)) plt.imshow(face_image_copy) plt.show()
수평인 삼각형을 만들기 위해서 만약 왼쪽 눈이 오른쪽 눈보다 낮은 곳에 위치한다면 왼쪽 눈의 y좌표를 기준으로 점을 찍고 높은 곳에 위치한다면 오른쪽 눈의 y좌표를 기준으로 점을 찍는다. 이 점을 왼쪽 눈과 오른쪽 눈의 좌표와 선으로 이어서 삼각형을 그린다.
4. 각도 구하고 이미지 회전
delta_x = right_eye_center_x - left_eye_center_x delta_y = right_eye_center_y - left_eye_center_y angle = np.arctan(delta_y/delta_x) angle = angle *180 / np.pi print(angle) -5.29008120537127
이제 이미지를 회전시키기 위한 각도를 찾는다. 밑변과 높이를 각각 구하고 np.artan 함수를 사용하여 각도를 구해주고 형식을 변환해 준다.
height, width , _ = face_image_copy.shape image_center = (width//2, height //2) M= cv2.getRotationMatrix2D(image_center, (angle),1.0) rotated = cv2.warpAffine(face_image_copy,M,(width,height)) plt.imshow(rotated) plt.show()
cv2.getRotationMatrix2D 함수를 사용하기 위해 이미지의 중심점을 구하고 각도를 넣어 회전 행렬을 구한다. 이미지의 전체 높이와 길이, 회전 행렬을 넣어 cv2.warpAffine 함수로 이미지를 눈 기준으로 회전시킬 수 있다.
'이미지 처리' 카테고리의 다른 글
이미지 처리-6 기본 동영상 처리 (0) 2023.06.19 이미지 처리-5 이미지 혼합 (0) 2023.06.19 이미지 처리-3 번호판 (2) 2023.06.18 이미지 처리-2 이미지 필터 처리 (0) 2023.06.17