객체인식, 이미지분할 등 컴퓨터 비전 task들 중에서 가장 기본이 되는 이미지 처리로 이미지속 객체들의 Contours를 찾고, 이를 시각화시키는 작업을 자주하게 된다. 이미지 속에서 객체들의 경계선을 추출한 contours는 보통 cv2.drawContours로 그려주게 될텐데, 이 때 matplotlib에서 제공하는 colormaps의 색상을 어떻게 활용할 수 있는지 아래에서 확인해보자.
우선, 이미지의 Contour를 얻기 위해 아래의 코드를 실행시켜줍니다.
import cv2
image = cv2.imread('./data/IMG_2421.jpg')
# read an image and convert BGR image to RGB and GRAY image
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
# threshold → Binary Image → find Contours
ret, thresh = cv2.threshold(gray, 127, 255, 0)
contour_thresh, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print("Number of Contours found with Canny edges = ", str(len(contour_thresh)))
# Number of Contours found with Canny edges = 4879
위의 코드로 얻어진 contour를 일단 간단하게 연두색으로 표시하여 시각화시켜보겠습니다.
import matplotlib.pyplot as plt
plt.figure(figsize=(30,16))
plt.subplot(131), plt.imshow(image), plt.title('Original Image', size=30), plt.axis('off')
plt.subplot(132), plt.imshow(thresh, cmap='gray'), plt.title('Threshold Image', size=30), plt.axis('off')
plt.subplot(133), plt.imshow(cv2.drawContours(np.copy(image), contour_thresh, -1, (0,255,0), 3)), plt.title('Contours with Threshold Image', size=30), plt.axis('off')
이제, 본격적으로 contour색을 matplotlib colormap색으로 바꿔보겠습니다.
colormap의 스펙트럼에 있는 색을 가져오기 위해서는 plt의 cm함수를 사용하면 됩니다.
cm들 중에서도 여러가지의 colormap들이 있는데, 그 중에서 저는 cool, spring, PiYG를 사용해보겠습니다.
(Matplotlib의 Colormaps의 종류들은 아래의 더보기에서 확인할 수 있습니다.)
https://matplotlib.org/stable/tutorials/colors/colormaps.html
# 코드로 색상 확인하는 법
n = 1400
cmap=plt.cm.get_cmap('cool', n)
cmap
먼저 코드를 돌려 실행한 결과입니다.
n = len(contour_thresh)
cool_colors = plt.cm.cool(np.linspace(0,1,n))
spring_colors = plt.cm.spring(np.linspace(0,1,n))
piyg_colors = plt.cm.PiYG(np.linspace(0,1,n))
cool_image, spring_image, piyg_image = np.copy(image), np.copy(image), np.copy(image)
for i in range(n):
cool_image = cv2.drawContours(cool_image, contour_thresh, i, 255*cool_colors[i], 3)
spring_image = cv2.drawContours(spring_image, contour_thresh, i, 255*spring_colors[i], 3)
piyg_image = cv2.drawContours(piyg_image, contour_thresh, i, 255*piyg_colors[i], 3)
plt.figure(figsize=(30, 16))
plt.subplot(131), plt.imshow(cool_image), plt.title('Cool Colormap', size=30), plt.axis('off')
plt.subplot(132), plt.imshow(spring_image), plt.title('Spring Colormap', size=30), plt.axis('off')
plt.subplot(133), plt.imshow(piyg_image), plt.title('PiYG Colormap', size=30), plt.axis('off')
코드에 대한 설명입니다.
#1 : colormap의 스펙트럼에 있는 색상들을 contour개수(n)만큼 나누어서 리스트로 불러온다.
- np.linspace() : 0부터1까지 n분의 1의 간격으로 쪼개진 수를 담아준다. (정규화 작업을 위한 것)
(ex.
- plt.cm.colormap()을 하게되면, colormap 스펙트럼을 0에서 1로 두고 n등분낸 후에 모든 위치의 색상을 리스트에 담아주게 됩니다. (0에서 255의 n등분을 내는 것 보다 0에서 1의 n등분이 쉽고, 간단하기 때문에 linspace를 활용하였습니다.)
n = len(contour_thresh)
# Continuous Colormap에서 n개의 discrete 색상 추출
cool_colors = plt.cm.cool(np.linspace(0,1,n))
spring_colors = plt.cm.spring(np.linspace(0,1,n))
piyg_colors = plt.cm.PiYG(np.linspace(0,1,n))
# 만약 반대순서로 스펙트럼 색상을 가져오고싶다면, 아래의 코드 실행
# spring_colors = plt.cm.spring(np.linspace(0,1,n)[::-1])
#2 : for 구문을 통해 colormap으로부터 불러온 색상들을 하나씩 지정하여 contour를 그려준다.
- drawContours(컨투어를 그려줄 이미지, contours list, 몇번째 contour를 그릴 것인지, contour 색상, contour 두께)
- for 구문을 통해 첫번째부터 n번째까지 각 순서에 맞는 i번째 contour를 i번째 색상으로 그려줍니다.
# image에 여러개가 중첩해서 그려지지 않도록 복사
cool_image, spring_image, piyg_image = np.copy(image), np.copy(image), np.copy(image)
for i in range(n):
cool_image = cv2.drawContours(cool_image, contour_thresh, i, 255*cool_colors[i], 3)
spring_image = cv2.drawContours(spring_image, contour_thresh, i, 255*spring_colors[i], 3)
piyg_image = cv2.drawContours(piyg_image, contour_thresh, i, 255*piyg_colors[i], 3)
#3 : 이미지 시각화를 통해 그려진 contour 색상 확인
plt.figure(figsize=(30, 16))
plt.subplot(131), plt.imshow(cool_image), plt.title('Cool Colormap', size=30), plt.axis('off')
plt.subplot(132), plt.imshow(spring_image), plt.title('Spring Colormap', size=30), plt.axis('off')
plt.subplot(133), plt.imshow(piyg_image), plt.title('PiYG Colormap', size=30), plt.axis('off')
한가지 색으로만 표시했을 땐 알 수 없었던 contour가 그려지는 순서도 알 수 있고, 한가지 색이 지루할 때 보기에도 예쁘게 표현할 수 있게 활용해보시면 좋을 것 같습니다.
감사합니다.
'Programming > python-computer vision' 카테고리의 다른 글
[python] OpenCV 이미지 시각화 코드 모음 (cv2.imshow) - vscode, jupyter, colab (0) | 2023.12.24 |
---|---|
Color Space (색공간), OpenCV (1) | 2023.07.13 |
기울어진 BBOX 이미지를 잘라내는 법, 수평으로 회전시키는 방법! (EasyOCR, OpenCV) (0) | 2023.02.17 |
바운딩 박스 텍스트 읽는 순서대로 정렬하는 법 | How to sort the shuffled bounding boxes in a same way to read text (0) | 2023.02.06 |
(OpenCV, Matplotlib) 파이썬에서 이미지 시각화하는 방법, 띄우는 방법 (0) | 2023.01.02 |