/ OPENCV

OpenCV 프로그래밍 - Chapter 02 영상 및 비디오 입출력

python으로 배우는 OpenCV 프로그래밍

이 포스팅은 ‘python으로 배우는 OpenCV 프로그래밍’ 교재를 참고하여 작성하였습니다.

01 영상 입출력과 디스플레이

파이썬에서 OpenCV로 영상파일을 읽고, 윈도우 화면에 표시하고, 파일로 저장하는 방법에 대해 알아본다.

아래 표현에서 []는 생략 가능한 옵션을 나타내고, 화살표는 함수의 반환값을 표현한다.

반환값이 없을 경우 화살표는 생략한다.

영상 입출력과 디스플레이 함수

함수 비고
cv2.imread(filename[,flags]) -> retval 영상 입력
cv2.imwrite(filename,img[,params]) -> retval 영상파일 출력
cv2.namedWindow(winname[,flags]) 윈도우 생성
cv2.imshow(winname, mat) 윈도우 표시
cv2.waitKey([, delay]) -> retval 키보드 입력 대기
cv2.destroyWindow(winname) 윈도우 파괴
cv2.destroyAllWindows() 모든 윈도우 파괴
  • 각 메서드에 대한 설명
    1. cv2.imread()는 영상파일을 numpy.ndarray의 배열로 읽어 반환한다.
      읽기에 실패하면 None을 반환하며, flags는 cv2.IMREAD_COLOR(디폴트), cv2.IMREAD_GRAYSCALE, cv2.IMREAD_UNCHANGED등의 읽기 옵션이다.
    2. cv2.imwrite()는 numpy.ndarray의 배열 img를 filename의 영상파일로 저장한다.
      파일의 확장자에 의해 영상포맷이 결정된다.
      params는 압축 관련 인수로 생략할 수 있다.
    3. cv2.namedWindow()는 지정한 winname에 해당하는 이름을 갖는 윈도우를 생성한다.
      flags는 cv2.WINDOW_AUTOSIZE(디폴트), cv2.WINDOW_NORMAL이 있다.
    4. cv2.imshow()는 winname윈도우에 영상 mat를 표시한다.
      winname 윈도우가 생성되어 있지 않아도 실행가능하다.
    5. cv2.waitKey()는 키보드 입력을 위해 ms단위로 대기한다. 디폴트값은 0이며 디폴트일땐 키보드 입력이 있을 때까지 무한대기한다.
    6. cv2.destroyWindow()는 주어진 winname윈도우만 파괴하고, cv2.destroyAllWindows()는 모든 윈도우를 파괴한다.

영상파일 읽기 및 화면 표시

import cv2

imageFile = './data/lena.jpg'
img  = cv2.imread(imageFile)    # cv2.IMREAD_COLOR
img2 = cv2.imread(imageFile, 0) # cv2.IMREAD_GRAYSCALE
cv2.imshow('Lena color',img)
cv2.imshow('Lena grayscale',img2)

cv2.waitKey()
cv2.destroyAllWindows()

print(img.shape)
print(img2.shape)

위 실습코드를 실행 시키면 다음과 같은 결과가 출력되며, 키보드 입력이 있으면 모든 윈도우가 파괴된다.

image

또한 위 코드를 실행하면 다음과 같은 결과가 출력된다.

(512, 512, 3)
(512, 512)

이 결과가 의미하는 바는 img = cv2.imread(imageFile)는 디폴트로 BGR 3채널의 값으로 출력됨을 알 수 있다
그리고 img2 = cv2.imread(imageFile, 0)는 flags값에 cv2.IMREAD_GRAYSCALE를 의미하는 0값이 입력되어 있으므로 1채널의 값으로 출력됨을 알 수 있다.
또한 이미지의 픽셀이 512*512라는 것 또한 알 수 있다.

영상파일 저장

import cv2

imageFile = './data/lena.jpg'
img = cv2.imread(imageFile) # cv2.imread(imageFile, cv2.IMREAD_COLOR)
cv2.imwrite('./data/Lena.bmp', img)
cv2.imwrite('./data/Lena.png', img)
cv2.imwrite('./data/Lena2.png',img, [cv2.IMWRITE_PNG_COMPRESSION, 9])
cv2.imwrite('./data/Lena2.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 90])

위 실습 코드는 영상파일을 저장하는 코드이며 간단한 예제이므로 설명은 생략한다.

matplotlib 1 : 컬러 영상 표시

import cv2
from   matplotlib import pyplot as plt

imageFile = './data/lena.jpg'
imgBGR = cv2.imread(imageFile) # cv2.IMREAD_COLOR
#plt.axis('off')
plt.imshow(imgBGR)
plt.show()

imgRGB = cv2.cvtColor(imgBGR,cv2.COLOR_BGR2RGB)
plt.imshow(imgRGB)
plt.show()

matplotlib은 BGR이 디폴트고, cv2는 RGB가 디폴트이므로 plt.show()를 사용해 결과를 출력할때에는 cv2.cvtColor()를 사용해서 BGR을 RGB로 변환해줘야 한다.
변환하지 않고 그대로 출력할 경우 다음과 같고
image 변환하고 출력할 경우 다음과 같다. image

각 출력결과의 하단에 표시된 값을 비교하면 이해하기 쉽다. 즉 채널을 표현하는 순서가 다를 뿐 RGB로 처리하는 것은 동일하다.
plt는 BGR순서로 RGB를 표현, cv2는 RGB순서로 RGB를 표현

matplotlib 2 : 그레이스케일 영상 표시

import cv2
from   matplotlib import pyplot as plt

imageFile = './data/lena.jpg'
imgGray = cv2.imread(imageFile, cv2.IMREAD_GRAYSCALE)
#plt.axis('off')

plt.imshow(imgGray, cmap = "gray", interpolation='bicubic')
plt.show()

plt.imshow(imgGray, cmap = “gray”, interpolation=’bicubic’)는 imgGray영상을 ‘gray’컬러맵(cmap), ‘bicubic’으로 보간한다.
따라서 다음과 같은 결과가 출력되며 3개의 채널을 가지던 RGB와 달리 1개의 채널만 가지고 있음을 알 수 있다. image 만약 plt.imshow(imgGray)로 결과를 출력한다면 다음과 같은 결과가 출력된다. image 실행 시켜본 결과 0이 검정색 255가 흰색을 의미하는 것을 알 수 있었다.

위에서 plt로 결과 출력한 윈도우에는 여백이 존재한다.
다음 코드는 이 여백을 조정하는 코드이다.

matplotlib3 : 여백 조정 및 영상 저장

import cv2
from   matplotlib import pyplot as plt

imageFile = './data/lena.jpg'
imgGray = cv2.imread(imageFile, cv2.IMREAD_GRAYSCALE)

plt.figure(figsize=(6,6))
plt.subplots_adjust(left=0, right=1, bottom=0, top=1)
plt.imshow(imgGray, cmap = 'gray')
##plt.axis('tight')
plt.axis('off')
plt.savefig('./data/0205.png')
plt.show()