[graphics] 선형 RGB 공간과 비선형 RGB 공간에서 색상 작업을 할 때 실질적인 차이점은 무엇입니까?

선형 RGB 공간의 기본 속성은 무엇이며 비선형 공간의 기본 속성은 무엇입니까? 8 비트 (또는 그 이상)에서 각 채널의 값에 대해 이야기 할 때 무엇이 ​​변경됩니까?

OpenGL에서 색상은 3 + 1 값이며 이것은 RGB + 알파를 의미하며 각 채널에 8 비트가 예약되어 있습니다. 이것이 제가 명확하게 얻는 부분입니다.

그러나 감마 보정에 관해서는 비선형 RGB 공간에서 작업하는 효과가 무엇인지 알 수 없습니다.

사진 편집을 위해 그래픽 소프트웨어에서 곡선을 사용하는 방법을 알고 있기 때문에 선형 RGB 공간에서 값을 그대로 가져 와서 조작하지 않고 수학 함수를 첨부하지 않고 각각 비선형 일 때 채널은 일반적으로 고전적인 멱 함수 동작을 따라 진화합니다.

이 설명을 실제 설명으로 받아 들여도 실제 선형 공간이 무엇인지 여전히 알 수 없습니다. -선형 색상 공간은 결국 모든 RGB 공간이 내가 이해하는 것에 대해 선형이기 때문에 인간의 눈에 더 적합합니다.



답변

RGB 색상으로 작업한다고 가정 해 보겠습니다. 각 색상은 세 가지 강도 또는 밝기로 표현됩니다 . “선형 RGB”와 “sRGB”중에서 선택해야합니다. 지금은 세 가지 다른 강도를 무시하여 단순화하고 하나의 강도 만 가지고 있다고 가정합니다. 즉, 회색 음영 만 처리하는 것입니다.

선형 색상 공간에서 저장하는 숫자와 숫자가 나타내는 강도 간의 관계는 선형입니다. 실제로 이것은 숫자를 두 배로 늘리면 강도 (회색의 밝기)가 두 배가된다는 것을 의미합니다. 두 개의 강도를 함께 추가하려면 (두 광원의 기여도를 기반으로 강도를 계산하거나 불투명 한 객체 위에 투명한 객체를 추가하기 때문에) 다음을 추가하기 만하면됩니다. 함께 두 개의 숫자. 어떤 종류의 2D 블렌딩이나 3D 셰이딩 또는 거의 모든 이미지 처리를 수행하는 경우 선형 색상 공간에서 강도를 원합니다., 숫자를 더하고 빼고 곱하고 나누기 만하면 강도에 동일한 효과를 낼 수 있습니다. 대부분의 색상 처리 및 렌더링 알고리즘은 모든 것에 추가 가중치를 추가하지 않는 한 선형 RGB로만 올바른 결과를 제공합니다.

정말 쉬운 것 같지만 문제가 있습니다. 빛에 대한 인간의 눈의 민감도는 높은 강도보다 낮은 강도에서 더 미세합니다. 즉, 구별 할 수있는 모든 강도의 목록을 작성하면 밝은 것보다 어두운 것이 더 많습니다. 다시 말해, 밝은 회색 음영보다 어두운 회색 음영을 더 잘 구분할 수 있습니다. 특히 8 비트를 사용하여 강도를 표현하고 선형 색상 공간에서이를 수행하면 너무 많은 밝은 음영이 발생하고 어두운 음영이 충분하지 않게됩니다. 어두운 영역에서는 밴딩이 발생하고 밝은 영역에서는 사용자가 구분할 수없는 흰색에 가까운 다양한 음영에 약간을 낭비하게됩니다.

이 문제를 피하고 8 비트를 최대한 활용하기 위해 sRGB 를 사용하는 경향이 있습니다 . sRGB 표준은 색상을 비선형으로 만들기 위해 사용할 곡선을 알려줍니다. 곡선은 하단이 더 얕아서 더 어두운 회색을 더 많이 가질 수 있고 상단이 더 가파르 기 때문에 밝은 회색이 더 적습니다. 숫자를 두 배로 늘리면 강도가 두 배 이상 증가합니다. 즉, sRGB 색상을 함께 추가하면 결과가 예상보다 더 밝아집니다. 요즘 대부분의 모니터는 입력 색상을 sRGB로 해석합니다. 따라서 화면에 색상을 표시하거나 채널당 8 비트 텍스처에 저장할 때 sRGB로 저장하면 이러한 8 비트를 최대한 활용할 수 있습니다.

이제 문제가 있음을 알 수 있습니다. 색상은 선형 공간에서 처리되지만 sRGB에 저장됩니다. 즉, 읽기에서 sRGB에서 선형으로 변환하고 쓰기에서 선형에서 sRGB로 변환을 수행하게됩니다. 이미 선형 8 비트 인텐시티에는 어두운 부분이 충분하지 않기 때문에 문제가 발생할 수 있으므로 한 가지 더 실용적인 규칙 이 있습니다. 피할 수있는 경우 8 비트 선형 색상을 사용하지 마십시오 . 8 비트 색상은 항상 sRGB라는 규칙을 따르는 것이 관습이되고 있으므로 강도를 8 비트에서 16 비트로 또는 정수에서 부동 소수점으로 넓히는 동시에 sRGB에서 선형으로 변환을 수행합니다. 마찬가지로 부동 소수점 처리를 완료하면 sRGB로 변환하는 동시에 8 비트로 좁 힙니다. 이 규칙을 따르면

sRGB 이미지를 읽을 때 선형 강도를 원하는 경우 다음 공식을 각 강도에 적용합니다.

float s = read_channel();
float linear;
if (s <= 0.04045) linear = s / 12.92;
else linear = pow((s + 0.055) / 1.055, 2.4);

반대로 이미지를 sRGB로 작성하려면 다음 공식을 각 선형 강도에 적용하십시오.

float linear = do_processing();
float s;
if (linear <= 0.0031308) s = linear * 12.92;
else s = 1.055 * pow(linear, 1.0/2.4) - 0.055; ( Edited: The previous version is -0.55 )

두 경우 모두 부동 소수점 값의 범위는 0 ~ 1이므로 8 비트 정수를 읽는 경우 먼저 255로 나누고 8 비트 정수를 쓰는 경우 255를 곱하고 싶습니다. 마지막으로 평소와 같은 방식입니다. 이것이 sRGB로 작업하기 위해 알아야 할 전부입니다.

지금까지 한 가지 강도 만 다루었지만 색상과 관련하여 더 영리한 일이 있습니다. 인간의 눈은 다른 색조보다 다른 밝기를 더 잘 구분할 수 있으므로 (기술적으로는 색차보다 휘도 해상도가 더 좋습니다) 색조와 별도로 밝기를 저장하여 24 비트를 더 잘 사용할 수 있습니다. 이것이 YUV, YCrCb 등의 표현이 시도하는 것입니다. Y 채널은 색상의 전체적인 밝기이며 다른 두 채널보다 더 많은 비트를 사용하거나 더 많은 공간 해상도를가집니다. 이렇게하면 RGB 강도와 같이 곡선을 적용 할 필요가 없습니다 (항상). YUV는 선형 색상 공간이므로 Y 채널의 숫자를 두 배로 늘리면 색상의 밝기가 두 배가되지만 RGB 색상에서 할 수있는 것처럼 YUV 색상을 더하거나 곱할 수 없습니다.

이것이 귀하의 질문에 대한 답이라고 생각하므로 간단한 역사적 메모로 끝낼 것입니다. sRGB 이전에는 오래된 CRT에 비선형 성이 내장되어있었습니다. 픽셀의 전압을 두 배로 늘리면 강도가 두 배 이상 증가합니다. 각 모니터마다 얼마나 달라 졌는지이 매개 변수를 감마 라고합니다 . 이 동작은 빛보다 더 어두워 질 수 있다는 것을 의미했지만, 먼저 보정하지 않으면 사용자의 CRT에서 색상이 얼마나 밝을 지 알 수 없기 때문에 유용했습니다. 감마 보정시작하는 색상 (아마도 선형)을 변환하고 사용자 CRT의 감마로 변환하는 것을 의미합니다. OpenGL은이 시대에서 왔기 때문에 sRGB 동작이 때때로 약간 혼란 스럽습니다. 하지만 이제 GPU 공급 업체는 위에서 설명한 규칙에 따라 작업하는 경향이 있습니다. 텍스처 또는 프레임 버퍼에 8 비트 강도를 저장할 때는 sRGB이고 색상을 처리 할 때는 선형입니다. 예를 들어, OpenGL ES 3.0, 각 프레임 버퍼 및 텍스처에는 “sRGB 플래그”가 있으며 읽고 쓸 때 자동 변환을 활성화 할 수 있습니다. sRGB 변환 또는 감마 보정을 명시 적으로 수행 할 필요가 없습니다.


답변

나는 “인간 색상 감지 전문가”는 아니지만 YUV-> RGB 변환에서 비슷한 것을 만났습니다. R / G / B 채널에는 가중치가 다르므로 소스 색상을 x로 변경하면 RGB 값이 다른 수량으로 변경됩니다.

말했듯이 저는 전문가가 아닙니다. 색상 보정 변환을 수행하려면 YUV 공간에서 수행 한 다음 RGB로 변환해야합니다 (또는 RGB에서 수학적으로 동등한 작업을 수행해야합니다. 데이터 손실). 또한 YUV가 최고의 기본 색상 표현인지는 모르겠지만 비디오 카메라가 해당 형식을 제공하므로 문제를 해결했습니다.

비밀 번호가 포함 된 마법의 YUV-> RGB 공식은 다음과 같습니다. http://www.fourcc.org/fccyvrgb.php


답변