OpenCV 비전 실무5장 · 영상 향상과 학습용 전처리18 / 21← 이전목차다음 →MetaContents

5장. 영상 향상과 학습용 전처리

실습 5 — 컬러 사진 평활화: 채널마다와 밝기 채널만

노란 불빛 아래의 어둑한 과일 상자 그림(ch05_fruit_dim.png)을 세 가지로 평활화합니다. B, G, R 채널마다, YCrCb 의 Y 만, HSV 의 V 만 평활화한 뒤 색이 얼마나 바뀌었는지 견주고, Y 만 평활화한 그림을 out_ch05_color_eq.png 로 저장합니다.

1단계. 원본의 색 읽기

Python
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단계. 채널마다 평활화

Python
# 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단계. 밝기 채널만 평활화

Python
# 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단계. 나란히 보고 저장하기

Python
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
원본, 채널마다 평활화, Y 만 평활화, V 만 평활화한 과일 상자 그림

코드 설명

  • 채널마다 평활화하면 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 그림으로 띄우고 저장할 수 있습니다.
← 이전 절5장 · 실습 4 — 히스토그램 평활화와 CLAHE 비교다음 절 →5장 · 프로젝트 1 — 어둡고 흐릿한 학습 사진 일괄 보정