Doğrusal ve doğrusal olmayan bir RGB alanında renklerle çalışırken pratik farklar nelerdir?


90

Doğrusal bir RGB uzayının temel özelliği nedir ve doğrusal olmayan alanın temel özelliği nedir? Bu 8 (veya daha fazla) bitteki her kanalın içindeki değerlerden bahsederken, ne değişir?

OpenGL'de renkler 3 + 1 değerlerdir ve bununla yani RGB + alfa, her kanala 8 bit ayrılmıştır ve bu açıkça aldığım kısımdır.

Ancak konu gama düzeltmesine gelince, doğrusal olmayan bir RGB alanında çalışmanın etkisinin ne olduğunu anlamıyorum.

Bir grafik yazılımında fotoğraf düzenleme için bir eğriyi nasıl kullanacağımı bildiğim için, açıklamam, doğrusal bir RGB alanında değerleri olduğu gibi, hiçbir işlem yapmadan ve matematik işlevi eklenmeden, her biri doğrusal olmadığında alacağınızdır. kanal genellikle klasik bir güç işlevi davranışını izleyerek gelişir.

Bu açıklamayı gerçek olarak alsam bile, gerçek doğrusal uzayın ne olduğunu hala anlamıyorum, çünkü hesaplamadan sonra tüm doğrusal olmayan RGB uzayları doğrusal hale gelir ve en önemlisi, bir Doğrusal renk alanı insan gözü için daha uygundur çünkü sonunda tüm RGB alanları anladığım kadarıyla doğrusaldır.


Pratik bir not, SVG da renk alanı olarak ya doğrusal ya da standart RGB belirtebilir ve bu :-) önemli görünüyor etkileyen aslında dışında, nedir hiçbir fikrim yok
Michael Mullany

@MichaelMullany bu doğrusal şey, kullanıcı için gerçek bir ayırt edici nitelikten çok bir ipucu gibi görünüyor.
Ken

Bana yardımcı olan bir şey: Sanırım bir matematik öğretmeninin bana "lineer duyduğun zaman düşün" dedi. Bunun yardımcı olup olmadığından emin değilim, ama benim için bir "Ah evet!" an
Joe Plante

Yanıtlar:


235

RGB renklerle çalıştığınızı varsayalım: her renk üç yoğunluk veya parlaklık ile temsil edilir . "Doğrusal RGB" ve "sRGB" arasında seçim yapmalısınız. Şimdilik, üç farklı yoğunluğu görmezden gelerek işleri basitleştireceğiz ve tek bir yoğunluğa sahip olduğunuzu varsayacağız: yani, yalnızca grinin tonlarıyla uğraşıyorsunuz.

Doğrusal bir renk uzayında, depoladığınız sayılarla temsil ettikleri yoğunluklar arasındaki ilişki doğrusaldır. Pratikte bu, sayıyı ikiye katlarsanız yoğunluğu (grinin açıklığını) ikiye katlarsınız demektir. İki yoğunluğu birbirine eklemek istiyorsanız (iki ışık kaynağının katkılarına göre bir yoğunluğu hesapladığınız için veya opak bir nesnenin üzerine saydam bir nesne eklediğiniz için), bunu yalnızca birlikte iki numara. Herhangi bir tür 2B harmanlama veya 3B gölgeleme ya da neredeyse her türlü görüntü işleme yapıyorsanız, yoğunluklarınızı doğrusal bir renk alanında istersiniz., böylece yoğunluklar üzerinde aynı etkiye sahip olmak için sayıları toplayabilir, çıkarabilir, çarpabilir ve bölebilirsiniz. Çoğu renk işleme ve işleme algoritması, her şeye fazladan ağırlık eklemediğiniz sürece yalnızca doğrusal RGB ile doğru sonuçlar verir.

Kulağa çok kolay geliyor ama bir sorun var. İnsan gözünün ışığa duyarlılığı, düşük yoğunluklarda yüksek yoğunluklara göre daha incedir. Yani, ayırt edebileceğiniz tüm yoğunlukların bir listesini yaparsanız, hafif olanlardan daha karanlık olanlar vardır. Başka bir deyişle, grinin koyu tonlarını, açık grinin tonlarıyla yapabileceğinizden daha iyi ayırt edebilirsiniz. Özellikle, yoğunluğunuzu temsil etmek için 8 bit kullanıyorsanız ve bunu doğrusal bir renk alanında yaparsanız, çok fazla açık gölgeyle ve yeterli koyu gölgeyle karşılaşmazsınız. Karanlık alanlarınızda şeritlenme olurken, açık alanlarınızda, kullanıcının ayırt edemeyeceği beyaza yakın farklı tonlardaki bitleri boşa harcarsınız.

Bu sorunu önlemek ve bu 8 biti en iyi şekilde kullanmak için sRGB kullanma eğilimindeyiz . SRGB standardı, renklerinizi doğrusal olmayan hale getirmek için kullanabileceğiniz bir eğri söyler. Eğri, altta daha sığdır, böylece daha koyu griler ve üstte daha dik olabilir, böylece daha az açık gri elde edersiniz. Sayıyı ikiye katlarsanız, yoğunluğu iki katından daha fazla hissedersiniz. Bu, sRGB renklerini birlikte eklerseniz olması gerekenden daha açık bir sonuç elde edeceğiniz anlamına gelir. Bugünlerde çoğu monitör giriş renklerini sRGB olarak yorumluyor. Dolayısıyla, ekrana bir renk koyduğunuzda veya bunu kanal başına 8 bitlik bir dokuda saklarken, sRGB olarak saklayın , böylece bu 8 bitten en iyi şekilde yararlanın.

Şimdi bir sorunumuz olduğunu fark edeceksiniz: renklerimizin doğrusal uzayda işlenmesini, ancak sRGB'de saklanmasını istiyoruz. Bu, okumada sRGB'den lineer dönüşüme ve yazma sırasında lineerden sRGB'ye dönüşüm yapacağınız anlamına gelir. Doğrusal 8 bit yoğunlukların yeterli koyuluğa sahip olmadığını daha önce söylediğimiz gibi, bu sorunlara neden olur, bu yüzden bir pratik kural daha var: eğer kaçınabiliyorsanız 8 bit doğrusal renkler kullanmayın . 8 bit renklerin her zaman sRGB olduğu kuralını takip etmek geleneksel hale geliyor, bu nedenle sRGB'den lineer dönüşümünüzü, yoğunluğunuzu 8'den 16 bit'e veya tam sayıdan kayan noktaya genişletirken aynı anda yaparsınız; benzer şekilde, kayan nokta işlemenizi bitirdiğinizde, sRGB'ye dönüştürürken aynı anda 8 bite daraltırsınız. Bu kurallara uyarsanız,

Bir sRGB görüntüsü okurken ve doğrusal yoğunluklar istiyorsanız, bu formülü her yoğunluğa uygulayın:

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

Diğer taraftan, bir görüntüyü sRGB olarak yazmak istediğinizde, bu formülü her doğrusal yoğunluğa uygulayın:

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 )

Her iki durumda da, kayan noktanın değeri 0 ile 1 arasındadır, bu nedenle 8 bitlik tam sayıları okuyorsanız önce 255'e bölmek istersiniz ve 8 bitlik tam sayılar yazıyorsanız 255 ile çarpmak istersiniz. son olarak, genellikle yaptığınız gibi. SRGB ile çalışmak için bilmeniz gereken tek şey bu.

Şimdiye kadar sadece tek bir yoğunlukla uğraştım, ancak renklerle yapılacak daha akıllıca şeyler var. İnsan gözü, farklı parlaklıkları farklı renk tonlarından daha iyi ayırt edebilir (daha teknik olarak, krominanstan daha iyi parlaklık çözünürlüğüne sahiptir), böylece parlaklığı renk tonundan ayrı olarak depolayarak 24 bitinizi daha da iyi kullanabilirsiniz. YUV, YCrCb, vb. Temsillerin yapmaya çalıştığı şey budur. Y kanalı, rengin genel açıklığıdır ve diğer iki kanaldan daha fazla bit kullanır (veya daha fazla uzamsal çözünürlüğe sahiptir). Bu şekilde, RGB yoğunluklarında yaptığınız gibi (her zaman) bir eğri uygulamanıza gerek kalmaz. YUV doğrusal bir renk uzayıdır, bu nedenle Y kanalındaki sayıyı ikiye katlarsanız, rengin açıklığını ikiye katlarsınız, ancak RGB renklerinde olduğu gibi YUV renklerini ekleyemez veya çoğaltamazsınız.

Sanırım bu, sorunuzu yanıtlıyor, bu yüzden kısa bir tarihi notla bitireceğim. SRGB'den önce, eski CRT'ler içlerinde doğrusal olmayan bir yapıya sahipti. Bir piksel için voltajı ikiye katlarsanız, yoğunluğu iki katından daha fazla yaparsınız. Her monitör için daha ne kadar farklıydı ve bu parametre gama olarak adlandırıldı . Bu davranış yararlıydı, çünkü ışıklardan daha fazla koyuluk elde edebileceğiniz anlamına geliyordu, ancak aynı zamanda, önce kalibre etmedikçe, kullanıcının CRT'sinde renklerinizin ne kadar parlak olacağını söyleyemeyeceğiniz anlamına geliyordu. Gamma düzeltmesiBaşladığınız renkleri (muhtemelen doğrusal) dönüştürmek ve bunları kullanıcının CRT'sinin gamasına dönüştürmek anlamına gelir. OpenGL bu çağdan geliyor, bu yüzden sRGB davranışı bazen biraz kafa karıştırıcı oluyor. Ancak GPU satıcıları artık yukarıda anlattığım konvansiyonla çalışma eğilimindedir: bir doku veya çerçeve tamponunda 8 bitlik bir yoğunluğu depoladığınızda, bu sRGB'dir ve renkleri işlerken doğrusaldır. Örneğin, bir OpenGL ES 3.0, her çerçeve arabelleği ve doku, okurken ve yazarken otomatik dönüştürmeyi etkinleştirmek için açabileceğiniz bir "sRGB bayrağı" içerir. Açıkça sRGB dönüşümü veya gama düzeltmesi yapmanız gerekmez.


6
harika cevap, teşekkür ederim, anlatılan şeyleri görmek her zaman harika, sadece bir kitap veya bu konu için yeterince iyi olacağını düşündüğünüz bir kaynak, renk boşlukları ve sRGB dönüşümü yapmak için kullanılan formüller nelerdir? <-> doğrusal veya bu davranışa yaklaşan fonksiyon nedir.
Ken

Korkarım iyi bir kitap veya kaynak bilmiyorum. Vikipedi sayfası kapsamı genişledi ve tüm beyaz nokta ve ne kadar küçük gamı (çoğu kişi bunu bilmek gerekmez gibi ben bahsetmedim olan) yaklaşık şeyleri içerir, ama bu onu biraz aşılmaz kılan .
Dan Hulme



1

Ben bir "insan renk algılama uzmanı" değilim, ancak YUV-> RGB dönüşümünde benzer bir şeyle karşılaştım. R / G / B kanalları için farklı ağırlıklar vardır, bu nedenle kaynak rengini x ile değiştirirseniz, RGB değerleri farklı miktarlarda değişir.

Dediğim gibi, ben bir uzman değilim, her neyse, sanırım, biraz doğru renk dönüşümü yapmak istiyorsanız, bunu YUV alanında yapmalı, sonra RGB'ye dönüştürmelisiniz (veya RGB'de matematiksel olarak eşdeğer işlemi yapmalısınız, dikkatli olun veri kaybı). Ayrıca, YUV'nin renklerin en iyi yerel temsili olduğundan emin değilim, ancak video kameralar bu formatı sağlıyor, sorunla karşılaştığım yer burası.

Gizli numaralar içeren sihirli YUV-> RGB formülü: http://www.fourcc.org/fccyvrgb.php


1
RGB <-> YUV dönüşümleri ve geri dönüşleri konusunda dikkatli olun. Bunun her durumda olduğundan emin değilim, ancak YUV renk alanı bazen 24 bit RGB'de 0-255 yerine 16-235 aralığına dönüşüyor. Böylece, her renk alanı dönüşümü yaptığınızda veri kaybedebilirsiniz. Çoğu insan, yardım edebilirseniz aynı renk uzayında kalmayı söyleme eğilimindedir.
Joe Plante
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.