비디오 프로덕션에서의 색채 이론
2022년 6월 21일, 제이슨 교로그(Jason Gyorog)
그것은 단지 당신이 가진 상상 속의 색소일 뿐입니다.
이 바나나는 노란색이 아닙니다.
빨간색, 녹색 및 파란색 빛만 발생하는 화면을 통해 이 이미지를 거의 확실하게 볼 수 있습니다. 이것들은 빛의 “원색”이며, 우리가 아이들에게 크레용과 핑거 페인트로 가르치는 것처럼, 여러분은 원하는 색을 얻기 위해 그것들을 섞을 수 있습니다.
우리는 이 말을 마치 빛의 자연적인 특성인 것처럼 말하지만, 실제로 그것은 우리 인간의 눈이 가진 특성입니다. 인간은 노란색 빛의 파장을 감지하는 특별한 센서를 가지고 있지 않습니다. 우리는 빨강, 파랑, 초록 빛만 볼 수 있습니다.
심지어 햇빛에 비친 진짜 바나나를 볼 때도, 우리의 눈은 빨간색+녹색을 보고 우리에게 노란색이라고 말합니다. 그래서 우리는 노란색을 볼 수 없지만, 우리는 모두 바나나가 노란색이라는 것을 인식합니다.
색채 인지
여러분의 색 인지는 간상체(rod)와 추상체(cone)의 두 가지 주요 세포 유형에 기초합니다. 간상체는 빛의 양에 매우 민감하지만 색을 감지하지 못합니다. 그것들은 야간 시력의 주요 원천이고, 그것이 적은 빛에서 색을 보는 것이 어려운 이유입니다.
추상체는 빛의 파장에 더 구체적이지만 전반적으로 덜 민감합니다. 대부분의 사람들은 세 가지 종류의 추상체를 가지고 있습니다 (비록 드문 소수의 사람들은 실제로 네 개를 가지고 있습니다). 각 추상체 셀 유형은 분광의 작은 부분을 선택할 수 있으며, 각각 고유한 피크 감도를 갖습니다. 색상을 감지하려고 할 때 이 세 가지 입력 값만 사용할 수 있으므로 노란색과 빨간색+녹색을 구분하지 못하는 이유가 됩니다.
저는 햇빛에 비친 바나나가 실제 노란색 빛을 반사한다고 가정했는데, 이것은 우리가 빨강+녹색으로 보는 것입니다. 하지만 이것이 사실인지 확실히는 모릅니다. 저는 눈으로만 본 적이 있으니까요.
조금 더 알아보기
생물학적인 이 부분은 색 재현범위(Color Gamut)를 이해하는데 도움이 될 수 있습니다. 아래 다이어그램은 우리가 볼 수 있는 모든 색을 분류하고자 한 자료입니다. 아래 말발굽 모양의 둘레를 따라 단색광들이 있고, 그 의미는 그것들이 빛의 단일 파장으로 표현될 수 있다는 것을 의미합니다. 가운데는 다른 색깔의 빛을 섞어서 만드는 색깔들이 있습니다. 다이어그램상의 각 점은 다른 강도의 단색 색상의 여러 조합으로 나타낼 수 있습니다.
다이어그램 내의 삼각형은 HDTV의 표준인 Rec.709 색 재현범위 내에서 재현할 수 있는 색상을 나타냅니다.
위 사진의 삼각형은 UHDTV의 표준인 Rec.2020 색 재현범위를 보여줍니다.
이 두 개의 분리된 색 공간은 모두 8비트 숫자로 나타낼 수 있습니다. 이것은 10비트 비디오와 8비트 비디오 유형을 보여주는 것이 아닙니다. 조금 헷갈릴 수도 있지만 RGB(0,0,0)는 두 색 재현범위에서 모두 검은색이지만 RGB(0,255,0)로 표시되는 색상은 사용하는 색 재현범위에 따라 다른 색조의 녹색을 의미합니다. 즉, HDTV와 UHDTV에서 동일한 RGB(0,255,0) 값의 색상을 가져도 다른 색조를 가진다는 의미입니다. 8비트 값 대신 10비트 값을 사용하면 삼각형 내에서 더 정확한 위치를 알 수 있습니다.
자, 이제 R, G, B가 어디에서나 실제로 같은 R, G, B가 아니라고 말씀드렸으니 더 추상적인 값들을 살펴보도록 하겠습니다.
YUV Color
YUV 컬러 시스템은 비디오 프로덕션과 관련된 많은 것과 마찬가지로 초기 컬러 텔레비전과 관련이 있습니다. 흑백 방송은 본질적으로 색상 없이 빛의 세기를 정의했을 뿐입니다. 호환성을 유지하기 위해 기본 방송으로 유지되었으며, 색상 정보가 별도로 태그 되었습니다.(이는 또한 30을 사용하는 대신 ‘30000/1000’ 또는 ‘29.97 프레임률’로 이어졌습니다).
위의 색상 맵에서 “Y” 값(그래프의 높이)은 “밝기 신호(Luma)”로 정의되며, 이는 사물이 얼마나 밝게 보이는 지를 나타내는 척도입니다. YUV에서 사용되는 Y와 동일하지만, 두 성분은 다르게 계산됩니다. (“U”와 “V”는 각각 “색도” 성분, 파란색 투영 및 빨간색 투영입니다.) 다음 사진은 50% 밝기에서 Y와 함께 표시된 U-V 평면의 이미지입니다.
[번역자 해설] 위의 CIE xy 색도도는 CIE XYZ로부터 유도한 것인데 이 3자극치 XYZ의 Y는 휘도 (Luminance)를 뜻합니다. 휘도는 빛의 밝은 정도를 뜻하는 것이며 100cd/㎡, 1000cd/㎡, 10,000cd/㎡ 등과 같이 절대적이 단위가 사용됩니다. 반면에 YUV의 Y는 밝은 정도를 0 ~ 1로 정규화시킨 값이라 절대값이 아니라 상대값입니다. 그리고 YUV의 Y(정확하게근 Y’)’는 R’, G’, B’로부터 계산합니다. 따라서 YUV에서의 Y는 휘도와 구분하기 위해 Luma라고 흔히 부릅니다.
참고로, 본 컬럼에서 사용하고 있는 YUV라는 용어가 혼란을 줄 수 있습니다. 원래 YUV라는 용어는 NTSC 컬러 방송을 위해 만들어진 composite video의 색공간 (color space)을 뜻하는 것입니다. 현재의 디지털 영상이나 컴퓨터에서 말하는 YUV는 실제로는 NTSC의 YUV가 아니라 (흔히 BT.601의) YCbCr 색공간을 뜻합니다.
아까 말씀드렸듯이, 추상체은 간상체에 비해 그다지 민감하지 않습니다. 자, 우리는 U와 V에 대한 정보의 양을 줄일 수 있지만 Y에 대한 모든 정보를 유지할 수 있다는 것을 발견했습니다. 그 차이는 거의 감지할 수 없습니다. 왜냐하면 우리는 밝기의 차이가 색상의 미세한 차이보다 훨씬 더 크다는 것을 알기 때문입니다.
RGB와 YUV를 이용한 다채로운 실험
이 이미지에는 색상이 무작위로 섞여 있습니다. Gimp 이미지 에디터를 사용하여 몇 가지 색상을 선택하고, 얼룩을 만들고, 전체 크기를 축소하여 약간 섞었습니다. 그리고 이 사진이 결과입니다.
이 색상들을 가지고 RGB에서 YUV로 변환한 다음 4:2:2와 4:2:0 크로마 서브샘플링을 적용해서 어떤 효과가 있는지 보여드리겠습니다. 무작위로 선택한 색상에서는, 이것은 꽤 분명한 효과를 낼 수 있지만, 고해상도의 실제 비디오에서는 거의 감지할 수 없습니다.
저는 ffmpeg를 사용하여 이 이미지를 여러 픽셀 형식으로 변환하고 16진수 덤프로 출력을 볼 것입니다. 저는 16진 덤프에 대해 “표준” 출력(-C 플래그)을 사용하는 것을 좋아합니다. 왜냐하면 왼쪽에는 주소가 표시되고, 그 다음에는 바이트의 16진수 값이 표시되고, 오른쪽에는 ASCII 문자가 표시되기 때문입니다. 그러나 이 원시 이미지 데이터의 경우 오른쪽의 정보는 별로 유용하지 않습니다.
먼저, 우리는 평범하고 오래된 RGB를 폐기할 것입니다.
$ ffmpeg -nostdin -loglevel quiet -i original.png -pix_fmt rgb24 -f rawvideo – | hexdump -C
00000000 02 33 89 46 28 b1 d8 7d 2b 89 b6 29 b5 54 10 de |.3.F(..}+..).T..|
00000010 ce 80 ff 2f 15 c6 62 63 e0 cb 8b 9d b8 b6 aa 8b |…/..bc……..|
00000020 8a ad b5 ba cf b9 fa c1 f2 bc ad db 8f 82 dd 8b |…………….|
00000030 d1 cf 54 a1 df 98 6f 4e 8f 68 75 b9 b3 b9 8f b6 |..T…oN.hu…..|
00000040 b6 8b 50 78 b1 d9 dd d8 |..Px….|
00000048
RGB 24 픽셀 형식은 왼쪽 위 픽셀로 시작하고 빨간색, 녹색 및 파란색 각각에 대한 바이트를 포함합니다. 그런 다음, 오른쪽에 있는 다음 픽셀에 빨강, 녹색, 파랑이 지정됩니다. 이 작업은 줄의 끝에 도달할 때까지 왼쪽에서 오른쪽으로 진행되며, 왼쪽에서 아래로 다음 줄을 시작합니다. 이미지는 가로 6픽셀, 세로 4픽셀이므로 픽셀당 3바이트로 6x4x3=72바이트입니다. 각 행에는 8바이트가 표시되므로 예상대로 4줄 반이면 72바이트가 됩니다.
Gimp의 Dropper 도구를 사용하여 왼쪽 상단 픽셀을 선택할 수 있으며, RGB(2,51,137)의 색상 값이 출력의 처음 3바이트와 일치하는 RGB(0x02, 0x033, 0x089)로 16진수로 변환됩니다. HTML/CSS에서 이와 동일한 값을 사용하여 웹 페이지의 색상을 #023389로 지정할 수 있습니다.
Packed vs. Planar
이 형식은 “패킹된” 픽셀 형식인 반면, YUV 형식은 “평면”이기 때문에 저는 이들의 접점에 대해 이야기하려고 합니다. “평면” 형식에서는 각 픽셀에 대한 세 가지 값을 모두 알려 주는 대신 모든 Y 값이 먼저 제공된 다음 U, V가 모두 제공됩니다.(다음으로 이동하기 전에 각 픽셀에 대한 세 가지 값을 모두 알려주지 않습니다.) 이것을 증명하기 위해, 저는 모든 픽셀이 왼쪽 위 파란색인 버전의 이미지를 만들었습니다.
$ ffmpeg -nostdin -loglevel quiet -i allblue.png -pix_fmt rgb24 -f rawvideo – | hexdump -C
00000000 02 33 89 02 33 89 02 33 89 02 33 89 02 33 89 02 |.3..3..3..3..3..|
00000010 33 89 02 33 89 02 33 89 02 33 89 02 33 89 02 33 |3..3..3..3..3..3|
00000020 89 02 33 89 02 33 89 02 33 89 02 33 89 02 33 89 |..3..3..3..3..3.|
00000030 02 33 89 02 33 89 02 33 89 02 33 89 02 33 89 02 |.3..3..3..3..3..|
00000040 33 89 02 33 89 02 33 89 |3..3..3.|
00000048
보시다시피, 이는 동일한 3바이트가 24번(픽셀당 1개) 반복됨을 의미합니다.
$ ffmpeg -nostdin -loglevel quiet -i allblue.png -pix_fmt yuv444p -f rawvideo – | hexdump -C
00000000 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 |8888888888888888|
00000010 38 38 38 38 38 38 38 38 ad ad ad ad ad ad ad ad |88888888……..|
00000020 ad ad ad ad ad ad ad ad ad ad ad ad ad ad ad ad |…………….|
00000030 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 |dddddddddddddddd|
00000040 64 64 64 64 64 64 64 64 |dddddddd|
00000048
“02 33 89” 픽셀 색상으로 알려진 RGB(2,51,137)는 “38 ad 64″로 불리는 YUV(56,173,100)로 변환됩니다. 이것은 또한 동일한 색상을 계속해서 나타내지만 모든 Y 값이 그룹화된 다음 모든 U 값, 모든 V 값이 그룹화되는 것을 볼 수 있습니다. 이 변환의 이면에는 YUV에서 RGB로의 기록이 상당히 잘 되어 있습니다.
$ ffmpeg -nostdin -loglevel quiet -i allblue.png -pix_fmt yuv422p -f rawvideo – | hexdump -C
00000000 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 |8888888888888888|
00000010 38 38 38 38 38 38 38 38 ad ad ad ad ad ad ad ad |88888888……..|
00000020 ad ad ad ad 64 64 64 64 64 64 64 64 64 64 64 64 |….dddddddddddd|
00000030
4:2:2 하위 샘플링으로 변환하면 여전히 24개의 “38”의 인스턴스(픽셀당 하나씩)가 있지만 U 및 V 값에는 각각 12개의 값만 있음을 알 수 있습니다. 이는 해당 평면의 각 값이 2 픽셀을 나타내므로 절반이 되기 때문입니다. 왼쪽 상단 픽셀과 그 옆 픽셀은 U 및 V 값을 공유해야 합니다.
$ ffmpeg -nostdin -loglevel quiet -i allblue.png -pix_fmt yuv420p -f rawvideo – | hexdump -C
00000000 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 |8888888888888888|
00000010 38 38 38 38 38 38 38 38 ad ad ad ad ad ad 64 64 |88888888……dd|
00000020 64 64 64 64 |dddd|
00000024
4:2:0 서브샘플링을 사용하면 더욱 압축됩니다. 여전히 24개의 Y값을 가지고 있지만, U와 V는 각각 6개뿐입니다. 이 형식에서 4개의 픽셀로 구성된 각 블록은 U와 V 값을 공유하므로 왼쪽 상단 픽셀은 옆에 있는 픽셀과 아래에 있는 픽셀, 대각선 픽셀과 공유합니다.
색 변환
이제 다시 돌아가서, 이러한 변환이 원래 이미지에 어떤 영향을 미치는지 살펴보겠습니다. 여기에서 각 ffmpeg 명령은 원본 이미지를 요청된 서브샘플링 형식으로 변환한 다음 해당 데이터를 ffmpeg의 다른 인스턴스로 파이프합니다. 이 인스턴스는 서브 샘플링된 형식을 수신하고 새 이미지를 내보냅니다. 4:4:4 이미지(서브샘플링을 사용하지 않음)도 정확히 동일하지 않습니다. RGB에서 YUV로 변환하는 것은 반올림 오류 때문에 부분적으로 약간의 손실이 발생할 수 있기 때문입니다.
$ ffmpeg -nostdin -loglevel quiet -i original.png -pix_fmt yuv444p -f rawvideo – | ffmpeg -nostdin -loglevel quiet -f rawvideo -s 6×4 -pixel_format yuv444p -i pipe:0 yuv444p.png
$ ffmpeg -nostdin -loglevel quiet -i original.png -pix_fmt yuv422p -f rawvideo – | ffmpeg -nostdin -loglevel quiet -f rawvideo -s 6×4 -pixel_format yuv422p -i pipe:0 yuv422p.png
$ ffmpeg -nostdin -loglevel quiet -i original.png -pix_fmt yuv420p -f rawvideo – | ffmpeg -nostdin -loglevel quiet -f rawvideo -s 6×4 -pixel_format yuv420p -i pipe:0 yuv420p.png
yuv444p.png
yuv422p.png
yuv420p.png
4:4:4에서 4:2:0까지의 픽셀을 나란히 배열해봤습니다. 상단의 중간에 위치한 픽셀들(yuv422p.png)은 상당히 눈에 띄는 변화를 가지고 있습니다. 갈색과 녹색은 평균적으로 오염된 노란색으로 변합니다. 각 픽셀 쌍은 동일한 색상 값을 가지지만 고유한 강도 값을 얻습니다. 4:2:0 이미지를 보면 왼쪽 위 픽셀 쌍이 빨간색 픽셀 쌍으로 평균화되어 왼쪽 위 픽셀 블록 네 개가 모두 보라색을 띠는 것을 쉽게 볼 수 있습니다. 다시 말하지만 색도(색상) 값이 동일하더라도 휘도(강도) 값이 다르기 때문에 여전히 다른 음영으로 나타납니다.
보는 것이 믿는 것이다
마지막으로, 이 서브 샘플링이 실제 이미지에 어떤 영향을 미치는지 살펴보겠습니다. 온라인에서 찾은 대부분의 이미지는 이미 상당히 고도로 압축되어 있습니다. 원본이 이미 4:2:0 변환을 거쳤더라도 서로 인접한 픽셀이 충분히 다르다는 것을 보장하기 위해 Gimp를 사용하여 원본 2701×1920에서 1200×853으로 축소했습니다.
yuv444p yuv422p yuv420p의 포맷에 대해 다음을 수행합니다.
ffmpeg -nostdin -loglevel quiet -i Common_Jezebel_1200.png -pix_fmt $FORMAT -f rawvideo – |
ffmpeg -nostdin -loglevel quiet -f rawvideo -s 1200×853 -pixel_format $FORMAT -i pipe:0 Common_Jezebel_1200-${FORMAT}.png
Common_Jezebel_1200-yuv444p.png
Common_Jezebel_1200-yuv422p.png
Common_Jezebel_1200-yuv420p.png
보시다시피 크로마 서브 샘플링을 사용한 이미지는 원본과 거의 구별이 되지 않습니다. 이것이 바로 많은 카메라, 특히 휴대폰과 같은 소비자용 카메라가 YUV 4:2:0 비디오를 생성하는 이유입니다. 보관하기에는 더 작지만 여전히 훌륭한 품질을 제공합니다.
원래 RGB 값으로 크로마 서브샘플링을 할 수 있는 방법은 없습니다. 따라서 RGB 비디오는 YUV 형식에 비해 매우 드뭅니다. 압축 방법에 대해 점점 더 깊이 들어갈수록 실제 바이트의 숫자 값은 우리가 종종 색과 연관시키는 단순한 RGB 값에서 점점 멀어져 갑니다. 그러나 일반적으로 각 픽셀에 세 가지 색상만 있는 모니터에서 보기 때문에 대부분 RGB로 다시 변환할 수 있습니다.
빨강, 초록, 파랑은 빛의 “원색”이지만, 그것조차도 실제 빛의 파장이 작용하는 방식을 단순화한 것입니다. 그것은 단지 우리 인간의 눈에 충분한 것일 뿐입니다.