IT

맷플롯립(Matplotlib): 단일 플롯에 다수 이미지 그리기

유병혁 2018. 7. 25. 14:19

안녕하세요? 이번 글에서는 맷플롯립(Matplotlib)에서 단일 플롯에 다수 이미지를 그리는 방법을 정리해 보겠습니다.

먼저, 실습을 위한 이미지를 준비해 보겠습니다. 최근에 소백산국립공원 수목들을 드론으로 촬영한 이미지들입니다.


우선 해당 이미지들을 불러오기 위해 작업 디렉터리 위치를 변경합니다.

1
2
3
import os
os.getcwd() # 디렉터리 위치 리턴
os.chdir("D:\THMDATA"# 디렉터리 위치 변경
cs


맷플롯립 하부의 pyplot과 image 패키지를 불러옵니다. imread 함수로 IMG03.JPG 파일을 읽어보겠습니다.

imread는 이미지를 다차원 NumPy 배열(Red, Green, Blue)로 로딩합니다.  print를 통해 확인해보면 되겠습니다.

만약 아래 주석과 같이 ValueError가 발생했다면 Pillow 패키지가 설치되지 않아 png 파일만 지원되는 것입니다.

(명령 프롬프트에서 pip install pillow를 실행하셔서 해당 패키지를 설치해 주시면 됩니다.)


1
2
3
4
5
6
7
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
 
img = mpimg.imread('IMG03.jpg')
print(img)
## ValueError: Only know how to handle extensions: ['png'];
## with Pillow installed matplotlib can handle more images
cs


plot 패키지를 통해 이미지를 띄워본 결과는 아래와 같습니다:

1
2
plt.imshow(img)
plt.show()
cs



자, 이번에는 OpenCV와 맷플롯립을 함께 이용해 보도록 하겠습니다.

1
2
3
4
5
6
7
import cv2
 
img = cv2.imread('IMG03.jpg')
print(img)
 
plt.imshow(img)
plt.show()
cs



OpenCV도 다차원 NumPy 배열로 RGB 영상을 표현하지만 순서가 반대입니다.

따라서 BGR을 RGB로 순서 변경하고 그래프를 그리면 결과는 맷플롯립과 동일해집니다.

1
2
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show()
cs


이번에는 그래프의 제목을 추가하고, 이미지 특성에 맞게 축을 생략해 보도록 하겠습니다.

1
2
3
4
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title('Withered trees'# 제목 추가
plt.axis("off"# 축 제거
plt.show()
cs


결과는 아래와 같습니다.


이번에는 단일 플롯에 두 개의 이미지를 그려보도록 하겠습니다. 맷플롯립은 플롯을 rows*cols 행렬로 설정할 수 있습니다.

1
2
3
fig = plt.figure()
rows = 1
cols = 2
cs


아래와 같이 1*2 행렬에서 지정한 순서에 하부 플롯을 할당해주면 되겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
img1 = cv2.imread('IMG01.jpg')
img2 = cv2.imread('IMG03.jpg')
 
ax1 = fig.add_subplot(rows, cols, 1)
ax1.imshow(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB))
ax1.set_title('Jumok community')
ax1.axis("off")
 
ax2 = fig.add_subplot(rows, cols, 2)
ax2.imshow(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))
ax2.set_title('Withered trees')
ax2.axis("off")
 
plt.show()
cs


각 플롯에 제목을 추가하고 축을 제거한 상태의 결과는 아래와 같습니다.

이번에는 논문처럼 각 그림의 하단에 (a), (b)를 추가해 볼까요?! 결과는 다음과 같습니다.

1
2
3
4
5
6
7
8
9
10
11
ax1 = fig.add_subplot(rows, cols, 1)
ax1.imshow(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB))
ax1.set_xlabel('(a)')
ax1.set_xticks([]), ax1.set_yticks([])
 
ax2 = fig.add_subplot(rows, cols, 2)
ax2.imshow(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))
ax2.set_xlabel('(b)')
ax2.set_xticks([]), ax2.set_yticks([])
 
plt.show()
cs




자, 이제 반복문을 이용하여 폴더 내 이미지를 모두 검색하고, 이것을 rows*cols 행렬에 순차적으로 배치해 보도록 하겠습니다.

그림 제목은 xlabels라는 리스트를 생성하여 작성했고, 이미지 검색은 glob 모듈 기능을 이용했습니다. 결과는 다음과 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import glob
 
fig = plt.figure() # rows*cols 행렬의 i번째 subplot 생성
rows = 2
cols = 2
= 1
 
xlabels = ["xlabel""(a)""(b)""(c)""(d)"]
 
for filename in glob.glob("*.jpg"):
    img = cv2.imread(filename)
    ax = fig.add_subplot(rows, cols, i)
    ax.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    ax.set_xlabel(xlabels[i])
    ax.set_xticks([]), ax.set_yticks([])
    i += 1
 
plt.show()
cs