2013-03-21 12 views
5

Zacząłem kodować program do obróbki obrazu z różnych algorytmów przetwarzania obrazu, głównie z pracy René Schulte, a podczas testów porównawczych zauważyłem, że ze wszystkich efektów, które mogłem znaleźć z różnych źródeł, kod stosowania efektu "Softlight" był najwolniejszy. Nie jestem dobra w optymalizowaniu równania, ale uważam, że filtr oparty jest na formule, która może powtarzać zmienne bez powodu.Czy ta formuła jest powtarzalna, czy optymalna?

Czy można to podsumować w czymś krótszym lub szybszym?

// Basically, b is from Image A, and t from Image B 
int csoftLight(float b, float t) 
     { 
      b /= 255; 
      t /= 255; 

      return (int)((t < 0.5) ? 255 * ((1 - 2 * t) * b * b + 2 * t * b) : 255 * ((1 - (2 * t - 1)) * b + (2 * t - 1) * (Math.Pow(b, 0.5)))); 
     } 

[Edycja - Wyniki za pomocą równania Mohammed Hossain znaleźć o oświetleniu rozproszonym w PS]

// Input: 137 and 113 

// Byte version: 
int other = ((byte)((B < 128) ? (2 * ((A >> 1) + 64)) * ((float)B/255) : (255 - (2 * (255 - ((A >> 1) + 64)) * (float)(255 - B)/255)))); 
// Returns 116  


// float version: 
int res = (int)((t < 0.5) ? 255 * ((1 - 2 * t) * b * b + 2 * t * b) : 255 * ((1 - (2 * t - 1)) * b + (2 * t - 1) * (Math.Pow(b, 0.5)))); 
// Returns 129 

[Edytuj]

Oto najszybszy algorytm na podstawie Mohammed Hossain odpowiedź:

int csoftLight(byte A, byte B) 
{ 
    return (int)((A < 128) ? (2 * ((B >> 1) + 64)) * ((float)A/255) : (255 - (2 * (255 - ((B >> 1) + 64)) * (float)(255 - A)/255)));   
} 
+0

bym nadzieję, że kompilatory zrobi eliminacja wspólnych podwyrażeń, ale kiedy o zmiennym Point angażuje się ... – nneonneo

+0

I googling nazwisko faceta, który dodał ten kod do oryginalnego źródła nic nie zwraca.Na koniec zadzwonię do kodera! –

+0

Operacje arytmetyczne na float są droższe niż na liczbach całkowitych. zmienić typy parametrów na int, wtedy mogę dostarczyć rozwiązanie –

Odpowiedz

4

Ta odpowiedź powinna ci w tym pomóc i wyjaśnić kilka rzeczy: How does photoshop blend two images together?

Jednym z równań jest algorytm łagodnego światła.

#define ChannelBlend_SoftLight(A,B) ((uint8)((B < 128)?(2*((A>>1)+64))*((float)B/255):(255-(2*(255-((A>>1)+64))*(float)(255-B)/255)))) //not very accurate 

Jest ważne uniknąć kosztownej operacji pierwiastkowa i mniej ważne wykorzystuje operatorów bit przesunięcia w miejscu podziału przez 2 (która powinna być zoptymalizowana jazdy inteligentnych kompilatorów, tak czy inaczej). Wykorzystuje również więcej operacji na liczbach całkowitych niż operacji pływających, co jest szybsze.

Oto inny wzór (dzięki uprzejmości właścicielom this który przełącza operacji zmienna, a to pozornie działa ...

#define ChannelBlend_SoftLight(A,B) (uint8)(((A < 128) ? (2 * ((B >> 1) + 64)) * ((float) A/255) : (255 - (2 * (255 - ((B >> 1) + 64)) * (float) (255 - A)/255)))); 
+0

Wow, masz dokładnie kontekst równania. Megaupvote! –

+0

Nie wiem, co robię źle, ale nie zwraca poprawnego obrazu: 'int csoftLight (bajt A, bajt B) { powrót ((bajt) ((B <128)? (2 * ((A >> 1) + 64)) * ((zmienna) B/255): (255 - (2 * (255 - ((A >> 1) + 64)) * (zmienna) (255 - B)/255))); } ' –

+1

Musisz wywołać to dla każdego kanału piksela; jeśli robisz to w RGB, musisz wywołać to trzy razy (R, G, B). Produktem końcowym są trzy wartości (R, G, B), które są trzema kanałami wyjściowego piksela. Czy obecnie to robisz? –

Powiązane problemy