टीएल; डीआर: 2 * 1LSB त्रिकोणीय-पीडीएफ dithering clamping के कारण 0 और 1 पर edgecases में टूट जाता है। एक समाधान उन edgecases में एक 1bit वर्दी तक lerp है।
मैं एक दूसरे उत्तर को जोड़ रहा हूं, क्योंकि यह देखने से मैं मूल रूप से थोड़ा अधिक जटिल हो गया था। ऐसा प्रतीत होता है कि यह मुद्दा "TODO: क्लैम्पिंग" की आवश्यकता है? मेरे कोड में जब से मैं 2012 में सामान्यीकृत से त्रिकोणीय dithering में बदल गया ... अंत में इसे देखने के लिए अच्छा लगता है :) समाधान / पोस्ट के लिए पूर्ण कोड का उपयोग करें : https://www.shadertoy.com/view/llXfzS
सबसे पहले, यहां वह समस्या है जिसे हम देख रहे हैं, जब 2 * 1LSB त्रिकोणीय-पीडीएफ के साथ 3 बिट्स के लिए एक संकेत की मात्रा:
- अनिवार्य रूप से हॉटमुल्टोमिक्स ने क्या दिखाया।
इसके विपरीत बढ़ते हुए, प्रश्न में वर्णित प्रभाव स्पष्ट हो जाता है: एडगैसेस में आउटपुट काले / सफेद करने के लिए औसत नहीं है (और वास्तव में ऐसा करने से पहले 0/1 से परे अच्छी तरह से फैली हुई है)।
एक ग्राफ को देखने से थोड़ी अधिक जानकारी मिलती है:
(ग्रे लाइन्स मार्क 0/1, ग्रे में भी जो सिग्नल हम आउटपुट की कोशिश कर रहे हैं, पीली-लाइन डीथर्ड / क्वांटीकृत आउटपुट का औसत है, लाल त्रुटि है (सिग्नल-एवरेज))।
दिलचस्प बात यह है कि सीमा पर न केवल औसत आउटपुट 0/1 है, बल्कि यह रैखिक (शोर के त्रिकोणीय पीडीएफ के कारण भी) नहीं है। निचले सिरे को देखते हुए, यह सहज ज्ञान युक्त बनाता है कि आउटपुट क्यों बदल जाता है: जैसे ही डिथर्ड सिग्नल नकारात्मक मानों को शामिल करना शुरू करता है, क्लैम्पिंग-ऑन-आउटपुट आउटपुट के निचले स्तरित भागों (यानी नकारात्मक मान) के मूल्य को बदलता है, जिससे औसत के मूल्य में वृद्धि। एक चित्रण क्रम में प्रतीत होता है (समान, सममित 2LSB dither, औसत अभी भी पीले रंग में)
अब, यदि हम केवल 1LSB सामान्यीकृत डार्स का उपयोग करते हैं, तो किनारों-मामलों में कोई समस्या नहीं है, लेकिन फिर निश्चित रूप से हम त्रिकोणीय डिटेरिंग के अच्छे गुणों को खो देते हैं (उदाहरण के लिए इस प्रस्तुति को देखें )।
ए (व्यावहारिक, अनुभवजन्य) समाधान (हैक) तो, [-0.5; 0.5] को वापस करने के लिए है [edgecase के लिए एक समान dithering):
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) );
शेष सीमा के लिए त्रिकोणीय dithering बरकरार रखते हुए, जो edgecases को ठीक करता है:
तो आपके प्रश्न का उत्तर नहीं देने के लिए: मुझे नहीं पता कि क्या अधिक गणितीय रूप से ठोस समाधान है, और यह जानने के लिए भी उत्सुक हूं कि परास्नातक अतीत ने क्या किया है :) तब तक, कम से कम हमारे पास अपने कोड को काम करने के लिए यह भयावह हैक है।
EDIT
I को केवल संकेत को संपीड़ित करने पर, प्रश्न में दिए गए समाधान-सुझाव को कवर करना चाहिए। क्योंकि औसत edgecases में रैखिक नहीं है, बस इनपुट-सिग्नल को संपीड़ित करने से एक आदर्श परिणाम नहीं होता है - हालांकि यह समापन बिंदुओं को ठीक करता है:
संदर्भ