[캐글스터디] 해리포터 투명망토 만들기

뚜비·2022년 1월 25일
0

캐글스터디

목록 보기
5/5

유튜브 "빵형의 개발도상국"을 보면서 공부 및 프로젝트를 진행하였습니다. https://youtu.be/suytB_6aS6M - 해리포터 투명망토 만들기
참고한 깃허브 자료
https://github.com/kairess/invisibility_cloak



✨해리포터 투명망토 만들기


출처 : 빵형의 개발도상국 유튜브 [해리포터 투명망토 만들기]


✅ 우리가 사용할 라이브러리

  • openCV : 이미지 처리 라이브러리, 웹캠 사용을 위해 가져옴!
  • numpy : 행렬 연산 라이브러리


STEP 1. 전반적인 원리

  • Color Segementation

    위의 사진처럼 해당 이미지에서 특정 색을 뽑아낼 것이다! 그 후 특정 색에 해당하는 지점은 흰 색(255)으로 다른 부분은 검은 색(0)인 mask를 만든다.

  • Mask

    그 후 background 이미지를 이용해 masking을 한다. 이 때 background 이미지는 미리 사람이 없는 부분을 찍어둔다! 이 background에 masking을 하면 res1이 나온다.
    ✅ 1. 특정 색깔을 뽑아서 마스크를 만든다
    ✅ 2. 미리 저장해둔 background 이미지에 마스크를 입힌다 = res1

  • Result

    만들어진 res1과 원본 이미지에서 mask한 부분을 뺀 res2을 합치면 우리가 원하는 결과물이 나온다.
    ✅ 3. 지금 카메라(또는 비디오)에서 들어온 이미지를 마스크만큼 뺀다 = res2
    ✅ 4. 두 개를 합친다! result



STEP 2. 코딩하기

import cv2
import numpy as np
import time, argparse

parser = argparse.ArgumentParser()
parser.add_argument('--video', help='Input video path')
args = parser.parse_args()

cap = cv2.VideoCapture(args.video if args.video else 0) 
# 비디오 파일을 읽는다. 비디오가 없다면 0으로 설정하여 웹캠이 켜진다. 

time.sleep(3)
# 3초간 정지 = 카메라를 켜지는데 시간이 걸리기 때문

# Grap background image from first part of the video **비디오 앞 부분에 사람이 나오지 않은 배경이 꼭 필요(중요)**
for i in range(60):
  ret, background = cap.read()

# 동영상의 결과값을 기록하기 위한 코드! 
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
out = cv2.VideoWriter('videos/output.mp4', fourcc, cap.get(cv2.CAP_PROP_FPS), (background.shape[1], background.shape[0]))
out2 = cv2.VideoWriter('videos/original.mp4', fourcc, cap.get(cv2.CAP_PROP_FPS), (background.shape[1], background.shape[0]))
# fps = cap.get(cv2.CAP_PROP_FPS) 카메라 프레임 수를 가져올 수 있습니다

while(cap.isOpened()):
  ret, img = cap.read() # 한 프레임씩 읽어온다! 원본 이미지가 img에 저장됨
  if not ret:
    break
  
  # Convert the color space from BGR to HSV
  # cv2.cvtColor() : 컬러 시스템을 변경한다. 
  # **원본 이미지를 BGR에서 HSV로 바꾼다.** 
  hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

  # Generate mask to detect red color
  # 빨간색의 범위는 0~10 170~180이라 두 개로 나누어 마스크 생성 후 더함! 
  # 0~10까지 빨간색
  lower_red = np.array([0, 120, 70]) # 채도는 120 밝기는 70
  upper_red = np.array([10, 255, 255]) # 채도는 255 밝기는 255
  mask1 = cv2.inRange(hsv, lower_red, upper_red) # **cv2.inRange() : 범위 안에 해당하는 값들로 마스크를 생성**

  # 170~180까지 빨간색
  lower_red = np.array([170, 120, 70])
  upper_red = np.array([180, 255, 255])
  mask2 = cv2.inRange(hsv, lower_red, upper_red)

  mask1 = mask1 + mask2 # 빨간색을 다 mask한 마스크가 탄생

# 검정색을 가리고 싶을 떄 
  # lower_black = np.array([0, 0, 0])
  # upper_black = np.array([255, 255, 80])
  # mask1 = cv2.inRange(hsv, lower_black, upper_black)

  '''
  # Refining the mask corresponding to the detected red color
  https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/py_morphological_ops/py_morphological_ops.html
  '''

  # Remove noise **마스크를 색만 뽑으면 노이즈가 발생해서 정제해주는 함수임**
  mask_cloak = cv2.morphologyEx(mask1, op=cv2.MORPH_OPEN, kernel=np.ones((3, 3), np.uint8), iterations=2) #노이즈 없애고
  mask_cloak = cv2.dilate(mask_cloak, kernel=np.ones((3, 3), np.uint8), iterations=1) # 픽셀 크기 늘리기 
  mask_bg = cv2.bitwise_not(mask_cloak)

  cv2.imshow('mask_cloak', mask_cloak)

  # Generate the final output
  # bitwise_and() : 두개의 행렬이 0이 아닌 것만 통과됨 즉 마스크 영역만 남음(And 연산)
  res1 = cv2.bitwise_and(background, background, mask=mask_cloak) # background에서 mask만 남고 
  res2 = cv2.bitwise_and(img, img, mask=mask_bg) # 캠으로 들어오는 이미지에서 mask가 안 된 부분만 남고 
  result = cv2.addWeighted(src1=res1, alpha=1, src2=res2, beta=1, gamma=0) 
  # cv2.addWeighted() 두 개의 이미지를 합친다 

  cv2.imshow('res1', res1)

  # cv2.imshow('ori', img)
  cv2.imshow('result', result)
  out.write(result)
  out2.write(img)

  if cv2.waitKey(1) == ord('q'):
    break

out.release()
out2.release()
cap.release()
  • 비디오 앞 부분에 사람이 나오지 않은 배경이 꼭 필요(중요)

    2초 정도 사람이 없는 배경을 찍어주고 등장하도록 하자! 즉 사람이 없는 60 frame 동안 background에 사람이 없는 이미지를 저장해준다!

  • 원본 이미지를 BGR에서 HSV로 바꾼다.
    ❓ HSV
    Hue 색조 Saturation 채도 Value 명도 를 나타낸다.
    openCV의 경우 H는 0~180 S는 0~255 V는 0~255까지의 범위를 갖는다.

BGR보다 HSV가 사람이 인식하는 색깔의 수치와 HSV 컬러시스템이 표현하는 방식이 가장 비슷하다고 한다. 즉 사람이 빨간색으로 인식하는 것을 빨간색으로 잘 표현해줄 수 있다고 한다.

HSV는 각도로 색을 나타낸다 opencv의 경우 위의 사진처럼 해당 각도를 해당 색으로 표현한다.

만약 빨간색으로 얻고 싶으면 다음과 같은 범위(0~10, 170~180)로 잘라주면 된다!

  • cv2.inRange() : 범위 안에 해당하는 값들로 마스크를 생성
    즉 lower_red와 upper_red 사이에 있는 애들은 255로 만들고 나머지는 0으로 만든다.

  • 마스크를 색만 뽑으면 노이즈가 발생해서 정제해주는 함수임
    링크를 클릭해보면 dilate함수와 morphologyEx 함수가 존재

dilate는 픽셀을 늘려주는 함수

morphologyEx는 노이즈를 삭제해주는 함수


❗ 결과 ❗

마침 잠옷이 빨간색이라ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 잘 가려진다
profile
SW Engineer 꿈나무 / 자의식이 있는 컴퓨터

0개의 댓글