딥러닝

[딥러닝] OpenCV

퓨어맨 2022. 7. 28. 12:46

OpenCV 개요

  • Computer Vision : 사람의 시각적인 부분을 기계로 구현하는것을 목적으로 하는 딥러닝 분야
  • 이미지, 동영상 등의 처리를 지원하는 라이브러리
  • C++로 제작되어 있고 Java, Android, Python 등 다양한 언어에서 구현 가능
  • 특히 Python에서 OpenCV를 사용할 경우 Numpy, Matplotlib 등의 라이브러리들과 바로 연동 가능

 

import numpy as np
import matplotlib.pyplot as plt
# OpenCV 임포트
import cv2

# 이미지 불러오기
cat = cv2.imread('image/image_cat.jpg')

# OpenCV와 matplotlib간 연동됨
plt.imshow(cat);

 

OpenCV의 색상 체계

  • 일반적인 이미지는 RGB 색상을 사용
  • OpenCV는 BGR 색상 체계를 사용함(그래서 RGB를 그대로 사용하면 Red계열 색상이 Blue계열로 변경되어 출력됨)
  • 초기에는 알파벳 순서대로 BGR로 쓰다가 이후에 색상 주파수가 낮은 순으로 RGB로 바뀌어 현재는 RGB가 대중적으로 사용됨
  • OpenCV에서는 RGB를 BGR로 변환하여 불러와야 함

 

cat = cv2.imread('image/image_cat.jpg')
# cvtColor : 색상 변환 함수
cat2 = cv2.cvtColor(cat, cv2.COLOR_RGB2BGR)

# x축, y축 좌표 눈금을 없애고 싶을때
plt.xticks([])
plt.yticks([])

plt.imshow(cat2);

 

 

이미지 색상 변환

  • 컬러 이미지(RGB)
  • 흑백 이미지(Gray) → 0 ~ 255 사이의 흑백 픽셀값으로 구성된 이미지
    • 컬러 이미지는 용량이 크고 연산량이 많기 때문에 실시간 처리가 힘들고, 이를 간소화시켜 계산과 연산을 용이하게 하기 위해 흑백이미지나 이진이미지를 사용
    • 컬러 이미지는 채도와 명도에 영향을 받기 때문에 이를 최소화 하기 위함
      • 명도(밝은 정도) - 밤에 색상을 볼 때 정확한 색상을 보여주지 못하는 경우 존재
      • 채도(탁한 정도) - 색상에 빛을 강하게 비추는 경우 정확한 색상을 보지 못하는 경우가 존재
  • 이진 이미지(binary) → 0(검정)과 255(흰) 두가지 색상으로만 구성된 이미지
    • 배경과 객체를 구분
    • 관심 영역과 비관심 영역을 분리
    • 필터를 만들거나 단순한 이미지 처리를 할 경우 사용

 

 

흑백(Gray) 이미지 만드는 방법

1. 기존 컬러 이미지를 Gray로 불러서 출력하기

# 이미지를 불러올때 gray로 받아주고 출력시에도 gray 색상으로 변환하여 출력
cat_gray = cv2.imread("image/image_cat.jpg", cv2.IMREAD_GRAYSCALE)

plt.imshow(cat_gray, cmap='gray');

 

2. 컬러 이미지를 그대로 불러온 다음 cvtColor를 통해 gray로 변환 후 출력하기

cat2 = cv2.imread("image/image_cat.jpg")

cat2_gray = cv2.cvtColor(cat2, cv2.COLOR_BGR2GRAY)

plt.imshow(cat2_gray, cmap='gray');

 

 

이진(binary) 이미지 만들기

  • 기존 이미지가 컬러 이미지라면 gray로 변환 후에 이진 이미지로 만들어줘야 함!
# threshold : 특정 기준을 통해서 데이터를 변환시켜주는 함수(문턱(경계)이라는 뜻)
# (이미지, 경계 기준값, 경계값보다 클 경우 적용되는 값, 경계값 적용 방식)
# 경계 기준값 : 0 ~ 255 값 중에서 선택
# 적용값 : 기준값보다 큰 경우에 할당되는 값(150보다 크면 255, 작으면 0)
_, bi_cat = cv2.threshold(cat2_gray, 150, 255, cv2.THRESH_BINARY)

# _ : 첫번째 리턴값은 받지 않음(경계값)
# bi_cat : 두번째 리턴값은 threshold가 적용된 이미지 데이터

plt.imshow(bi_cat, cmap='gray');

 

경계값 적용 방식 종류

  • cv2.THRESH_BINARY : 픽셀값이 경계값보다 크면 value(적용값), 아니면 0을 할당(흰색, 검은색으로만 표시)
  • cv2.THRESH_BINARY_INV : THRESH_BINARY의 반대(픽셀값이 경계값보다 크면 0, 아니면 value를 할당)
  • cv2.THRESH_TRUNC : 픽셀값이 경계값보다 크면 경계값, 아니면 픽셀값을 그대로 할당
  • cv2.THRESH_TOZERO : 픽셀값이 경계값보다 크면 픽셀값, 아니면 0을 할당(검은색을 좀 더 부각)
  • cv2.THRESH_TOZERO_INV : THRESH_TOZERO의 반대(픽셀값이 경계값보다 크면 0, 아니면 픽셀값 할당)

 

 

동영상 혹은 카메라(웹 캠) 불러오기

  • 카메라로부터 프레임 캡쳐 후 연결하여 영상으로 보여주기
  • 동영상 파일로부터 프레임 캡쳐 후 연결하여 영상으로 보여주기
# 영상 파일을 다룰 때는 예외처리(제대로 동작하지 않았을 경우에 대한 처리)를
# 해주는 것이 오류방지에 좋음

# 1. 영상 파일에서 프렝미단위로 사진을 캡쳐해 받아오기
try :
    # VideoCapture : 동영상을 프레임 단위로 캡쳐
    # 1) 웹 캠으로 부터 캡쳐
    # 카메라번호 - USB포트 번호, 일반적으로 0
    cap = cv2.VideoCapture(0)
    
    # 2) 동영상으로 부터 캡쳐
#    cap = cv2.VideoCapture("image/video.mp4")
    print("비디오 캡쳐 시작")
    
except :
    print("비디오 캡쳐 실패")
    
# 2. 캡쳐해 온 프레임을 계속해서 한 장씩 읽어와 연결하여 출력(영상으로 보여주겠음!)
while True:
    # read : 캡쳐한 이미지 프레임을 한 장씩 읽어오는 함수
    # ret : 읽기 성공여부(True, False)
    # frame : 읽어온 이미지 데이터(numpy 배열 타입)
    ret, frame = cap.read()
    
    # 프레임을 읽지 못했거나 영상의 모든 프레임을 다 읽었을 경우 종료
    if ret == False :
        print("프레임 읽기 실패 or 프레임 모두 읽음!")
        # 비디오 캡쳐 종료
        cap.release()
        # 생성한 창을 모두 닫아주기
        cv2.destroyAllWindows()
        break
    
    # 윈도우 창 크기 변경
#     frame = cv2.resize(frame, (1000, 700))
    
    # 흑백 영상 출력
#     frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    
    # imshow : 새 윈도우 창을 띄워서 이미지를 계속 출력(윈도우 창 이름, 전달받을 프레임)
    cv2.imshow("Video", frame)
    
    # waitKey : 키보드의 특정 키 값을 입력할 때까지 기다리는 명령
    # (숫자) : 한 장의 프레임을 읽어들이고 40ms 기다렸다 다음 사진을 읽어들일 수
    #          있도록 딜레이를 주는 역할
    key = cv2.waitKey(40)
    # ex) 영상이 초당 60 프레임이라면 16 ms로 설정
    # 영상 초당 프레임수와 waitKey값의 차이가 나면 플레이 자체는 문제 없지만
    # 마지막 프레임이 잘리는 현상이 발생할 수 있음
    
    # 재생중에 영상을 끄고 싶을 경우
    # 윈도우 창의 X를 누르지 말고 키보드로 멈춰야함(X누르면 에러뜨거나 커널 재시작)
    # 27 : 아스키코드로 ESC
    # 49 : 아스키코드로 1
    if key == 27:
        print("동영상 읽기 종료")
        cap.release()
        cv2.destroyAllWindows()
        break

 

 

영상 녹화하기

try:
    cap = cv2.VideoCapture("image/video.mp4")
    print("비디오 캡쳐 시작!!")
except:
    print("비디오 캡쳐 실패ㅠㅠ")
    
# 녹화될 파일 설정
fps = 30.0           # 초당 프레임 수
w = int(cap.get(3))  # 캡쳐한 비디오의 가로(3)크기
h = int(cap.get(4))  # 캡쳐한 비디오의 세로(4)크기

# 영상의 코덱 설정(CODEC : COder and DECoder)
# COder : 음성 또는 영상의 신호를 디지털 신호로 변환
# DECoder : coder의 반대
# DIVX : 일반적으로 avi 파일에 많이 사용되는 코덱
codec = cv2.VideoWriter_fourcc(*'DIVX')

out = cv2.VideoWriter("image/record_file.avi", codec, fps, (w,h))

# 녹화 상태 여부
record = False

while True :
    ret, frame = cap.read()
    
    if ret == False :
        print("비디오 읽기 실패 또는 비디오 모두 읽음")
        cap.release()
        out.release()
        cv2.destroyAllWindows()
        break
    
    cv2.imshow("record", frame)
    
    # 영상 녹화 시작 여부
    if record :  # record가 True가 되면 녹화시작!
        out.write(frame)
        
    k = cv2.waitKey(40)
    
    if k == 27 :
        print("영상 및 녹화를 종료합니다")
        cap.release()
        out.release()
        cv2.destroyAllWindows()
        break
        
    # 숫자 2 키보드
    if k == 50 :
        print("녹화를 시작합니다")
        record=True

'딥러닝' 카테고리의 다른 글

[딥러닝] 로이터뉴스 카테고리분류(RNN+LSTM)  (0) 2022.07.28
[딥러닝] Simple RNN  (0) 2022.07.26
[딥러닝] 데이터 증강(ImageDataGenerator)  (0) 2022.07.26
[딥러닝] VGG16 모델  (0) 2022.07.26
[딥러닝] CNN 모델  (0) 2022.07.26