본문 바로가기

딥러닝

[딥러닝] 영상(Image), OpenCV-Python, 동영상 다루기

728x90

1. 영상(Image)

  • 픽셀이 바둑판 모양의 격자로 나열되어 있는 형태(2차원 행렬)
  • 픽셀: 이미지를 구성하는 가장 작은 단위
import cv2
print('현재 OpenCV 버전: ', cv2.__version__)

 

 

2. 그레이스케일 영상

  • 흑백 사진처럼 색상 정보가 없는 영상
  • 밝기 정보만으로 구성된 영상
  • 밝기 정보는 256단계로 표현(0~255)
  • 1픽셀은 8bits에 저장 = 1byte
  • 가로크기 * 세로크기 = 이미지 용량
    • 예) 28 * 28 = 784 bytes
img = cv2.imread('./dog.bmp', cv2.IMREAD_GRAYSCALE)
print(img)

cv2.imshow('img', img)    # 창이름: 'img'
cv2.waitKey()

import cv2
import matplotlib.pyplot as plt

# cv2를 통해 그레이스케일로 불러온 후 matplotlib으로 그레이스케일 영상 출력
img = cv2.imread('./dog.bmp', cv2.IMREAD_GRAYSCALE)
plt.axis('off')    # x축 y축을 숨김
plt.imshow(img, cmap='gray')    # colormap을 흑백으로 설정
plt.show()

 

 

3. 트루컬러 영상

  • 컬러 사진처럼 색상 정보를 가지고 있기 때문에 다양한 색상을 표현할 수 있는 영상
  • red, green, blue 색 성분을 사용하고 각 256단계로 표현
  • 픽셀의 표현 -> (255, 255, 255) 튜플 형태로 표현
  • 1픽셀은 3bytes
  • 가로크기 * 세로크기 * 3 = 이미지 용량
    • 28 * 28 * 3 = 2352 bytes
img = cv2.imread('./dog.bmp')    # cv2.IMREAD_COLOR 가 생략됨
print(img)

cv2.imshow('img', img)
cv2.waitKey()

 

 

✔️cv2를 통해 컬러로 불러온 후 matplotlib으로 컬러영상 출력

# OpenCV: BGR, matplotlib: RGB  때문에 색이 반전되어 출력됨
img = cv2.imread('./dog.bmp')
plt.axis('off')
plt.imshow(img)
plt.show()    # 비정상적으로 출력됨

 

 

✔️cv2를 통해 컬러로 불러온 후 matplotlib으로 컬러영상 출력

img = cv2.imread('./dog.bmp')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)    # BGR -> RGB
plt.axis('off')
plt.imshow(img)
plt.show()   # 정상적으로 출력됨

 

 

💡문제

    subplot을 이용하여 왼쪽에는 그레이스케일 영상, 오른쪽에는 컬러영상을 출력하라

img_gray = cv2.imread('./dog.bmp', cv2.IMREAD_GRAYSCALE)
img_color = cv2.imread('./dog.bmp')
img_color = cv2.cvtColor(img_color, cv2.COLOR_BGR2RGB)

plt.subplot(121)    # 1행 2열 첫 번째 subplot
plt.axis('off')
plt.imshow(img_gray, cmap='gray')

plt.subplot(122)    # 1행 2열 두 번째 subplot
plt.axis('off')
plt.imshow(img_color)
plt.show()

 

 

 

4. 영상 파일 형식

  • BMP
    • 픽셀 데이터를 압축하지 않고 저장
    • 용량이 매우 큼(픽셀의 일반적인 크기)
    • 파일 구조가 단순해서 별도의 라이브러리 없이 프로그래밍이 가능
  • JPG(JPEG)
    • 압축률이 좋아서 파일 용량이 크게 감소
    • 사진과 같은 컬러영상을 저장
    • 손실 압축
  • GIF
    • 움직이는 영상 지원
    • 256색 이하의 영상을 저장
    • 무손실 압축
  • PNG
    • 웹 이미지용으로 권장
    • 무손실, 손실 압축
    • 알파 채널(투명도)을 지원
    • (255, 255, 255, 1)

 

✔️영상 정보 알아보기

import cv2

img_gray = cv2.imread('./dog.bmp', cv2.IMREAD_GRAYSCALE)
print('img_gray type: ', type(img_gray))     
print('img_gray shape: ', img_gray.shape)    # (세로, 가로)
print('img_gray dtype: ', img_gray.dtype)    # uint8: 0~255

img_color = cv2.imread('./dog.bmp')
print('img_color type: ', type(img_color))
print('img_color shape: ', img_color.shape)   #(세로, 가로, 컬러)
print('img_color dtype: ', img_color.dtype)

 


 

💡문제1

     img_color가 그레이스케일 영상인지, 컬러영상인지 구분하라

if len(img_color.shape) == 3:
	print('컬러')
elif len(img_color.shape) == 2:
	print('그레이스케일')

- 컬러 이미지의 경우, 'shape' 속성은 '(height, width, channels)' 형태의 튜플을 반환한다.

- 그레이스케일 이미지의 경우, '(height, width)' 형태의 튜플을 반환한다.

 

 

💡문제2

     img_color에 특정 색 정보로 영상을 변경하라

# 방법1
for x in range(h):
	for y in range(w):
    	img_color[x, y] = (255, 102, 255)

cv2.imshow('img_color', img_color)
cv2.waitKey()

# 방법2
img_color[:,:] = (255, 102, 255)     # 이미지 배열의 모든 행과 모든 열

cv2.imshow('img_color', img_color)
cv2.waitKey()

 


 

✔️numpy를 사용하여 네 개의 이미지를 생성

import cv2
import numpy as np

img1 = np.zeros((240, 320), dtype=np.uint8)  # 모든 값이 0인 배열 -> 검정색
img2 = np.empty((240, 320), dtype=np.uint8)  # 메모리 공간만 할당하고 값을 초기화하지 않음 -> 임의의 값 포함
img3 = np.ones((240, 320), dtype=np.uint8) * 150   # 모든 값이 1인 배열 * 150 -> 회색
img4 = np.full((240, 320, 3), (155, 102, 255), dtype=np.uint8)  # 주어진 값으로 배열을 채움

cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
cv2.imshow('img3', img3)
cv2.imshow('img4', img4)
cv2.waitKey()

 

 

✔️copy() 함수 알아보기

import cv2

img = cv2.imread('./dog.bmp')
img_test = img.copy()     # 원본 이미지를 수정하지 않고 변형할 수 있음

img_test[90:210, 120:240] = (255, 102, 255)

cv2.imshow('img', img)
cv2.imshow('img_test', img_test)
cv2.waitKey()

 

import cv2

img = cv2.imread('./dog.bmp')
img_test = img    # 둘 다 'img'를 가리킴 -> img_test에 대한 모든 수정은 img에도 영향을 미침


img_test[90:210, 120:240] = (255, 102, 255)

cv2.imshow('img', img)
cv2.imshow('img_test', img_test)
cv2.waitKey()

 

 

✔️ 도형 그리기

import cv2
import numpy as np

img = np.full((500, 500, 3), 255, np.uint8)   # 500x500 크기의 흰색(255) 3채널 이미지

cv2.line(img, (70, 70), (400, 70), (0, 0, 255), 5)  # (70, 70)에서 (400, 70)까지 빨간색(0, 0, 255)의 두께 5인 선
cv2.rectangle(img, (50, 200, 150, 100), (0, 255, 0), 3)  # (50, 200)에서 (150, 100) 크기의 녹색 (0, 255, 0) 직사각형
cv2.rectangle(img, (50, 350, 150, 100), (0, 255, 0), -1)  # 두께가 -1로 설정되어 있어 직사각형 내부가 완전히 채워짐
cv2.circle(img, (300, 250), 50, (255, 0, 0), 4)  # 중심이 (300, 250)인 반지름 50의 파란색(255, 0, 0) 원

# (300, 400) 위치에 검정색(0, 0, 0) 텍스트, 0.7크기
cv2.putText(img, 'Hello OpenCV', (300, 400), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 0))

cv2.imshow('img', img)
cv2.waitKey()

 

5. OpenCV-Python 모듈

 

  • opencv
    • 컴퓨터 비전과 이미지 처리를 위한 오픈소스 라이브러리
    • 1999년 인텔에서 영상처리 기술을 개발하기 위한 목적으로 만듦
    • 2000년 BSD 라이선스로 배포
    • 2011년 이후 opencv2로 개발 시작
  • opencv 설치
    • pip install opencv-python
  • 모듈 불러오기
    • import cv2

 

6. 동영상 다루기

  • 카메라 영상 불러오기
    • cv2.VideoCapture(0)   
  • 동영상 불러오기
    • cv2.VideoCapture('파일경로')
  • 동영상 출력하기
    • FourCC(Four Character Code)
    • 4바이트로 된 문자열이며 데이터 형식을 구분하는 고유 글자
    • 주로 AVI 파일의 영상 코덱을 구분할 때 사용(DIVX, XVID, MP4V...)
      • 예) cv2.VideoWriter.fourcc(*'DIVX')    cv2.VideoWriter(파일명, FourCC객체, fps, (가로, 세로))

 

 

✔️ 카메라 영상 불러오기

import cv2
import sys

cap = cv2.VideoCapture(0)   # 기본 카메라 장치를 열어 cap 객체로 캡처

if not cap.isOpened():      # 카메라가 열리지 않은 경우
	print('카메라를 열 수 없음')
    sys.exit()
    
print('카메라 연결 성공')    # 카메라가 열린 경우
print('가로 사이즈: ', int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)))
print('세로 사이즈: ', int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
print('FPS: ', cap.get(cv2.CAP_PROP_FPS))   # FPS(Frame Per Second)


# ret: 영상을 읽었는지 여부(True, False)
# frame: 읽어온 영상
while True:
	ret, frame = cap.read()    # 카메라로부터 frame을 읽어옴
    if not ret:
    	break
    cv2.imshow('frame', frame)
    if cv2.waitKey(10) == 27:  # ESC 키 누르면 프로그램 종료
    	break
        
cap.release()    # 카메라 장치 해제

 

 

✔️ 동영상 불러오기

import cv2
import sys

cap = cv2.VideoCapture('./sea.mp4')    # 파일을 불러와 cap 객체에 저장
 
if not cap.isOpened():
	print('동영상을 불러올 수 없음')
    sys.exit()
    
print('동영상 연결 성공')
print('가로 사이즈: ', int(cap.get(cv2.CAP_PROP_FRAME_WIdth)))
print('세로 사이즈: ', int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
print('FPS: ', cap.get(cv2.CAP_PROP_FPS))
print('프레임수: ', int(cap.get(cv2.CAP_PROP_FRAME_COUNT)))   # 초당 프레임 수

while True:
	ret, frame = cap.read()
    if not ret:
    	break
    cv2.imshow('frame', frame)  # 읽어온 프레임을 화면에 표시
    if cv2.waitKey(10) == 27:
    	break
        
cap.release()

 

 

✔️ 실시간 동영상 캡처, 출력하기

 
import cv2

cap = cv2.VideoCapture(0)  # 기본 웹캠을 열어 객체에 저장

w = round(cap.get(cv2.CAP_PROP_FRAME_WIDTH)  # 캡처한 영상의 가로 크기
h = round(cap.get(cv2.CAP_PROP_FRAME_HEIGHT) # 세로 크기
fps = cap.get(cv2.CAP_PROP_FPS)

fourcc = cv2.VideoWriter.fourcc(*'DIVX')   # 'DIVX' 코덱을 사용하여 영상을 인코딩
out = cv2.VideoWriter('output.avi', fourcc, fps, (w, h))   # 영상을 파일로 저장

while True:
	ret, frame = cap.read()
    if not ret:   # ret: 프레임을 제대로 읽었는지를 나타내는 불리언 값
    	break
    out.write(frame)  # 캡처한 프레임을 파일(output.avi)에 저장
    cv2.imshow('frame', frame)  # 캡처한 프레임을 화면에 실시간으로 표시
    if cv2.waitKey(10) == 27:
    break
    
cap.release()
out.release()   # VideoWriter 객체를 해제하여 파일을 닫음

 

 

✔️ 두 개의 동영상 합쳐서 출력하기

import cv2
import sys

cap1 = cv2.VideoCapture('./sea1.mp4')   # 동영상 파일 불러오기
cap2 = cv2.VideoCapture('./sea2.mp4')

w = round(cap1.get(cv2.CAP_PROP_FRAME_WIDTH))    # 가로
h = round(cap1.get(cv2.CAP_PROP_FRAME_HEIGHT))   # 세로
frame_cnt1 = round(cap1.get(cv2.CAP_PROP_FRAME_COUNT))   # cap1의 프레임수
frame_cnt2 = round(cap2.get(cv2.CAP_PROP_FRAME_COUNT))   # cap2의 프레임수
fps1 = cap1.get(cv2.CAP_PROP_FPS)
fps2 = cap2.get(cv2.CAP_PROP_FPS)

fourcc = cv2.VideoWriter.fourcc(*'DIVX')
out = cv2.VideoWriter('mix.avi', fourcc, fps1, (w, h))   # 합쳐진 영상을 'mix.avi'파일로 저장

for i in range(frame_cnt1):     # 첫 번째 동영상 재생
	ret, frame = cap1.read()
    cv2.imshow('output', frame)
    out.write(frame)
    if cv2.waitKey(10) == 27:
    	break
        
for i in range(frame_cnt2):     # 두 번째 동영상 재생
	ret, frame = cap2.read()
    cv2.imshow('output', frame)
    out.write(frame)
    if cv2.waitKey(10) == 27:
    	break
        
cap1.release()
cap2.release()
out.release()
728x90