Schoolwork/컴퓨터그래픽스 및 비젼

[Python] 04주차 과제 - 웹캠영상에서 얼굴 검출

FATKITTY 2020. 9. 5. 14:03
반응형

 목적:

- 이 과제에서는 웹캠의 live 입력 영상에 대하여 얼굴 검출을 실행하여 결과를 보여준다.

 

 과제의 내용:

A. 03주차의 얼굴 검출 프로그램을 활용하여 웹캠으로 live feed 받는 영상에서 사람의 얼굴 또는 피부만을 검출한 영상을 연속적으로 보여준다.

B. 카메라 입력 영상에 대하여 먼저 가우시안 필터(가우시안 스무싱)을 적용한 후 다음과정을 진행하기 바랍니다.

C. 출력은 다음과 같이 나타나도록 한다. 또는 두 영상을 별도의 윈도우에 각각 디스플레이해도 된다.

윈도우

웹캠으로 부터의 live feed 를 연속적으로 디스플레이 함

왼쪽 영상에 대한 얼굴 검출 결과 : 얼굴, 피부 영역만 원래 색으로 표시하고 나머지 영역은 검정색으로 처리

 

 기타:

- 주요한 과정에 대하여 opencv, numpy 등 package 함수를 사용해도 무방합니다.

- 영상을 멈추지 않고 계속 보여주면서 Track bar 를 사용하여 신뢰도 임계값을 조절할 수 있도록 하면 보너스 포인트를 부여합니다. (필수 사항은 아닙니다.)

- 필요한 경우 각 단계에서 *적절한* 최적화 가 필요합니다. 여러분의 최적화 노력을 PPT 에 간략하게 설명하기 바랍니다.

- 기타 세부적인 사항은 합리적으로 가정하시기 바랍니다.

- OpenCV 에서는 여러 대의 카메라를 동시에 사용할 수 있습니다, 0번 카메라로부터 영상을 live feed 받는 것을 원칙으로 합니다.  

- 영상에 대하여 적절한 해상도를 선택하세요. 고해상도일수록 처리 속도가 느려집니다.

- 이 프로그램은 여러분이 최적화한 파라미터값으로 진행되는 것을 원칙으로 합니다.

과제내용

Code

import cv2
import numpy as np

video = cv2.VideoCapture(0)  # 카메라 생성, 0번 카메라로 live feed 받기
# 비디오 캡쳐 객체가 정상적으로 Open되었는지 확인
if video.isOpened():
    print('width: {}, height : {}'.format(video.get(3), video.get(4)))

# 얼굴 모델 이미지
sample = cv2.imread('faces.jpg')

a = 0  # millisecond
user_th = 0  # 사용자 설정 신뢰도 임계값

# capt window에 0~255 신뢰도 임계값 조절 trackbar
cv2.namedWindow('capt', 0)
MaxValue = 0
def set_MaxValue(val):
    global MaxValue
    MaxValue = val
cv2.createTrackbar('MaxValue', 'capt', MaxValue, 255, set_MaxValue)

# 가로 세로 각 배수씩 더 크게 검정색 이미지를 생성
def create_image_multiple(h, w, d, hcout, wcount):
    image = np.zeros((h*hcout, w*wcount,  d), np.uint8)
    color = tuple(reversed((0, 0, 0)))
    image[:] = color
    return image

# 통이미지 하나에 원하는 위치로 복사(표시)
# dst는 create_image_multiple 함수에서 만든 통이미지, src는 복사할 이미지
def showMultiImage(dst, src, h, w, d, col, row):
    # 3 color
    if d == 3:
        dst[(col*h):(col*h)+h, (row*w):(row*w)+w] = src[0:h, 0:w]
    # 1 color
    elif d == 1:
        dst[(col*h):(col*h)+h, (row*w):(row*w)+w, 0] = src[0:h, 0:w]
        dst[(col*h):(col*h)+h, (row*w):(row*w)+w, 1] = src[0:h, 0:w]
        dst[(col*h):(col*h)+h, (row*w):(row*w)+w, 2] = src[0:h, 0:w]


while True:
    a = a + 1

    check, frame = video.read()  # 카메라에서 이미지 얻기. 비디오의 한 프레임씩 읽기, 제대로 프레임을 읽으면 ret값이 True 실패하면 False, frame에는 읽은 프레임이 나옴
    print(check)
    print(frame)

    hsv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    hsv_sample = cv2.cvtColor(sample, cv2.COLOR_BGR2HSV)

    user_th = cv2.getTrackbarPos('MaxValue', 'capt')  # 사용자 설정 신뢰도 임계값

    gau_frame = cv2.GaussianBlur(frame, (5, 5), 0)  # 얻어온 프레임에 대해 가우시안 필터 먼저 적용

    height = gau_frame.shape[0]  # 이미지 높이
    width = gau_frame.shape[1]  # 이미지 넓이
    depth = gau_frame.shape[2]  # 이미지 색상 크기

    cv2.threshold(gau_frame, user_th, 255, cv2.THRESH_BINARY)  # 가우시안 필터 적용된 프레임에 대한 임계처리, 임계값은 trackbar로 사용자가 설정
    S = cv2.calcHist([hsv_sample], [0, 1], None, [180, 256], [0, 180, 0, 256])  # 오브젝트 영역 이미지(S)
    F = cv2.calcHist([hsv_frame], [0, 1], None, [180, 256], [0, 180, 0, 256])  # 오브젝트 영역을 찾을 이미지(F)
    R = S / (F + 1)  # 히스토그램 S와 F의 비율을 계산. (분모에 1 안 더하면 0 때문에 nan 값 생김)

    h, s, v = cv2.split(hsv_frame)  # HSV 색공간의 타겟 이미지를 h,s,v 채널로 분리
    B = R[h.ravel(), s.ravel()]
    B = np.minimum(B, 1)  # 배열 B에서 1 이상 값을 1로.
    B = B.reshape(hsv_frame.shape[:2])  # B의 shape를 1차원에서 이미지 크기의 shape로 다시 변경

    # 역투영
    disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
    cv2.filter2D(B, -1, disc, B)
    B = np.uint8(B)
    cv2.normalize(B, B, 0, 255, cv2.NORM_MINMAX)  # 배열 B의 타입을 uint8로 변환하고 0 ~ 255 사이의 값으로 정규화

    ret, thresh = cv2.threshold(B, user_th, 255, cv2.THRESH_BINARY)  # 역투영 된 이미지에 대한 임계처리, 임계값은 trackbar로 사용자가 설정

    # 화면에 표시할 이미지 만들기 (1 x 2)
    result = create_image_multiple(height, width, depth, 1, 2)  # 화면 표시할 1x2 검정 이미지 생성
    showMultiImage(result, gau_frame, height, width, depth, 0, 0)  # 왼쪽 (0, 0)
    showMultiImage(result, thresh, height, width, 1, 0, 1)  # 오른쪽 (0, 1)

    cv2.imshow('capt', result)
    if cv2.waitKey(1) == 32:
        break

print(a)
video.release()

 

점수 8/10

반응형