OpenCV 프로그래밍 - Chapter 02 영상 및 비디오 입출력
python으로 배우는 OpenCV 프로그래밍
- OpenCV 프로그래밍 - Chapter 01 서론
- OpenCV 프로그래밍 - Chapter 02 영상 및 비디오 입출력
- OpenCV 프로그래밍 - Chapter 03 간단한 그래픽 및 이벤트 처리
- OpenCV 프로그래밍 - Chapter 04 OpenCV 기본연산
- OpenCV 프로그래밍 - Chapter 05 임계값과 히스토그램 처리
- OpenCV 프로그래밍 - Chapter 06 영상 공간 필터링
이 포스팅은 ‘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() | 모든 윈도우 파괴 |
- 각 메서드에 대한 설명
- cv2.imread()는 영상파일을 numpy.ndarray의 배열로 읽어 반환한다.
읽기에 실패하면 None을 반환하며, flags는 cv2.IMREAD_COLOR(디폴트), cv2.IMREAD_GRAYSCALE, cv2.IMREAD_UNCHANGED등의 읽기 옵션이다. - cv2.imwrite()는 numpy.ndarray의 배열 img를 filename의 영상파일로 저장한다.
파일의 확장자에 의해 영상포맷이 결정된다.
params는 압축 관련 인수로 생략할 수 있다. - cv2.namedWindow()는 지정한 winname에 해당하는 이름을 갖는 윈도우를 생성한다.
flags는 cv2.WINDOW_AUTOSIZE(디폴트), cv2.WINDOW_NORMAL이 있다. - cv2.imshow()는 winname윈도우에 영상 mat를 표시한다.
winname 윈도우가 생성되어 있지 않아도 실행가능하다. - cv2.waitKey()는 키보드 입력을 위해 ms단위로 대기한다. 디폴트값은 0이며 디폴트일땐 키보드 입력이 있을 때까지 무한대기한다.
- cv2.destroyWindow()는 주어진 winname윈도우만 파괴하고, cv2.destroyAllWindows()는 모든 윈도우를 파괴한다.
- cv2.imread()는 영상파일을 numpy.ndarray의 배열로 읽어 반환한다.
영상파일 읽기 및 화면 표시
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)
위 실습코드를 실행 시키면 다음과 같은 결과가 출력되며, 키보드 입력이 있으면 모든 윈도우가 파괴된다.
또한 위 코드를 실행하면 다음과 같은 결과가 출력된다.
(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로 변환해줘야 한다.
변환하지 않고 그대로 출력할 경우 다음과 같고
변환하고 출력할 경우 다음과 같다.
각 출력결과의 하단에 표시된 값을 비교하면 이해하기 쉽다.
즉 채널을 표현하는 순서가 다를 뿐 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개의 채널만 가지고 있음을 알 수 있다.
만약 plt.imshow(imgGray)로 결과를 출력한다면 다음과 같은 결과가 출력된다.
실행 시켜본 결과 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()