Qual è l'algoritmo dietro lo strato di regolazione "Bianco e nero" di Photoshop?


11

Qualcuno può spiegare l'algoritmo dietro il livello di regolazione "Bianco e nero" in Photoshop?

Screenshot di Photoshop

Devo riprodurlo utilizzando C ++ per un'applicazione che enfatizza i pixel non rossi / magenta (ish) di un'immagine (con una tolleranza configurabile simile a percentuale) e questa risorsa ha mostrato il comportamento che mi aspetto.


Non riesco ancora a riprodurlo, ma ho trovato un indizio:

Ogni pixel è definito da un massimo di due controlli, un additivo (RGB) e un sottrattivo (CMY).


Ti sei mai avvicinato di più a capire l'algoritmo? Sto anche provando a capirlo.
pizzafilms,

No, non l'ho fatto: /
Blamoo

Risposte:


4

Ho replicato perfettamente l'algoritmo in MATLAB (basato sulla risposta di @ Ivan Kuckir ):

function [ mO ] = ApplyBlackWhiteFilter( mI, vCoeffValues )

FALSE   = 0;
TRUE    = 1;

OFF = 0;
ON  = 1;

numRows = size(mI, 1);
numCols = size(mI, 2);
dataClass = class(mI);

numCoeff    = size(vCoeffValues, 1);
hueRadius   = 1 / numCoeff;
vHueVal     = [0:(numCoeff - 1)] * hueRadius;

mHsl = ConvertRgbToHsl(mI);
mO = zeros(numRows, numCols, dataClass);

vCoeffValues = numCoeff * vCoeffValues;

for jj = 1:numCols
    for ii = 1:numRows
        hueVal = mHsl(ii, jj, 1);
        lumCoeff = 0;

        % For kk = 1 we're dealing with circular distance
        diffVal     = min(abs(vHueVal(1) - hueVal), abs(1 - hueVal));
        lumCoeff    = lumCoeff + (vCoeffValues(1) * max(0, hueRadius - diffVal));
        for kk = 2:numCoeff
            lumCoeff = lumCoeff + (vCoeffValues(kk) * max(0, hueRadius - abs(vHueVal(kk) - hueVal)));
        end

        mO(ii, jj) = mHsl(ii, jj, 3) * (1 + lumCoeff);
    end
end


end

Fai attenzione che la conversione da vPhotoshopValuesin vCoeffValuesdovrebbe essere eseguita come vCoeffValues = (vPhotoshopValues - 50) ./ 50.
Poiché i valori di Photoshop sono in [-200, 300] e devono essere mappati linearmente in [-5, 5] con 50 -> 0.

Ecco un confronto con Photoshop:

inserisci qui la descrizione dell'immagine

L'errore massimo è inferiore a 1 nell'intervallo [0, 255].

Il codice completo è disponibile sul mio repository GitHub di elaborazione del segnale StackExchange Q688 .


8

Ogni immagine (a colori) è composta da componenti RGB. quando aggiungi (o riduci) un valore costante a tutti i pixel solo nei componenti ROSSI vedrai l'effetto equivalente a spostare la scheda ROSSO verso destra, e allo stesso modo ridurre il componente ROSSO di una costante avrà l'effetto inverso.

Come saggio, puoi incrementare / decrementare ogni componente di un valore fisso come descritto. Se aumenti / riduci TUTTI i componenti RGB di uno stesso valore, ciò equivarrà a una modifica della luminosità (in pratica stai aggiungendo / rimuovendo il colore BIANCO).

Il ciano, il blu, il magenta - corrispondono a tale trasformazione nello spazio colore CMYK. (Ma immagino che il blu in questo spazio colore corrisponda al mix di ciano e giallo. Quindi è un po 'complicato. La trasformazione è essenzialmente la stessa per tutti.

L'ultimo elemento Tinta: {Tonalità e saturazione} corrisponde alle stesse operazioni, ma qui le immagini vengono prima trasformate nel modello HSV e quindi HUE e saturazione vengono aggiunte / sottratte in modo indipendente.

Non conosco le esatte relazioni dei marcatori del quadrante con i numeri corrispondenti, ma che puoi capire provando i valori pratici.


1
Ci sono RGB e CMY, quindi tutto ciò che devi fare è trasformarti in uno dei due spazi colore e puoi regolare quanto vuoi. Basta non dimenticare di aggiornare l'altra terzina una volta terminata la regolazione.
Jonas,

Credo che questa risposta sia errata e incompleta. 1. Nell'implementazione di PS, lo scorrimento del cursore "blu" non influisce sulla luminosità dei pixel ciano e lo scorrimento del cursore "ciano" non influisce sulla luminosità dei pixel blu. Questo approccio descritto in questa risposta non funzionerebbe così. 2. non descrivi come, dopo aver manipolato i componenti RGBCMY, vengano convertiti in scala di grigi (sebbene sia probabilmente dotProduct(color, vec3(0.2989, 0.5870, 0.1140)un'operazione). 3. Il blu non "corrisponde a un mix di ciano e giallo" in qualsiasi spazio colore.
Stefan Monov,

4. Non menzionate che l'operazione di tinta viene eseguita dopo la conversione in scala di grigi e non prima.
Stefan Monov,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.