5장. 영상 향상과 학습용 전처리
컬러 사진의 평활화
그림을 세 사람이 나눠 칠한다고 해 봅시다. 한 사람은 파랑, 한 사람은 초록, 한 사람은 빨강만 맡아서 저마다 "내 색을 고르게 진하게" 칠하면, 셋이 맞춰 두었던 색의 비율이 깨져 엉뚱한 색이 나옵니다. B, G, R 채널마다 따로 평활화하면 이런 일이 생깁니다. 3장에서 본 YCrCb 나 HSV 처럼 밝기를 따로 떼어 둔 색공간으로 바꾸면, 밝기 채널 하나만 평활화하고 색은 건드리지 않을 수 있습니다.
왼쪽 상자는 채널 세 장을 저마다 평활화하는 방법, 오른쪽 상자는 YCrCb 의 Y(밝기)만 평활화하는 방법입니다. 여기서 세 사람이 저마다 칠하는 것이 채널마다 평활화이고, 한 사람이 조명의 세기만 바꾸는 것이 밝기 채널만 평활화입니다. 3장에서 YCrCb 의 Y 가 흑백 밝기와 같은 식으로 구해진다고 했습니다.
가운데 그림은 채널마다 평활화한 결과입니다. 누런 벽이 하늘색으로, 나무 상자가 회색으로 바뀌었습니다. 오른쪽은 Y 채널만 평활화한 결과로, 벽과 상자의 색 계열은 원본 그대로 두고 밝기만 펴졌습니다. 그림은 노란 불빛 아래의 과일 상자를 도형으로 그린 가상의 그림(ch05_fruit_dim.png)입니다.
컬러 평활화의 세 방법
| 방법 | 순서 | 색(H) | 쓰는 곳 |
|---|---|---|---|
| 채널마다 | split → 세 장 모두 equalizeHist → merge | 바뀐다 | 쓰지 않는 것이 좋다 |
| YCrCb 의 Y | BGR2YCrCb → 0번 채널만 → YCrCb2BGR | 거의 그대로 | 밝기를 고르게 펼 때 |
| HSV 의 V | BGR2HSV → 2번 채널만 → HSV2BGR | 그대로 | 색상을 꼭 지켜야 할 때 |
짧은 예시
import cv2
img = cv2.imread("ch05_fruit_dim.png")
# BGR → YCrCb 로 바꾸고, 0번 채널(Y, 밝기)만 평활화한 뒤 다시 BGR 로
ycc = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
ycc[:, :, 0] = cv2.equalizeHist(ycc[:, :, 0])
fixed = cv2.cvtColor(ycc, cv2.COLOR_YCrCb2BGR)
# 왼쪽 위 벽 칸(세로 10, 가로 10)의 색상 H 를 견준다
def hue(im):
return int(cv2.cvtColor(im, cv2.COLOR_BGR2HSV)[10, 10, 0])
each = cv2.merge([cv2.equalizeHist(c) for c in cv2.split(img)])
print(hue(img), hue(each), hue(fixed)) # 결과: 13 91 19벽의 색상 H 는 원본 13(주황 계열)입니다. 채널마다 평활화하면 91(청록 계열)로 크게 바뀌고, Y 만 평활화하면 19 로 같은 주황 계열에 머뭅니다.
주의할 점
cv2.COLOR_YCrCb2BGR처럼 되돌리는 변환을 잊으면, YCrCb 숫자를 BGR 로 알고 띄워 색이 엉뚱하게 나옵니다.- Y 만 펴도 아주 어둡던 곳은 더 어두워질 수 있습니다. 평활화는 순서대로 자리를 다시 매기므로, 밝은 칸이 많은 사진에서는 어두운 칸이 앞자리로 밀려납니다.