2013-09-30 19 views
10

Ho il seguente pezzo di codice:Quali sono gli intervalli di coordinate nello spazio colore CIELAB?

public List<Tuple<double, double, double>> GetNormalizedPixels(Bitmap image) 
{ 
    System.Drawing.Imaging.BitmapData data = image.LockBits(
     new Rectangle(0, 0, image.Width, image.Height), 
     System.Drawing.Imaging.ImageLockMode.ReadOnly, 
     image.PixelFormat); 

    int pixelSize = Image.GetPixelFormatSize(image.PixelFormat)/8; 

    var result = new List<Tuple<double, double, double>>(); 

    unsafe 
    { 
     for (int y = 0; y < data.Height; ++y) 
     { 
      byte* row = (byte*)data.Scan0 + (y * data.Stride); 

      for (int x = 0; x < data.Width; ++x) 
      { 
       Color c = Color.FromArgb(
        row[x * pixelSize + 3], 
        row[x * pixelSize + 2], 
        row[x * pixelSize + 1], 
        row[x * pixelSize]); 

       // (*) 
       result.Add(Tuple.Create(
        1.0 * c.R/255, 
        1.0 * c.G/255, 
        1.0 * c.B/255); 
      } 
     } 
    } 

    image.UnlockBits(data); 

    return result; 
} 

Il frammento chiave (*) è questo:

result.Add(Tuple.Create(
    1.0 * c.R/255, 
    1.0 * c.G/255, 
    1.0 * c.B/255); 

che aggiunge un pixel con i suoi componenti scalati alla gamma [0, 1] essere ulteriormente utilizzati nella classificazione attività con classificatori diversi. Alcuni richiedono che gli attributi siano normalizzati in questo modo, altri non si preoccupano, quindi questa funzione.

Tuttavia, che cosa devo fare quando mi piacerebbe classificare i pixel in uno spazio colore diverso rispetto RGB, come L*a*b*? Mentre i valori di tutte le coordinate nello spazio colore RGB rientrano nell'intervallo [0,256) nello spazio colore L*a*b*a* e b* si dice che siano illimitati.

Così quando si cambia il frammento (*) a:

Lab lab = c.ToLab(); 

result.Add(Tuple.Create(
    1.0 * lab.L/100, 
    1.0 * lab.A/?, 
    1.0 * lab.B/?); 

(ToLab è un metodo di estensione, implementato utilizzando algoritmi appropriati dalla here)

cosa devo mettere i punti interrogativi?

+0

Interessante domanda. Ricorda che la risposta dipende dalla scelta rgb e dal bianco di riferimento. L'approccio della forza bruta proposto da BartoszKP dipende da questi fattori e potrebbe dover essere rieseguito a seconda della piattaforma. – SeF

risposta

21

In pratica il numero di tutti i colori possibili di RGB è limitato, pertanto lo spazio L*a*b* è limitato. E 'facile trovare le gamme di coordinate con il seguente programma semplice:

Color c; 

double maxL = double.MinValue; 
double maxA = double.MinValue; 
double maxB = double.MinValue; 
double minL = double.MaxValue; 
double minA = double.MaxValue; 
double minB = double.MaxValue; 

for (int r = 0; r < 256; ++r) 
    for (int g = 0; g < 256; ++g) 
     for (int b = 0; b < 256; ++b) 
     { 
      c = Color.FromArgb(r, g, b); 

      Lab lab = c.ToLab(); 

      maxL = Math.Max(maxL, lab.L); 
      maxA = Math.Max(maxA, lab.A); 
      maxB = Math.Max(maxB, lab.B); 
      minL = Math.Min(minL, lab.L); 
      minA = Math.Min(minA, lab.A); 
      minB = Math.Min(minB, lab.B); 
     } 

Console.WriteLine("maxL = " + maxL + ", maxA = " + maxA + ", maxB = " + maxB); 
Console.WriteLine("minL = " + minL + ", minA = " + minA + ", minB = " + minB); 

o uno simile utilizzando qualsiasi altra lingua.

Quindi, coordinate CIELAB spazio intervalli sono i seguenti:

L in [0, 100]

A [-86,185, 98.254]

B in [-107,863, 94,482 ]

e la risposta è:

Lab lab = c.ToLab(); 

result.Add(Tuple.Create(
    1.0 * lab.L/100, 
    1.0 * (lab.A + 86.185)/184.439, 
    1.0 * (lab.B + 107.863)/202.345); 
+4

Definire RGB. sRGB? Adobe RGB? –

+0

@ColeJohnson Punto molto interessante. Direi che questo funziona per qualsiasi versione concreta di RGB, ma non ne sono sicuro. Qui il contesto è definito come GDI + e in qualsiasi altra lingua come libreria grafica di questa lingua. – BartoszKP

+0

FWIW Lo spazio CIELAB include i colori 'immaginari' per design: http://en.wikipedia.org/wiki/Lab_color_space – theodox

8

Normalmente, i seguenti valori funziona perché l'uscita standard di algoritmi di conversione di colore comune:

  • L * asse (leggerezza) varia da 0 a 100

  • a * b * (attributi di colore) asse vanno da -128 a +127

Maggiori informazioni possono essere trovate here.

0

Se il codice Lab-conversione viene attuato in accordo con la definizione Lab-colori (vedi, per esempio Lab color space), poi operato f(...), che viene utilizzato per definire L, a e b modifiche entro [4/29,1 ], thefore

L = 116 * f(y) - 16 is in [0,100] 
a = 500 * (f(x)-f(y)) is in [-500*25/29, 500*25/29] 
b = 200 * (f(y)-f(z)) is in [-200*25/29, 200*25/29] 

Alcune persone (come bortizj nella sua risposta) normalizzare questi valori alla gamma, che un byte variabile può contenere. Quindi devi analizzare il codice per determinare, quale intervallo produce. Ma ancora una volta, le formule in Wiki ti daranno l'intervallo sopra. La stessa gamma ti darà il code here

+0

Grazie per la risposta. IIRC Stavo usando gli algoritmi di conversione esatti dal sito web EasyRGB a cui ti stai riferendo (RGB -> XYZ -> LAB) e il risultato è diverso - sei sicuro che i valori che fornisci siano corretti? – BartoszKP