ASCII कैरेक्टर पिक्सेल नहीं हैं: ASCII rendering की गहन पड़ताल
(alexharri.com)- इमेज के आउटलाइन और आकार को संरक्षित रखने वाली ASCII rendering तकनीक विकसित की गई, जिससे पारंपरिक तरीकों में दिखने वाली धुंधली किनारों की समस्या हल हुई
- पिक्सेल-स्तर की साधारण brightness mapping की जगह, हर कैरेक्टर के visual shape को संख्यात्मक रूप से मापकर मैच करने वाला high-dimensional vector-आधारित approach इस्तेमाल किया गया
- हर कैरेक्टर के लिए ऊपर, नीचे, बाएँ, दाएँ क्षेत्रों की density मापकर 2D से 6D तक विस्तारित shape vector बनाया गया, जिससे अधिक सटीक कैरेक्टर चयन संभव हुआ
- boundary की sharpness बढ़ाने के लिए global और directional contrast enhancement algorithms लागू किए गए
- GPU acceleration, caching, और k-d tree search के जरिए real-time ASCII rendering performance हासिल की गई, जिससे high-quality visual effect संभव हुआ
इमेज से ASCII में रूपांतरण
- ASCII में 95 printable characters होते हैं, और monospace font का उपयोग करके इमेज को grid में विभाजित किया जाता है
- हर cell की brightness निकालकर उसे कैरेक्टर density के अनुसार map किया जाता है
- साधारण nearest-neighbor interpolation से boundaries पर असमान jaggies प्रभाव पैदा होता है
- supersampling के जरिए cell के भीतर कई sample लेकर average brightness निकाली जाए तो परिणाम थोड़ा smooth होता है, लेकिन boundaries फिर भी धुंधली रहती हैं
- मूल समस्या यह है कि कैरेक्टर्स को पिक्सेल की तरह माना जाता है, यानी उनकी अपनी visual shape को ध्यान में नहीं रखा जाता
कैरेक्टर shape का उपयोग
- हर कैरेक्टर में cell के भीतर visual density distribution अलग होती है
- उदाहरण:
Tऊपर की ओर भारी होता है, जबकिLनीचे की ओर भारी होता है
- उदाहरण:
- इसे संख्यात्मक रूप देने के लिए cell के भीतर sampling circle रखे जाते हैं, और हर क्षेत्र में कैरेक्टर के occupancy ratio की गणना की जाती है
- ऊपर और नीचे के दो क्षेत्रों की occupancy को vector के रूप में व्यक्त कर 2D shape vector बनाया जाता है
- हर कैरेक्टर का shape vector पहले से compute करके रखा जाता है, और इमेज के sampling vector से Euclidean distance के आधार पर सबसे नज़दीकी कैरेक्टर चुना जाता है
6D shape vector तक विस्तार
- केवल ऊपर-नीचे वाला 2D representation
-,p,qजैसे बीच या बाएँ-दाएँ केंद्रित कैरेक्टर्स को ठीक से व्यक्त नहीं कर पाता - cell को 6 sampling circles तक बढ़ाकर ऊपर-मध्य-नीचे और बाएँ-दाएँ के अंतर सभी को capture किया जाता है
- 6D shape vector कैरेक्टर के आकार को कहीं अधिक सटीकता से दर्शाता है, और गोल तथा diagonal कैरेक्टर्स को भी अच्छी तरह व्यक्त करता है
- 3D scene rendering में outer outlines तो sharp रहती हैं, लेकिन surfaces के बीच की boundaries धुंधली पड़ने की समस्या सामने आती है
contrast enhancement
- sampling vector के हर तत्व को exponent से adjust किया जाता है, ताकि dark values और dark हों, जबकि bright values बनी रहें
- vector को normalize करने के बाद exponent लागू किया जाता है, फिर उसे वापस मूल range में restore किया जाता है
- इस प्रक्रिया से boundaries का visual separation बेहतर होता है, और कैरेक्टर चयन अधिक स्पष्ट हो जाता है
- एकसमान brightness वाले क्षेत्रों में परिवर्तन बहुत कम होता है, इसलिए smooth gradient बना रहता है
- लेकिन कुछ boundaries पर staircasing प्रभाव दिखाई देता है
directional contrast enhancement
- हर cell के बाहर भी external sampling circles रखे जाते हैं ताकि आसपास की brightness information इकट्ठी की जा सके
- external sampling vector के bright values, internal vector के संबंधित तत्वों को dark की ओर adjust करते हैं, जिससे boundary direction में contrast बढ़ता है
- external sampling को ऊपर-मध्य-नीचे के प्रभाव तक फैलाने पर smooth और sharp boundary representation संभव होती है
- global contrast enhancement के साथ मिलाकर, 3D scenes में स्पष्ट boundaries और बेहतर readability वाली ASCII rendering हासिल की जा सकती है
performance optimization
- कैरेक्टर चुनते समय nearest-neighbor search को सीधे बार-बार दोहराना धीमा पड़ता है, इसलिए multi-dimensional space में तेज़ खोज के लिए k-d tree का उपयोग किया जाता है
- caching के जरिए एक जैसे sampling vectors के परिणाम दोबारा इस्तेमाल किए जाते हैं
- हर vector को 5-bit इकाइयों में quantize करके memory-efficient cache key बनाई जाती है
- range को 8 पर सेट कर quality और memory usage के बीच संतुलन रखा जाता है
- cached lookup बहुत तेज़ होता है, और हज़ारों कैरेक्टर्स को भी real time में process किया जा सकता है
- sampling vector की गणना GPU पर स्थानांतरित कर दी जाती है, जिससे internal/external sampling और contrast enhancement operations shader pipeline में process किए जाते हैं
- CPU की तुलना में कई गुना बेहतर performance
निष्कर्ष
- कैरेक्टर shape को vector के रूप में मापकर उपयोग करने वाला approach ASCII rendering की resolution और sharpness को काफी बढ़ा देता है
- यह तरीका word embedding जैसी अवधारणा से मिलता-जुलता है, और अन्य visual problems में भी लागू हो सकता है
- शुरुआती implementation धीमा था, लेकिन GPU acceleration, caching, और k-d tree search के जरिए mobile पर भी smooth FPS हासिल हुआ
- color-आधारित ASCII representation पर चर्चा नहीं की गई, लेकिन आगे और तरह के shape-contrast संयोजनों पर प्रयोग की संभावना बताई गई
- ASCII rendering केवल एक साधारण visual effect नहीं, बल्कि shape recognition और vector representation की विस्तार-क्षमता दिखाने वाला उदाहरण है
1 टिप्पणियां
Hacker News की टिप्पणियाँ
अगर vectors को normalize करने के बाद Euclidean distance निकाली जाए, तो सिर्फ़ matrix multiply (matmul) से भी वही नतीजा मिल सकता है
क्योंकि normalized vectors में Euclidean distance, cosine distance का linear transform होती है
अगर असली distance value नहीं बल्कि सिर्फ़ ranking मायने रखती है, तो sqrt ऑपरेशन छोड़ा जा सकता है और वही परिणाम थोड़ा तेज़ी से मिल जाता है
मुझे इस तरह के लेख सच में बहुत पसंद हैं। ऊपर से देखने पर सरल लगते हैं, लेकिन इन्हें शानदार बनाने के लिए गहराई से पड़ताल करनी पड़ती है
Lucas Pope ने Return of The Obra Dinn के dithering system को विकसित करते समय जो लिखा था, वह भी पढ़ने लायक है
Lucas Pope की डेवलपमेंट पोस्ट
“Saturn की image ChatGPT से generate की” यह वाक्य पढ़कर हैरानी हुई
Saturn की असली तस्वीरें तो public domain में भरी पड़ी हैं, फिर इंटरनेट को fake images से क्यों प्रदूषित किया जाए, समझ नहीं आता
हो सकता है किसी दिन wiki, websites, forums तक भी लोग खुद न लिखें
अगर “X×Y size की high-contrast Saturn image” तुरंत generate की जा सके, तो वह सच में जादू जैसा बदलाव होगा
जैसे calculator या internet ने creativity को खत्म नहीं किया, वैसे ही इंसान हमेशा सबसे कम friction वाले tools चुनेगा और सितारों की ओर बढ़ता रहेगा
हर example देखते समय यही लगा कि “अच्छा है, लेकिन इसे और बेहतर किया जा सकता है”, और फिर लेखक ने सच में वही करके दिखाया, यह देखकर प्रभावित हुआ
यह बेहद खूबसूरत लेख है, और पूरा ब्लॉग इसी तरह के गहरे स्तर का है, इसलिए subscribe करने लायक है
alexharri.com/blog
ascii-side-of-the-moon प्रोजेक्ट बनाते समय मैंने खुद ASCII renderer implement करने पर विचार किया था
आखिर में chafa इस्तेमाल किया, लेकिन कभी न कभी फिर कोशिश करूँगा
क्या इसे library के रूप में जारी करने की कोई योजना है, या फिर website code देखना ठीक रहेगा?
अभी library की कोई योजना नहीं है, लेकिन ज़रूरत हो तो website code बेझिझक ले सकते हैं
अगर मैं बनाता, तो WebGL 2 → WebGL 1 conversion से compatibility बढ़ाता, और हर font के लिए shape vector पहले से calculate करने वाला tool भी चाहिए होता
“ASCII art में shape का इस्तेमाल मैंने नहीं देखा” इस बात पर, वास्तव में shape का उपयोग करने वाला generator मौजूद है
ascii-silhouettify नाम के प्रोजेक्ट में color regions की outlines के हिसाब से सबसे बड़े character चुनने वाला algorithm इस्तेमाल होता है
Acerola ने 2024 में edge-detection आधारित ASCII rendering आज़माई थी
इसमें brightness-based pass के ऊपर directional symbols (| / - \) overlay किए जाते थे
संबंधित वीडियो देखें
उदाहरण के लिए पारंपरिक 2D art की तरह मोटी outlines, या Chiaroscuro की तरह मुलायम light-dark contrast जैसी कई दिशाओं में प्रयोग हो सकते हैं
ज़्यादातर ASCII filters glyph के shape को ध्यान में नहीं रखते
chafa हर glyph को 8×8 bitmap की तरह संभालता है, और यह approach काफ़ी प्रभावशाली लगी
chafa source और gallery देखें तो उसकी बारीकी का अंदाज़ा होता है
जानना चाहूँगा कि directional approach बड़े आकारों को बेहतर दिखा सकती है या नहीं
oldschool PC fonts देखो तो वह सच में एक अंतहीन rabbit hole है
फुर्सत में मैं Braille-आधारित color graphics पर प्रयोग कर रहा हूँ
resolution तो काफ़ी है, लेकिन color representation की precision कम है, इसलिए sampling के बाद contrast fixup चाहिए
लेखक की sampling technique को color contrast बढ़ाने में लागू करना अच्छा हो सकता है
पहले Sobel filter से contrast बढ़ाने की कोशिश की थी, लेकिन character grid के साथ alignment न मिलने के कारण वह काम नहीं कर पाया
यह सच में शानदार technical approach और गहरी analysis थी
आखिर में Cognition cube array का improved version देखने की उम्मीद थी, जो नहीं मिला, इसका थोड़ा अफ़सोस रहा
इससे YouTube पर देखे एक designer की याद आई, जिसने subpixel color contrast से बेहतर favicon बनाया था
संबंधित लेख (Web Archive)
फिर भी लेख खुद बहुत बढ़िया था, और dynamic examples सच में प्रभावशाली थे