2012-02-14 13 views
6

Dla tych, którzy jeszcze nie znają funkcji "Kolor na alfa" Gimpa, oto strona z dokumentacji Gimpa: Color to Alpha. Wykonuje naprawdę dobrą robotę i zastanawiam się, jak dokładnie Gimp robi to w zakresie manipulacji kolorami, w zależności od przestrzeni kolorów, w której mogą znajdować się kolory. Dziękuję za wszelkie wskazówki.Jaki algorytm znajduje się za funkcją "Kolor na alfa" Gimpa?

EDIT 1: generowania informacji przezroczystości dla piksela na podstawie jego podobieństwa do klucza koloru (jednego wybranego w „Color Alpha do” okna), podobnie jak niektóre folk zasugerował przed usunięciem jego odpowiedź z jakiegoś powodu, Brzmiałoby to jak dobry wgląd, ale przypuszczam, że jest to bardziej zawiłe. Załóżmy, że szacujemy podobieństwo kolorów w zakresie jednostek od 0,0 do 1,0, a mamy piksel, którego kolor jest na przykład 0,4 podobny do, powiedzmy, koloru białego (tak jakbyś wybrał kolor biały w "Kolor do "Okno dialogowe" Alpha), a zatem piksel otrzymuje wartość alfa 0,6, a następnie w jaki sposób zmieniłbyś rzeczywisty kolor piksela, aby zrekompensować utratę jasności/jaskrawości/nasycenia, gdy wynikowy piksel jest wyświetlany na białym tle z wartością alfa 0,6?

EDIT 2: Właściwie aktualizacja: Sub-pytanie związane z pierwszej edycji zostało odebrane w How to change the alpha of a pixel without changing the resulting color? ale to chyba nie cała prawda, ponieważ to, co dzieje się w źródle GIMP jest za „kolor do Alpha” funkcja nie jest tak prosta i wydaje się być oparta na określonym algorytmie, a nie formule.

+0

Powiązane pytanie: http://stackoverflow.com/questions/9282714/how-to-change-the-alpha-awpixel-z-niezmienia-ne-takowanie-koloru –

+0

@MarkRansom Wiem, że pytanie, które opublikowałeś, jest powiązane z tym, który zadał mi to pytanie! :) I nawet jeśli twoja formuła może osiągnąć efekt tej cechy Gima, to tajemnica wciąż istnieje, ponieważ złożoność tego, co widziałem w źródłach Gima, jest wyższa niż w twojej formule. –

+0

@MarkRansom Continuing: Ale twoje podejście wydaje się być bardziej elastyczne niż Gimp, ponieważ dzięki rozwiązaniu dla przepisanego układu równań, można "wyciąć" obraz z tła jednego koloru i położyć go na tle innego koloru , a obraz nadal wyglądałby tak samo. Więc myślę, że nie ma już większego sensu w tym pytaniu, więc zamierzam zarejestrować to pytanie do skasowania, jeśli nikt nie ma nic przeciwko. –

Odpowiedz

1

Musisz wymyślić mechanizm porównywania podobieństwa kolorów. Istnieje wiele różnych przestrzeni kolorów, w których możesz to zrobić. RGB często nie jest najlepszy do tego typu rzeczy. Ale możesz użyć HSV, YCbCr lub jakiejś innej przestrzeni luma/chroma. Często odległość w jednym z tych pól daje lepszą odpowiedź niż odległość euklidesowa w RGB. Gdy masz już dystans, możesz podzielić to przez maksymalną odległość, aby uzyskać procent. Ten odsetek byłby odwrotnością alfa, którego chcesz użyć, jako jedną z możliwości.

Jeśli chcesz wiedzieć, jak robi to GIMP, możesz spojrzeć na źródło. Na przykład here's one recent code change do tej wtyczki.

+0

Dzięki, ale już widziałem źródło i nie było wystarczająco proste i było słabo udokumentowane. To, co piszesz w pierwszej części odpowiedzi, jest już omówione w wydaniu na moje pytanie, co w prostszych słowach oznacza, że ​​nie jest trudno oszacować podobieństwo między dwoma kolorami, raczej co zrobić z kolorem piksela, którego alfa zmienił się z 1,0 na inną wartość, co w rzeczywistości również nie jest skomplikowane: http://stackoverflow.com/questions/9282714/how-to-change-the-alpha-awpixel-without-changing -wynikający kolor –

+0

Wydaje się, że wiesz o GIMP. Czy możesz być wystarczająco miły, aby odpowiedzieć na moje pytanie [tutaj] (http://stackoverflow.com/questions/29147244/gimp-colorization-technique)? –

+0

Wygląda na to, że pytanie zostało usunięte, więc nie wiem, jakie było rzeczywiste pytanie. Przepraszam! – user1118321

8

Spojrzałem na kod źródłowy, a jego mięso jest funkcją colortoalpha. Parametry * a1 do * a4 to odpowiednio: wejście/wyjście czerwony, zielony, niebieski i alfa, a c1 do c3 to kolor, który tworzy alfa.

Podczas łączenia dwóch kolorach C1 i C2 z określonym alfa a (0 ≤ a ≤ 1), wynik jest

y = a * c1 + (1-a) * c2 

Tutaj robimy operacji odwrotnej: Znamy koniec wynik y i kolor tła c2, i chcesz dowiedzieć się c1 i a. Ponieważ jest to nieokreślone równanie, istnieje nieskończona ilość rozwiązań. Jednak zakresy 0 ≤ c1 ≤ 255 i 0 ≤ a ≤ 1 dodają granice rozwiązania.

Sposób działania wtyczki Gimp polega na tym, że dla każdego piksela minimalizuje on wartość alfa (tj. Maksymalizuje przezroczystość). Odwrotnie oznacza to, że dla każdego wynikowego piksela, który nie jest całkowicie przezroczysty (tj. Nie był dokładnie kolorem tła), jeden ze składników RGB ma wartość 0 lub 255.

Powoduje utworzenie obrazu, który po nałożeniu na wierzch określony kolor zapewni oryginalny obraz (przy braku błędów zaokrąglania) i ma maksymalną przezroczystość dla każdego piksela.

Warto zauważyć, że cały proces odbywa się w przestrzeni kolorów RGB, ale może być również wykonywany w innych, o ile operacja łączenia odbywa się w tej samej przestrzeni kolorów.

1

Więc zajrzałem do GIMP source code ... ew! Zrobiłem to ogólne i czytelne. Nadal jednak dość szybko. Aby uzyskać wyjaśnienie matematyczne, patrz Sampo's answer. Poniżej realizacja C# (łatwo zamienić na ° C/C++):

static class PixelShaders { 

    /// <summary> 
    /// Generic color space color to alpha. 
    /// </summary> 
    /// <param name="pA">Pixel alpha.</param> 
    /// <param name="p1">Pixel 1st channel.</param> 
    /// <param name="p2">Pixel 2nd channel.</param> 
    /// <param name="p3">Pixel 3rd channel.</param> 
    /// <param name="r1">Reference 1st channel.</param> 
    /// <param name="r2">Reference 2nd channel.</param> 
    /// <param name="r3">Reference 3rd channel.</param> 
    /// <param name="mA">Maximum alpha value.</param> 
    /// <param name="mX">Maximum channel value.</param> 
    static void GColorToAlpha(ref double pA, ref double p1, ref double p2, ref double p3, double r1, double r2, double r3, double mA = 1.0, double mX = 1.0) { 
     double aA, a1, a2, a3; 
     // a1 calculation: minimal alpha giving r1 from p1 
     if (p1 > r1) a1 = mA * (p1 - r1)/(mX - r1); 
     else if (p1 < r1) a1 = mA * (r1 - p1)/r1; 
     else a1 = 0.0; 
     // a2 calculation: minimal alpha giving r2 from p2 
     if (p2 > r2) a2 = mA * (p2 - r2)/(mX - r2); 
     else if (p2 < r2) a2 = mA * (r2 - p2)/r2; 
     else a2 = 0.0; 
     // a3 calculation: minimal alpha giving r3 from p3 
     if (p3 > r3) a3 = mA * (p3 - r3)/(mX - r3); 
     else if (p3 < r3) a3 = mA * (r3 - p3)/r3; 
     else a3 = 0.0; 
     // aA calculation: max(a1, a2, a3) 
     aA = a1; 
     if (a2 > aA) aA = a2; 
     if (a3 > aA) aA = a3; 
     // apply aA to pixel: 
     if (aA >= mA/mX) { 
      pA = aA * pA/mA; 
      p1 = mA * (p1 - r1)/aA + r1; 
      p2 = mA * (p2 - r2)/aA + r2; 
      p3 = mA * (p3 - r3)/aA + r3; 
     } else { 
      pA = 0; 
      p1 = 0; 
      p2 = 0; 
      p3 = 0; 
     } 
    } 

} 

realizacja GIMP (here) wykorzystuje RGB koloru, wykorzystuje wartość alpha float się od 0 do 1, i R, G, B, float z 0 do 255.

Implementacja RGB nie udaje się spektakularnie, gdy obraz ma artefakty JPEG, ponieważ oznaczają one nieznaczne, dostrzegalne odchylenia kolorów, ale dość znaczące bezwzględne odchylenia R, G, B. Używanie przestrzeni kolorów LAB powinno załatwić sprawę.

Jeśli chcesz usunąć tylko całe tło z obrazu, algorytm koloru do alfa nie jest opcją optymalną. Mam dobre wyniki, gdy obliczona odległość przestrzeni kolorów dla każdego piksela przy użyciu przestrzeni kolorów LAB. Obliczona odległość została następnie zastosowana do kanału alfa oryginalnego obrazu. Główna różnica pomiędzy tym kolorem a kolorem do alfa jest tym, że piksele pikseli nie zostaną zmienione. Tło usuwa po prostu ustawia alfa (krycie) na różnicę przestrzeni kolorów. Działa dobrze, jeśli kolor tła nie występuje na pierwszym planie. Jeśli tak się stanie, nie można usunąć tła lub algorytm BFS musi być używany tylko do poruszania się po zewnętrznych pikselach (coś w rodzaju korzystania z wyboru magicznej różdżki w GIMP, a następnie usuwania zaznaczenia).

Nie można usunąć tła, jeśli obraz na pierwszym planie ma otwory i piksele w kolorze zbliżonym do koloru tła. Takie obrazy wymagają ręcznego przetwarzania.

+0

Nie testowałem jeszcze, ale już + 1 za twoją pracę;) Potrzebuję algo do zastosowania go na obrazach SVG, nie znalazłem rozwiązania, by to zrobić ... – abimelex

+0

Zastanawiam się, dlaczego być związane z grafiką wektorową. BTW, teraz gdy patrzę na to, zastanawiam się, co oznaczają parametry "mA" i "mX". Brakuje konwersji przestrzeni kolorów RGB do LAB.Jeśli ktoś jest zainteresowany usunięciem tła z obrazów rastrowych, mam działający kod w C# implementujący wszystko, co tu napisałem (przestrzeń kolorów LAB i BFS algo pozostawiają obiekt nietknięty podczas usuwania tła). Po prostu zadaj kolejne pytanie, ponieważ jest to coś więcej niż zwykły efekt "kolor do alfa". Nazwałbym to inteligentnym usuwaniem tła. Dobry do zdjęć "zielonego ekranu". – Harry

Powiązane problemy