OpenCV-Python 시작하기

1. 영상 파일 불러와서 출력하기

OpenCV API: https://docs.opencv.org/master/


OpenCV를 이용하여 영상 파일 불러와서 출력하는 프로그램 생성

import sys
import cv2

print("Hello, OpenCV", cv2.__version__)

# cat.bmp 파일을 불러와 img 변수에 저장
img = cv2.imread('cat.bmp')

# 영상 파일 불러오기가 실패하면 에러 메시지를 출력하고 종료
if img is None:
    print("Image load failed!")
    sys.exit()

# "image"라는 이름의 새 창 만들기
cv2.namedWindow("image")
# 이 창에 img 영상을 출력
cv2.imshow("image", img)
# 키보드 입력이 있을 때까지 대기
cv2.waitKey()

# 생성된 모든 창을 닫음
cv2.destroyAllWindows()


영상 파일 불러오기

cv2.imread(filename, flags=None) -> retval
  • filename: 불러올 영상 파일 이름 (문자열)
  • flags: 영상 파일 불러오기 옵션 플래그

    flags 기능
    cv2.IMREAD_COLOR BGR 컬러 영상으로 읽기 (기본값)
    shape=(rows, cols, 3)
    cv2.IMREAD_GRAYSCALE 그레이스케일 영상으로 읽기
    shape=(rows, cols)
    cv2.IMREAD_UNCHANGED 영상 파일 속성 그대로 읽기
    e.g. 투명한 PNG 파일: shape=(rows, cols, 4)
    → alpha channel(투명도 정보)까지 불러오기
  • retval: 불러온 영상 데이터 (numpy.ndarray)


영상 파일 저장하기

cv2.imwrite(filename, img, params=None) -> retval
  • filename: 저장할 영상 파일 이름 (문자열)
  • img: 저장할 영상 데이터 (numpy.ndarray)
  • params: 파일 저장 옵션 지정 (속성 & 값의 정수 쌍)


새 창 띄우기

cv2.namedWindow(winname, flags=None) -> None
  • winname: 창 고유 이름 (문자열)
  • flags: 창 속성 지정 플래그

    flags 기능
    cv2.WINDOW_NORMAL 영상 크기를 창 크기에 맞게 지정
    cv2.IMREAD_GRAYSCALE 그레이스케일 영상으로 읽기
    cv2.WINDOW_AUTOSIZE 창 크기를 영상 크기에 맞게 변경 (기본값)


창 닫기

cv2.destroyWindow(winname) -> None
cv2.destroyAllWindows() -> None
  • winname: 닫고자 하는 창 이름
  • cv2.destroyWindow(): 지정한 창 하나만 닫기
  • cv2.destroyAllWindows(): 열려있는 모든 창 닫기
  • 일반적으로 프로그램 종료 시 운영 체제에 의해 열려 있는 모든 창이 자동을 닫힘


창 위치 이동

cv2.moveWindow(winname, x, y) -> None
  • winname: 창 이름
  • x, y: 이동할 위치 좌표


창 크기 변경

cv2.resizeWindow(winname, width, height) -> None
  • winname: 창 이름
  • width: 변경할 창의 가로 크기
  • height: 변경할 창의 세로 크기
  • 창 생성 시 cv2.WINDOW_NORMAL 속성으로 생성되어야 동작
  • 영상 출력 부분의 크기만 고려함 (제목 표시줄, 창 경계는 고려되지 않음)


영상 출력하기

cv2.imshow(winname, mat) -> None
  • winname: 영상을 출력할 대상 창 이름
    • 만약, winname에 해당하는 창이 없으면(cv2.namedWindow()로 생성 안했을 때) 창을 새로 만들어서 영상 출력
  • mat: 출력할 영상 데이터 (numpy.ndarray)
  • uint16, int32 자료형 행렬의 경우, 행렬 원소 값을 255로 나눠서 출력 (정수는 0 ~ 255 사이로 가정)
  • float32, float64 자료형 행렬의 경우, 행렬 원소 값에 255를 곱해서 출력 (실수는 0 ~ 1 사이로 가정)
  • Windows 운영 체제에서는 Ctrl + C (복사), Ctrl + S (저장) 지원
  • 실제로는 cv2.waitKey() 함수를 호출해야 화면에 영상이 나타남
    • 단순히 cv2.imshow()만 실행하면 화면이 뜨고 바로 사라짐


키보드 입력 대기

cv2.waitKey(delay=None) -> retval
  • delay: 밀리초 단위 대기 시간
    • delay ≤ 0 이면 무한히 기다림
    • 기본값은 0
  • retval: 눌린 키 값(ASCII code)
    • 키가 눌리지 않으면 -1
  • cv2.waitkey() 함수는 OpenCV 창이 하나라도 있을 때 동작
  • 특정 키 입력을 확인하려면 ord() 함수 이용
  • 주요 특수키 코드: 27(ESC), 13(ENTER), 9(TAB)


Matplotlib 사용하여 영상 출력하기

  • 컬러 영상 출력
    • 컬러 영상 색상 정보가 RGB 순서이어야 함
    • cv2.imread() 함수로 불러온 영상은 BGR 순서이므로 RGB 순서로 변경해야 함 → cv2.cvtColor() 함수 이용
  • 그레이스케일 영상 출력
    • plt.imshow() 함수에서 컬러맵을 cmap=’gray’로 지정
import matplotlib.pyplot as plt
import cv2

# 컬러 영상 출력
imgBGR = cv2.imread('cat.bmp')
# BGR 순서를 RGB 순서로 변경
imgRGB = cv2.cvtColor(imgBGR, cv2.COLOR_BGR2RGB)

plt.axis('off')
plt.imshow(imgRGB)
plt.show()

# 그레이스케일 영상 출력
# 2차원 행렬의 밝기값만 저장
imgGray = cv2.imread('cat.bmp', cv2.IMREAD_GRAYSCALE)

plt.axis('off')
# cmap='gray' 해주어야 그레이스케일 출력 가능
plt.imshow(imgGray, cmap='gray')
plt.show()

# 두 개의 영상을 함께 출력
# plt.subplot(행개수 열개수 순번)
plt.subplot(121), plt.axis('off'), plt.imshow(imgRGB)
plt.subplot(122), plt.axis('off'), plt.imshow(imgGray, cmap='gray')
plt.show()


이미지 슬라이드쇼

  • 특정 폴더에 있는 이미지 파일(*.jpg) 목록 읽기
    • os.listdir()
      import os
    
      file_list = os.listdir('./images')
      # jpg만 발라내기
      img_files = [file for file in file_list if file.endswith('.jpg')]
    
    • glob.glob()
      import glob
    
      # 특정 패턴 문자열 불러오기
      img_files = glob.glob('./images/*.jpg')
    
  • 전체 화면 영상 출력 창 만들기
# 전체 화면으로 'image' 창 생성
# 전체화면 가능하게 하기 위해 cv2.WINDOW_NORMAL 속성으로 설정
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
# 전체화면 속성 설정
cv2.setWindowProperty('image', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
  • 이미지 슬라이드쇼 전체 코드
import sys
import glob
import cv2

# 이미지 파일을 모두 img_files 리스트에 추가
# glob.glob(): 특정 패턴 문자열 불러오기
img_files = glob.glob('./images/*.jpg')

# 파일 이름 리스트 출력해서 확인해보기
for f in img_files:
    print(f)

if not img_files:
    print("There are no jpg files in 'images' folder")
    sys.exit()

# 전체 화면으로 'image' 창 생성
# 전체화면 가능하게 하기 위해 cv2.WINDOW_NORMAL 속성으로 설정
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
# 전체화면 속성 설정
cv2.setWindowProperty('image', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

# 무한 루프
# 파일 개수 변수 만들기
cnt = len(img_files)
# 인덱스 변수 만들기
idx = 0

while True:
    # 이미지 불러오기
    img = cv2.imread(img_files[idx])

    # 제대로 불러왔는지 확인
    if img is None:
        print('Image load failed!')
        break

    # 이미지 출력하기
    cv2.imshow('image', img)
    # 대기 시간 1초(1000ms)
    # 만약 1초를 기다렸는데 ESC키가 눌러지지 않는 경우 -1을 리턴하여 계속 while 루프를 돌게 함
    if cv2.waitKey(1000) == 27:  # ESC
        break

    idx += 1
    # 인덱스가 개수보다 커지거나 같은 경우 0으로 초기화
    if idx >= cnt:
        idx = 0

cv2.destroyAllWindows()