디더 노이즈를 고정하는 적절한 방법은 무엇입니까?


9

2 비트 노이즈 (n =] 0.5,1.5 [및 output = floor (input * (2 ^ bits-1) + n))로 색상 심도를 줄이고 디더링 할 때 값 범위의 끝 (입력 0.0 및 1.0) )가 시끄 럽습니다. 그것들을 단색으로하는 것이 바람직 할 것입니다.

예 : https://www.shadertoy.com/view/llsfz4

노이즈 그라디언트 (위의 그림은 그라디언트와 양쪽 끝을 각각 흰색과 검은 색으로 표시 해야 하지만 노이즈 가있는 셰이더 스토어의 스크린 샷입니다 )

물론 값 범위를 압축하여 끝을 항상 단일 값으로 반올림하여 문제를 해결할 수 있습니다. 이것은 약간의 해킹을 느끼며 이것을 "적절하게"구현할 수있는 방법이 있는지 궁금합니다.


어떤 이유로 든 쉐이더 토이가 내 브라우저에서 실행되지 않았습니다. 당신이 의미하는 바를 보여주기 위해 간단한 이미지를 게시 할 수 있습니까?
Simon F

1
n =]-1, 1 [과 같을까요?
JarkkoL

@JarkkoL 음수 부동 소수점을 정수로 변환하는 공식은 output = floor (input * intmax + n)입니다. 여기서 노이즈가없는 n = 0.5입니다 (예 :> = 0.5를 반올림하지만 <0.5는 내림). 이것이 소음이 0.5에서 "중심"이되는 이유입니다.
hotmultimedia

@SimonF 님이 shadertoy의 이미지를 추가했습니다
hotmultimedia

1
GPU와 같이 반올림하지 않고 출력을 자르는 것처럼 보입니다. 반올림하면 최소한 흰색이 표시됩니다. shadertoy.com/view/MlsfD7 (image : i.stack.imgur.com/kxQWl.png )
Mikkel Gjoel

답변:


8

TL; DR : 2 * 1LSB 삼각 -pdf 디더링이 클램핑으로 인해 0과 1에서 에지 케이스에서 끊어집니다. 해결책은 해당 에지 케이스에서 1 비트 균일 디더링으로 뛰어 드는 것입니다.

나는 이것이 원래 생각했던 것보다 조금 더 복잡하다는 것을 알면서 두 번째 대답을 추가하고 있습니다. 이 문제는 "TODO : 클램핑이 필요합니까?" 2012 년에 정규화에서 삼각 디더링으로 전환 한 이후 내 코드에서. 마침내 그것을 보는 것이 좋습니다 :) 게시물 전체에서 사용되는 솔루션 / 이미지의 전체 코드 : https://www.shadertoy.com/view/llXfzS

우선, 2 * 1LSB 삼각-PDF 디더링을 사용하여 신호를 3 비트로 양자화 할 때보고있는 문제는 다음과 같습니다.

출력 -본질적으로 hotmultimedia가 보여준 것.

대비가 증가하면 문제에 설명 된 효과가 분명해집니다. 가장자리의 경우 출력이 평균적으로 흑백으로 표시되지 않습니다 (실제로 0/1 이상으로 확장 됨).

여기에 이미지 설명을 입력하십시오

그래프를 보면 좀 더 통찰력을 얻을 수 있습니다.

여기에 이미지 설명을 입력하십시오 (회색 선은 0/1로 표시되며 회색으로도 출력하려고하는 신호이며, 노랑 선은 디더링 / 양자화 된 출력의 평균이며, 빨간색은 오류 (신호 평균)입니다.)

흥미롭게도, 한계에서 평균 출력이 0/1이 아니라 선형 일 수도 있습니다 (소음의 삼각형 pdf 때문일 수 있습니다). 하단을 보면 출력이 왜 분기되는지 직관적으로 이해할 수 있습니다. 디더링 된 신호가 음의 값을 포함하기 시작하면 클램핑-온-출력은 출력의 하단 디더링 된 부분의 값 (음의 값)을 변경합니다. 평균값 증가. 그림은 순서대로 나타납니다 (균일 한 대칭 2LSB 디더링, 평균은 여전히 ​​노란색).

여기에 이미지 설명을 입력하십시오

이제 1LSB 정규화 디더를 사용하면 가장자리에 전혀 문제가 없지만 삼각형 디더링의 좋은 속성을 잃게됩니다 (예 : 이 프레젠테이션 참조 ).

여기에 이미지 설명을 입력하십시오

(실용적이고 경험적인) 해킹 (해킹)은 엣지 케이스에 대해 [-0.5; 0.5 [균일 디더링)으로 되돌아가는 것입니다.

float dithertri = (rnd.x + rnd.y - 1.0); //note: symmetric, triangular dither, [-1;1[
float dithernorm = rnd.x - 0.5; //note: symmetric, uniform dither [-0.5;0.5[

float sizt_lo = clamp( v/(0.5/7.0), 0.0, 1.0 );
float sizt_hi = 1.0 - clamp( (v-6.5/7.0)/(1.0-6.5/7.0), 0.0, 1.0 );

dither = lerp( dithernorm, dithertri, min(sizt_lo, sizt_hi) );

삼각형 디더링을 나머지 범위에 그대로 유지하면서 가장자리를 고정시킵니다.

여기에 이미지 설명을 입력하십시오

따라서 귀하의 질문에 대답하지 않으려면 : 더 수학적으로 견고한 해결책이 있는지 모르겠으며 과거의 석사가 무엇을했는지 알고 싶습니다.) 그때까지는 코드가 계속 작동하도록하는이 끔찍한 해킹이 있습니다.

편집
나는 아마도 신호를 압축하는 것에 대한 The Question에서 주어진 해결 방법 제안을 다룰 것입니다. 엣지 케이스에서 평균값이 선형이 아니기 때문에 입력 신호를 압축하는 것만으로는 완벽한 결과를 얻지 못합니다. 여기에 이미지 설명을 입력하십시오

참고 문헌


가장자리의 삐걱 거리는 소리가 완벽하게 보입니다. 나는 약간의 편차를 기대할 것입니다 : P
Alan Wolfe

그래, 나는 또한 너무 놀랐다. 그렇다면 적어도 규모가 일치하지만 분포를 직접 혼합하면 부작용이없는 것으로 흥미 롭습니다.
Mikkel Gjoel

@MikkelGjoel 불행히도, 코드의 버그로 인해 귀하의 신념이 잘못되었습니다. 당신은 모두 같은 RNG를-재사용 dithertri하고 dithernorm대신 독립적 인 하나. 모든 수학을 공부하고 모든 용어를 취소하면 전혀 견딜 수 없다는 것을 알게 될 것입니다! 대신 코드는에서 하드 컷오프처럼 작동하여 v < 0.5 / depth || v > 1 - 0.5/depth즉시 균일 분포로 전환합니다. 그것은 당신이 가지고있는 멋진 디더링에서 벗어나는 것이 아니라 불필요하게 복잡합니다. 버그를 고치는 것은 실제로 나쁘다. 결국 디더링이 더 나빠질 것이다. 딱딱한 컷오프 만 사용하십시오.
orlp

더 깊이 파고 들었던 샘플을 평균화하는 동안 감마 보정을하지 않는 셰이더 토이에서 또 다른 문제가 발견되었습니다 (선형이 아닌 sRGB 공간 평균). 감마를 적절하게 다루면 불행히도 아직 끝나지 않은 것을 알 수 있습니다. 감마 보정을 처리하려면 노이즈를 형성해야합니다. 다음은 문제를 표시하는 shadertoy 입니다. shadertoy.com/view/3tf3Dn 나는 많은 것들을 시도했지만 그것을 작동시키지 못했습니다. 그래서 여기에 질문을 게시했습니다 : computergraphics.stackexchange.com/questions/8793/… .
orlp

3

나는 당신의 질문에 완전히 대답 할 수 있는지 확신 할 수 없지만 몇 가지 생각을 추가하고 함께 대답에 도달 할 수 있습니다 :)

첫째, 질문의 기초는 나에게 다소 불분명합니다. 다른 모든 색상에 노이즈가있을 때 깨끗한 흑백을 갖는 것이 바람직하다고 생각하는 이유는 무엇입니까? 디더링 후 이상적인 결과는 완전히 균일 한 노이즈를 가진 원본 신호입니다. 흑백이 다르면 노이즈가 신호에 따라 달라집니다 (어쨌든 색상이 고정되는 위치에서 발생하기 때문에 문제가되지 않을 수 있습니다).

즉, 흰색이나 검은 색으로 노이즈가 발생하는 경우 문제가 발생하는 상황이 있습니다 (흑백이 동시에 "깨끗해 져야"하는 사용 사례는 알지 못합니다). 텍스처의 경우 텍스처 외부에도 노이즈가 표시되므로 전체 쿼드에 노이즈를 추가하지 않아도됩니다. 한 가지 해결책은 [-0.5; 1.5 [를 더하는 대신 [-2.0; 0.0 [을 더하는 것 (즉, 2 비트의 잡음을 빼는 것))보다 잡음을 상쇄하는 것입니다. 이것은 상당히 실험적인 해결책이지만 더 정확한 접근법을 알지 못합니다. 그것에 대해 생각하면 손실 강도를 보상하기 위해 신호를 부스트하고 싶을 것입니다 ...

다소 관련 티모시 Lottes가 가장 필요한 스펙트럼의 부분에 노이즈 쉐이핑 스펙트럼의 밝은 단에 노이즈를 감소에 GDC 얘기 않았다 http://32ipi028l5q82yhj72224m8j-wpengine.netdna-ssl.com/wp- 내용 / 업로드 /2016/03/GdcVdrLottes.pdf


(실수로 실수로 Enter 키를 누르고 편집 시간 제한이 만료되었습니다.)이 예제의 사용 사례는 3 비트 디스플레이 장치에 부동 소수점 회색조 이미지를 렌더링하는 것이 중요한 상황 중 하나입니다. 여기서 LSB 만 변경하면 강도가 크게 바뀝니다. 값 범위를 압축하고 끝 값을 포화시키는 것과 같이 끝 값을 단색으로 매핑하는 "올바른 방법"이 있는지 이해하려고합니다. 그리고 그 수학적 설명은 무엇입니까? 예제 수식에서 입력 값 1.0은 평균 7에 해당하는 출력을 생성하지 않으므로 저를 귀찮게합니다.
hotmultimedia

1

삼각형 노이즈로 디더링하는 Mikkel Gjoel의 아이디어를 단일 RNG 호출 만 필요한 간단한 기능으로 단순화했습니다. 불필요한 비트를 모두 제거했기 때문에 현재 상황을 읽고 이해할 수 있어야합니다.

// Dithers and quantizes color value c in [0, 1] to the given color depth.
// It's expected that rng contains a uniform random variable on [0, 1].
uint dither_quantize(float c, uint depth, float rng) {
    float cmax = float(depth) - 1.0;
    float ci = c * cmax;

    float d;
    if (ci < 0.5 || ci >= cmax - 0.5) {
        // Uniform distribution on [-0.5, 0.5] for edges.
        d = rng - 0.5;
    } else {
        // Symmetric triangular distribution on [-1, 1].
        d = (rng < 0.5) ? sqrt(2.0 * rng) - 1.0 : 1.0 - sqrt(2.0 - 2.0*rng);
    }

    return uint(clamp(ci + d + 0.5, 0.0, cmax));
}

아이디어와 맥락에 대해서는 Mikkel Gjoel의 답변을 참조하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.