파이썬 openCV 16번째 강의는 RGB에서 YCbCr로(RGB to YCbCr)입니다. YCbCr는 일반적으로는 들어보신적이 없으실겁니다. 하지만 이 역시 꽤 많이 사용된 색공간으로, 이번 시간에 자세히 알려드리겠습니다.
0. YCbCr?
YCbCr은 일반적으로 실생활에 사용되는 색공간은 아닙니다. YCbCr은 RGB나 cmyk, HSV처럼 무언가의 약자가 아닌 Y(휘도)와 Cb/Cr(색채/크로마)의 값으로 이루어 졌다고 해서 YCbCr입니다. 그래서 YCbCr이라고 하는 경우도 있고, YCrCb 또는 YCC라고 하는 경우도 있습니다.
YCbCr의 색공간입니다. RGB와 비슷한 모양인것을 확인하 실 수 있으실겁니다. 그 이유는 YCbCr은 RGB의 인코딩 방식중 하나이기 때문에 RGB와 거의 비슷한 모양의 색공간을 가지게 됩니다. 따라서 RGB를 알면 YCbCr을 1:1 매칭으로 변환시킬 수 있고, YCbCr을 알면 RGB로 다시 역변환 시킬 수 있습니다.
1. openCV에서의 YCbCr
YCbCr역시 RGB에서 변환하는 공식이 따로 있습니다.
이때 delta는 영상에 따라 바뀌게 됩니다. 이번 영상은 0 ~ 255의 RGB값을 갖는 8bit 영상이기에 delta값은 128로 설정하겠습니다.
img = cv2.imread('lenna.png') height, width, channel = img.shape b = img[..., 0] g = img[..., 1] r = img[..., 2] |
이제 기본설정입니다. 이미지를 불러와주고, 크기를 구해주고, rgb로 나누어줍니다. 전에도 말씀드렸다시피 파이썬 openCV는 b, g, r 순서로 불러옵니다.
y = np.zeros((height, width), dtype=np.float) cr = np.zeros((height, width), dtype=np.float) cb = np.zeros((height, width), dtype=np.float) |
이제 y, cb, cr의 값을 구하기 위해 빈 영상을 만들어줍니다.
for i in range(height):
for j in range(width):
y[i][j] = 0.299 * r[i][j] + 0.587 * g[i][j] + 0.114 * b[i][j]
cr[i][j] = (r[i][j] - y[i][j]) * 0.713 + 128
cb[i][j] = (b[i][j] - y[i][j]) * 0.564 + 128
이제 각 화소별 Y, Cb, Cr값을 구하기 위해 중첩 for문을 사용하여 위 공식에 맞게 계산해줍니다.
out = (np.dstack((y, cr, cb))).astype(np.uint8) |
이제 합쳐진 영상을 만들어 줍니다. 이때, 순서를 YCbCr이 아닌, YCrCb로 맞춰줍니다. 그 이유는 openCV에서는 YCbCr의 순서가 아닌 YCrCb의 순서로 인식하기 때문에 openCV의 기준에 맞게 합쳐주어야 재대로된 결과가 나오기 때문입니다.
이제 완성된 영상을 확인해보겠습니다.
이번 영상들도 각각의 Y, Cb, Cr은 단일 채널이라 흑백으로 나옵니다. 합쳐진 영상도 원본과는 다르게 보이지만, 역변환공식을 적용하면 다시 원래의 R, G, B를 구하실 수 있습니다.
또한, 이번 YCbCr도 HSV와 마찬가지로 openCV 자체에서 변환 함수가 있습니다.
ycbcr = cv2.cvtColor(img, cv2.COLOR_BGR2YCR_CB) |
이때 COLOR_BGR2YCrCb와 COLOR_BGR2YCR_CB 두가지가 존재하는데, COLOR_BGR2YCR_CB가 기본적인 포맷입니다. 이렇게 분리한 후
y2, cr2, cb2 = cv2.split(ycbcr) |
각 채널별로 나눠주시면 똑같이 나오게 됩니다
2. 마치며
이번 강의에서 내장 함수로 변환한 영상과, 직접 계산한 영상이 똑같은 것을 볼 수 있습니다. 그 이유는 기본적인 RGB에서 YCbCr공식이 아닌, openCV에서 자체적으로 공지하고 있는 YCbCr변환 공식을 사용하였기에 같은 프로세스를 거쳤다고 할 수 있기 때문입니다.
원래의 변환 공식으로 계산하실 수 있으나, 표기만 다를 뿐, 사실상 거의 같은 공식입니다.
def rgb2ycbcr():
img = cv2.imread('lenna.png')
height, width, channel = img.shape
b = img[..., 0]
g = img[..., 1]
r = img[..., 2]
y = np.zeros((height, width), dtype=np.float)
cr = np.zeros((height, width), dtype=np.float)
cb = np.zeros((height, width), dtype=np.float)
for i in range(height):
for j in range(width):
y[i][j] = 0.299 * r[i][j] + 0.587 * g[i][j] + 0.114 * b[i][j]
cr[i][j] = (r[i][j] - y[i][j]) * 0.713 + 128
cb[i][j] = (b[i][j] - y[i][j]) * 0.564 + 128
out = (np.dstack((y, cr, cb))).astype(np.uint8)
cv2.imshow('original', img)
cv2.imshow('ycbcr', out)
cv2.imshow('y', y.astype(np.uint8))
cv2.imshow('cb', cb.astype(np.uint8))
cv2.imshow('cr', cr.astype(np.uint8))
ycbcr = cv2.cvtColor(img, cv2.COLOR_BGR2YCR_CB)
y2, cr2, cb2 = cv2.split(ycbcr)
cv2.imshow('ycbcr2', ycbcr)
cv2.imshow('y2', y2)
cv2.imshow('cb2', cb2)
cv2.imshow('cr2', cr2)
cv2.waitKey(0)
'파이썬 강의 > openCV' 카테고리의 다른 글
파이썬 openCV 18. 에지검출 : 로버츠(roberts), 프리윗(prewitt), 소벨(sobel) (0) | 2020.12.07 |
---|---|
파이썬 openCV 17. 에지검출 : 유사 연산자(Homogeneity)와 차 연산자(Difference)기법 (1) | 2020.12.06 |
파이썬 openCV 15. RGB에서 HSV(HSI)로(RGB to HSV) (3) | 2020.12.01 |
파이썬 openCV 14. RGB에서 CMYK로(RGB to CMYK) (0) | 2020.11.29 |
파이썬 openCV 13. 블러링(blurring)/스무딩(smoothing)/샤프닝(sharpening) (0) | 2020.11.28 |