5장. 영상 향상과 학습용 전처리
실습 5 — 컬러 사진 평활화: 채널마다와 밝기 채널만
노란 불빛 아래의 어둑한 과일 상자 그림(ch05_fruit_dim.png)을 세 가지로 평활화합니다. B, G, R 채널마다, YCrCb 의 Y 만, HSV 의 V 만 평활화한 뒤 색이 얼마나 바뀌었는지 견주고, Y 만 평활화한 그림을 out_ch05_color_eq.png 로 저장합니다.
1단계. 원본의 색 읽기
import cv2
import numpy as np
img = cv2.imread("ch05_fruit_dim.png")
spots = {"벽": (10, 10), "사과": (120, 40), "파란 천": (135, 120)} # 이름: (세로, 가로)
def describe(name, im):
"""B·G·R 평균과, 고른 자리의 색상 H(0~179) 를 찍는다."""
hsv = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
means = [round(v, 1) for v in cv2.mean(im)[:3]]
hues = {k: int(hsv[y, x, 0]) for k, (y, x) in spots.items()}
print(f"{name:8} B·G·R 평균 {means} 색상 H {hues}")
describe("원본", img)원본 B·G·R 평균 [42.6, 66.0, 103.0] 색상 H {'벽': 13, '사과': 3, '파란 천': 106}2단계. 채널마다 평활화
# split 으로 세 장으로 나눠 저마다 평활화하고 merge 로 다시 합친다
each = cv2.merge([cv2.equalizeHist(c) for c in cv2.split(img)])
describe("채널마다", each)채널마다 B·G·R 평균 [146.9, 139.9, 141.3] 색상 H {'벽': 91, '사과': 177, '파란 천': 113}3단계. 밝기 채널만 평활화
# YCrCb: 0번 채널 Y 가 밝기다. Y 만 펴고 BGR 로 되돌린다
ycc = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
ycc[:, :, 0] = cv2.equalizeHist(ycc[:, :, 0])
y_only = cv2.cvtColor(ycc, cv2.COLOR_YCrCb2BGR)
describe("Y 만", y_only)
# HSV: 2번 채널 V 가 밝기다. V 만 펴고 BGR 로 되돌린다
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
hsv[:, :, 2] = cv2.equalizeHist(hsv[:, :, 2])
v_only = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
describe("V 만", v_only)Y 만 B·G·R 평균 [110.1, 132.7, 168.0] 색상 H {'벽': 19, '사과': 2, '파란 천': 117}
V 만 B·G·R 평균 [58.2, 91.4, 147.3] 색상 H {'벽': 13, '사과': 3, '파란 천': 105}4단계. 나란히 보고 저장하기
import matplotlib.pyplot as plt
plt.rcParams["font.family"] = "Malgun Gothic"
plt.rcParams["axes.unicode_minus"] = False
panels = [("원본", img), ("B·G·R 채널마다", each), ("YCrCb 의 Y 만", y_only), ("HSV 의 V 만", v_only)]
fig, axes = plt.subplots(1, 4, figsize=(13, 2.9))
for ax, (title, im) in zip(axes, panels):
ax.imshow(cv2.cvtColor(im, cv2.COLOR_BGR2RGB)) # 컬러는 RGB 로 바꿔 띄운다
ax.set_title(title)
ax.axis("off")
plt.tight_layout()
plt.show()
# 밝기만 편 그림을 저장한다
print("저장:", cv2.imwrite("out_ch05_color_eq.png", y_only))저장: True
코드 설명
- 채널마다 평활화하면 B·G·R 평균이 146.9, 139.9, 141.3 으로 비슷해져 누런빛이 통째로 사라집니다. 벽의 색상 H 가 13(주황 계열)에서 91(청록 계열)로 바뀌어 벽이 하늘색이 됐습니다. 사과의 H 177 은 3장에서 본 것처럼 빨강의 다른 끝(170~179)이라 여전히 빨강입니다.
- Y 만 평활화하면 B·G·R 평균의 차례(R 168.0 > G 132.7 > B 110.1)가 원본과 같아 따뜻한 빛이 남고, 벽의 H 는 19, 파란 천은 117 로 같은 색 계열에 머뭅니다. 다만 사과처럼 원래 어둡던 곳은 더 어두워졌습니다.
- V 만 평활화하면 색상 H 가 벽 13, 사과 3, 파란 천 105 로 원본(13, 3, 106)과 거의 같습니다. H 를 건드리지 않고 V 만 바꿨기 때문입니다. 그림에서는 사과와 귤이 Y 만 했을 때보다 밝고 진하게 보입니다.
cv2.COLOR_YCrCb2BGR,cv2.COLOR_HSV2BGR로 되돌린 뒤에야 다시 BGR 그림으로 띄우고 저장할 수 있습니다.