- Görüntünün konturlarını ve şeklini koruyan ASCII render etme tekniği geliştirilerek, mevcut yöntemlerdeki bulanık kenar sorunu çözüldü
- Piksel düzeyinde basit parlaklık eşlemesi yerine, her karakterin görsel formunu (shape) sayısallaştırıp eşleştiren yüksek boyutlu vektör tabanlı bir yaklaşım kullanıldı
- Her karakter için üst-alt-sol-sağ bölgelerin yoğunluğu ölçülerek, 2 boyuttan 6 boyuta genişletilmiş shape vector üretildi ve daha hassas karakter seçimi sağlandı
- Sınır çizgilerinin netliğini artırmak için global ve yönlü kontrast artırma (contrast enhancement) algoritmaları uygulandı
- GPU hızlandırma, önbellekleme ve k-d tree araması sayesinde gerçek zamanlı ASCII render etme performansı elde edilerek yüksek kaliteli görsel efektler sağlandı
Görüntüden ASCII'ye dönüşüm
- ASCII'de 95 yazdırılabilir karakter vardır ve görüntü monospace font kullanılarak bir ızgaraya bölünür
- Her hücrenin parlaklığı hesaplanır ve karakter yoğunluğuna göre eşlenir
- Basit en yakın komşu enterpolasyonu (nearest-neighbor interpolation), sınırların tırtıklı görünmesine yol açan jaggies etkisini üretir
- Süper örnekleme (supersampling) ile hücre içinde birden fazla örnek alınıp ortalama parlaklık hesaplandığında görüntü yumuşar, ancak sınırlar yine de bulanık kalır
- Sorunun özü, karakterleri piksel gibi ele almak ve karakterlerin kendine özgü formlarını hesaba katmamaktır
Karakter formunun (Shape) kullanımı
- Her karakterin hücre içindeki görsel yoğunluk dağılımı farklıdır
- Örn:
T üstte ağır basar, L altta ağır basar
- Bunu sayısallaştırmak için hücre içine örnekleme çemberleri (circle) yerleştirilir ve her bölgedeki karakter kaplama oranı hesaplanır
- Üst ve alt iki bölgenin kaplama oranı vektör olarak ifade edilerek 2 boyutlu shape vector oluşturulur
- Her karakterin shape vector'ü önceden hesaplanır ve görüntünün örnekleme vektörüne Öklid mesafesi (Euclidean distance) açısından en yakın karakter seçilir
6 boyutlu form vektörüne genişleme
- Yalnızca üst-alt 2 boyut,
-, p, q gibi orta ya da sağ-sol merkeze dayalı karakterleri ifade etmekte yetersiz kalır
- Hücre 6 örnekleme çemberine genişletilerek üst-orta-alt ile sol-sağ farkları birlikte yakalanır
- 6 boyutlu shape vector, karakter formunu çok daha hassas yansıtır ve dairesel ve diyagonal karakterleri de iyi ifade eder
- 3D sahne render edilirken dış konturlar keskin olsa da yüzeyler arasındaki sınırların bulanıklaştığı bir sorun ortaya çıkar
Kontrast artırma (Contrast Enhancement)
- Örnekleme vektörünün her bileşeni üs (exponent) ile ayarlanarak koyu değerler daha da koyulaştırılırken parlak değerler korunur
- Vektör normalize edilir, üs uygulanır ve ardından yeniden özgün aralığına geri döndürülür
- Bu süreç sayesinde sınır çizgilerinin görsel ayrımı güçlenir ve karakter seçimi daha net hale gelir
- Parlaklığı homojen olan bölgelerde değişim neredeyse yoktur; bu da yumuşak geçişlerin korunmasını sağlar
- Ancak bazı sınırlarda basamaklanma (staircasing) etkisi görülür
Yönlü kontrast artırma (Directional Contrast Enhancement)
- Her hücrenin dışına da harici örnekleme çemberleri yerleştirilerek çevredeki parlaklık bilgisi toplanır
- Harici örnekleme vektöründeki parlak değerler, iç vektördeki karşılık gelen bileşenleri koyulaştırarak sınır yönünde kontrastı artırır
- Harici örnekleme üst-orta-alt arasındaki etkiyi genişletecek şekilde artırıldığında, yumuşak ve net sınır gösterimi mümkün olur
- Global kontrast artırma ile birleştirildiğinde, 3D sahnelerde belirgin sınır çizgilerine ve yüksek okunabilirliğe sahip ASCII render etme elde edilir
Performans optimizasyonu
- Karakter seçerken en yakın aramayı basitçe tekrar etmek yavaş olduğundan, çok boyutlu uzayda hızlı arama için k-d tree kullanılır
- Önbellekleme ile aynı örnekleme vektörünün sonucu yeniden kullanılır
- Her vektör 5 bitlik birimlerle kuantize edilerek bellek açısından verimli önbellek anahtarı oluşturulur
- Aralığın 8 olarak ayarlanması, kalite ile bellek kullanımı arasında denge sağlar
- Önbelleğe alınmış aramalar çok hızlıdır ve binlerce karakter bile gerçek zamanlı işlenebilir
- Örnekleme vektörü hesaplaması GPU'ya taşınarak, iç ve dış örnekleme ile kontrast artırma işlemleri shader pipeline üzerinde yürütülür
- CPU'ya kıyasla kat kat performans artışı sağlanır
Sonuç
- Karakter formunu vektör olarak sayısallaştırıp kullanan yaklaşım, ASCII render etmenin çözünürlüğünü ve netliğini büyük ölçüde artırır
- Bu yöntem, word embedding benzeri bir kavrama dayanır ve başka görsel problemlere de uygulanma potansiyeli taşır
- İlk uygulama yavaş olsa da, GPU hızlandırma, önbellekleme ve k-d tree araması ile mobilde bile akıcı FPS elde edildi
- Renk tabanlı ASCII gösterimi ele alınmadı; gelecekte daha çeşitli form ve kontrast kombinasyonlarının denenebileceği belirtiliyor
- ASCII render etme, basit bir görsel efektin ötesinde, form tanıma ve vektör gösterimlerinin genişleyebilirliğini gösteren bir örnek
1 yorum
Hacker News yorumları
Vektörleri normalize ettikten sonra Öklid mesafesi hesaplanıyorsa, basit bir matris çarpımı (
matmul) ile aynı sonuç elde edilebilirÇünkü normalize edilmiş vektörlerde Öklid mesafesi, kosinüs mesafesinin doğrusal dönüşümüdür
Gerçek mesafe değeri değil de yalnızca sıralama (ranking) önemliyse,
sqrtişlemi atlanabilir ve aynı sonuç biraz daha hızlı hesaplanırBu tür yazıları gerçekten seviyorum. Dışarıdan basit görünüyor ama iyi yapmak için derinlemesine inceleme gerekiyor
Lucas Pope'un Return of The Obra Dinn için dithering sistemi geliştirirken yazdığı metni de tavsiye ederim
Lucas Pope'un geliştirme yazısı
“Satürn görselini ChatGPT ile oluşturdum” cümlesini görünce şaşırdım
Gerçek Satürn fotoğrafları zaten public domain olarak her yerde bulunabiliyorken, neden özellikle sahte bir görsel üretip interneti kirletelim ki?
Bir gün wiki'leri, web sitelerini, hatta forumları bile doğrudan yazmayı bırakabiliriz
Eğer “X×Y boyutunda, yüksek kontrastlı bir Satürn görseli”ni anında üretebiliyorsak, bu büyü gibi bir değişim olur
Nasıl hesap makinesi ya da internet yaratıcılığı öldürmediyse, insanlar da her zaman sürtünmesi en az olan aracı seçip yıldızlara doğru ilerlemeyi sürdürecek
Örneklere her baktığımda “güzel ama daha da iyileştirilebilir” diye düşünüyordum; yazarın bunu gerçekten çözdüğünü görmek etkileyiciydi
Gerçekten çok güzel bir yazı; blogun geneli de bu kadar derinlikli olduğu için takip etmeye değer
alexharri.com/blog
ascii-side-of-the-moonprojesini yaparken ASCII renderer'ı kendim yazmayı düşünüp düşünmemek arasında kalmıştımSonunda chafa'yı kullandım ama bir gün yeniden denemeyi düşünüyorum
Bunu bir kütüphane olarak yayımlamayı planlıyor musun, yoksa web sitesi koduna bakmamızda sakınca yok mu merak ediyorum
Şu an için kütüphane planı yok ama ihtiyaç varsa web sitesi kodunu gönül rahatlığıyla alabilirsiniz
Eğer bunu yaparsam, uyumluluğu artırmak için WebGL 2 → WebGL 1 dönüşümü ve yazı tipine göre shape vector'ları önceden hesaplayan bir araç da gerekirdi diye düşünüyorum
“ASCII sanatta
shapekullanan bir örnek görmedim” sözüne karşılık, aslında gerçekten shape kullanan bir üretici varascii-silhouettify adlı projede, renk bölgelerinin dış hatlarına en iyi uyan en büyük karakteri seçen bir algoritma kullanılıyor
Acerola, 2024'te kenar algılama tabanlı ASCII rendering denedi
Bu yöntemde parlaklığa dayalı geçişin üstüne yönlü semboller (
| / - \) bindiriliyorduİlgili video
Örneğin geleneksel 2D sanattaki gibi kalın dış çizgiler kullanmak ya da Chiaroscuro benzeri yumuşak ışık-gölge karşıtlıkları denemek mümkün
Çoğu ASCII filtresi glyph shape'ini hesaba katmıyor
chafa her glifi 8×8 bitmap olarak ele alıyor ve bu yaklaşım bana çok etkileyici geldi
chafa kaynağı ve galeri bu işin ne kadar incelikli olduğunu gösteriyor
Yönlülük merkezli yaklaşımın daha büyük biçimleri daha iyi ifade edip edemeyeceğini merak ediyorum
oldschool PC fonts gerçekten sonsuz bir tavşan deliği gibi
Boş zamanlarımda Braille tabanlı renkli grafikler üzerine denemeler yapıyorum
Çözünürlük yeterli ama renk ifadesinin hassasiyeti yetersiz olduğu için örneklemeden sonra kontrast düzeltmesi (contrast fixup) gerekiyor
Yazarın örnekleme tekniğini renk kontrastını güçlendirmeye uygulamak iyi olabilir
Daha önce Sobel filtresiyle kontrastı artırmayı denedim ama karakter ızgarasıyla hizalanmadığı için işe yaramadı
Gerçekten mükemmel bir teknik yaklaşım ve derinlikli bir analizdi
Sonunda Cognition cube array'in geliştirilmiş bir sürümünü görebilir miyiz diye umuyordum ama çıkmadı
Bana, YouTube'da subpixel renk kontrastı kullanarak daha iyi favicon yapan bir tasarımcıyı hatırlattı
İlgili yazı (Web Archive)
Yine de yazının kendisi çok iyiydi ve dinamik örnekler gerçekten etkileyiciydi