4장. 채널 처리와 히스토그램 분석
채널 나누기와 합치기
샌드위치를 떠올려 봅시다. 빵, 햄, 치즈를 한 겹씩 떼어 내면 어느 재료가 얼마나 들었는지 따로 볼 수 있습니다. 햄만 바꿔 끼운 뒤 다시 포개면 새 샌드위치가 됩니다. OpenCV 의 cv2.split 은 겹을 떼어 내는 일, cv2.merge 는 다시 포개는 일입니다.
그림을 왼쪽부터 읽습니다. 컬러 그림을 split 으로 나누면 흑백 그림 세 장이 되고, 필요한 장만 손본 뒤 merge 로 다시 합칩니다. 여기서 샌드위치가 컬러 그림이고, 떼어 낸 재료 한 겹이 채널 하나입니다. 비유와 다른 점이 하나 있습니다. 샌드위치는 떼면 원래 것이 없어지지만, cv2.split 은 원본을 그대로 두고 복사본 세 장을 새로 만들어 줍니다.
나누는 두 가지 방법
| 방법 | 쓰는 법 | 돌려주는 것 | 고치면 원본은 |
|---|---|---|---|
cv2.split | b, g, r = cv2.split(img) | 복사본 세 장 | 그대로 |
| NumPy 인덱싱 | b = img[:, :, 0] | 원본을 보는 창(뷰) | 함께 바뀐다 |
| 인덱싱 + 복사 | b = img[:, :, 0].copy() | 복사본 | 그대로 |
짧은 예시
import cv2
import numpy as np
img = cv2.imread("ch04_scenes/sunset.png")
# cv2.split: 채널마다 한 장씩, 세 장의 흑백 그림을 돌려준다
b, g, r = cv2.split(img)
print(b.shape, g.shape, r.shape) # 결과: (240, 320) 세 번
# cv2.merge: 흑백 그림 목록을 받아 채널로 겹친다. 넣는 순서가 곧 B, G, R 순서다
back = cv2.merge([b, g, r])
print(np.array_equal(back, img)) # 결과: True → 원본과 똑같다
# np.shares_memory: 두 배열이 같은 숫자 저장소를 쓰는지 본다
print(np.shares_memory(img[:, :, 0], img)) # 결과: True → 인덱싱은 원본을 보는 창
print(np.shares_memory(b, img)) # 결과: False → split 은 복사본np.shares_memory 는 "메모리를 함께 쓰는가"라는 뜻입니다. True 면 한쪽을 고칠 때 다른 쪽도 바뀝니다.
주의할 점
cv2.merge에 넣는 그림들은 크기와 자료형이 모두 같아야 합니다. 하나라도 다르면 오류가 납니다.- 인덱싱으로 꺼낸 채널을 고치면 원본 그림이 함께 바뀝니다. 원본을 지켜야 하면
cv2.split을 쓰거나.copy()를 붙입니다. cv2.split은 숫자를 새로 복사하므로 큰 그림에서는 인덱싱보다 조금 느립니다. 채널 하나만 읽어 볼 때는 인덱싱으로 충분합니다.