투명 망토 만들기

  1. 특정 색깔을 뽑아서 마스크를 만든다.
  2. 미리 찍어놓은 background 이미지에 마스크를 입힌다. (res1)
  3. 지금 카메라(또는 비디오)에서 들어온 이미지를 마스크만큼 뺀다. (res2)
  4. 두 개를 합친다. (res1 + res2)

 

파란색 HSV range 수정

lower_blue = np.array([105,120,70])
upper_blue = np.array([135,255,255])
mask1 = cv2.inRange(hsv, lower_blue, upper_blue)
 
 
import cv2
import numpy as np
import time, argparse

parser = argparse.ArgumentParser() # 인자값을 받을 수 있는 인스턴스
parser.add_argument('--video', help='Input video path') # 입력 받을 인자값 등록
args = parser.parse_args() # 입력받은 인자값을 args에 저장

cap = cv2.VideoCapture(args.video if args.video else 0) # 비디오를 불러오거나 없으면 웹캠 불러오기 

time.sleep(3) # 카메라가 켜지는 시간 때문에 3초간 멈춘다.

# Grap background image from first part of the video
for i in range(60): # 사람이 없는 60프레임 동안 이미지를 저장해놓는다.
    ret, background = cap.read() # background에 사람이 없는 이미지를 저장 

# 동영상의 결과값을 기록하기 위함
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]))

while(cap.isOpened()):
    ret, img = cap.read() # 한 프레임씩 읽어온다. 원본 이미지는 img에 저장된다.
    if not ret:
        break
  
    # Convert the color space from BGR to HSV
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    # 사람이 인식하는 색깔의 수치와 HSV컬러시스템이 표현하는 방식이 가장 비슷하다고 한다.
    
    # Generate mask to detect red color
    lower_red = np.array([0, 120, 70])
    upper_red = np.array([10, 255, 255])
    mask1 = cv2.inRange(hsv, lower_red, upper_red)

    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

    # 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. 두개의 행렬이 0이 아닌 것만 통과된다. 즉 segmentation한 마스크 영역만 남는다.
    res1 = cv2.bitwise_and(background, background, mask=mask_cloak)
    res2 = cv2.bitwise_and(img, img, mask=mask_bg) # 카메라로 들어온 이미지를 mask만큼
    result = cv2.addWeighted(src1=res1, alpha=1, src2=res2, beta=1, gamma=0) # 두개의 이미지를 합친다.

    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()

결과

 


느낀점

투명 망토 프로젝트는 초기 이미지를 저장해놓고 해당 색깔로 인식된 물체가 있다면, 그 물체를 초기 이미지로 덮는 간단한 원리로 진행된다. computer vision 관련 프로젝트에서 색을 잘 인지하기 위해서는 조명과 같은 환경이 매우 중요한 것 같다.

만약 딥러닝으로 진행되는 프로젝트라면 이미지 데이터를 구축할 때의 조명 환경도 많이 고려해야할 것 같다.

 

참고사항

- OpenCV를 사용해서 읽어 들인 이미지를 matplotlib로 화면에 출력할 때, 출력한 색이 이상하게 나오는데 그 이유는 OpenCV에서는 컬러 이미지를 RGB가 아닌 BGR순서로 저장하는데 matplotlib에선 RGB 순서로 저장하기 때문이다. 따라서 matplotlib에서 출력할 때는 BGR을 RGB로 바꿔줘야 한다.

 


RGB to HSV

- 일단, 특정 색상 객체를 추출하기 위해서 왜 HSV 이미지가 필요한지부터 알아야 한다.


RGB 모델

https://tattly.com/products/rgb

  1. RGB 모델은 빛의 삼원색을 이용하여 색을 표현하는 기본적인 색상 모델이다.
  2. 색을 빨강(Red), 초록(Green), 파랑(Blue), 3가지 성분의 조합으로 표현한다.
  3. R, G, B값은 0~255 사이의 값들로 표현된다.

HSV 모델

https://ko.wikipedia.org/wiki/HSV_%EC%83%89_%EA%B3%B5%EA%B0%84#/media/File:HSV_cone.jpg

 

  1. HSV 모델은 인간의 색인지에 기반을 둔 색상 모델이다.
  2. Hue(색조), Saturation(채도), Value(명도), 3가지 성분의 조합으로 표현된다.
  3. Hue(색조) : 색의 종류. 0º~360º 의 범위를 갖는다.
  4. Saturation(채도) : 색의 선명도, 진함의 정도(가장 진한 상태를 100%로 한다)
  5. Value(명도) : 색의 밝기, 밝은 정도(가장 밝은 상태를 100%로 한다)

RGB 에서 HSV로 변환하는 이유

- RGB 이미지에서 색 정보를 검출하기 위해서는 R, G, B 세가지 속성을 모두 참고해야한다.

- 하지만 HSV 이미지에서는 H(Hue)가 일정한 범위를 갖는 순수한 색 정보를 가지고 있기 때문에 RGB 이미지보다 쉽게 색을 분류할 수 있다.


RGB to HSV 공식

https://www.rapidtables.com/convert/color/rgb-to-hsv.html

 

- 위의 공식에서는 HSV 이미지를 H의 범위는 0~360으로 S, V는 0~1의 범위로 정규화 했다.

- OpenCV에서는 HSV 이미지를 H(0~180), S(0~255), V(0~255)로 표현한다.

- H(Hue)가 360이 아닌 180으로 범위를 지정한 이유는 OpenCV 이미지 변수들은 8bit로 설정되어 있어서 최대 255까지만 표현할 수 있기 때문이다.


mask 생성

- 모든 원소값이 0인 HSV 이미지와 같은 크기의 마스크 행렬을 만든다 

- HSV 이미지 픽셀 값과 내가 원하는 색상 범위를 비교해서 픽셀 값이 색상 범위 안에 있을 경우, 그에 대응되는 위치의 마스크 행렬의 원소 값에 1을 입력한다.

- HSV의 색상 범위는 다음과 같다.

 

- 구현 과정에서 색상의 범위를 지정하는게 제일 힘들었다. 육안으로 내가 검출하는 색상의 H, S, V값을 정확히 알 수 없기 때문에, 어느정도 예상해서 범위를 지정한 다음 잘 검출되는 범위로 계속 수정했다.

- OpenCV에서 색조 범위는 0~180이므로 원하는 색상을 얻으려면 HSV 색상표 값에서 1/2 해줘야 한다.

 

 

 

Ref : https://bradbury.tistory.com/64

복사했습니다!