240711 - ComfyUI, Inpainting i wstęp do Controlnetów
Spis Treści #
- Teoria - czym jest Noise (szum) w SD?
- Odszumianie - noise enabled / disabled
- Controlnet jako mechanizm kontroli tworzenia się szumu
- Umieśćmy grzybowe miasto w dziwnym miejscu - zabawy z inpainting i maskami
- Usunięcie tła
- Dodanie maski i wyjaśnienie pipeline
- Zmiany: prompt, InvertMask, podaj oryginał (a nie wycięte) do VAE Encode
- VAE Encode for Inpainting
- Controlnet (Advanced), podstawy
- Substrat
- Canny - preprocesowanie substratu
- Canny - Controlnet
- Lekka zmiana substratu
- Zabawa z Controlnetem Canny
- Reguła: 70% mocy a nie 100%, różnica 70% a 30%
- Technika: 70% dla pierwszych 30% iteracji
- Szukamy ładnego seeda
- Dobra rada - wybierz non-converging sampler (Ancestral)
- Linki powiązane

1. Teoria - czym jest Noise (szum) w SD? #
1.1. Odszumianie - noise enabled / disabled #
Zacznijmy od czegoś poczciwego. Typowy workflow, DreamshaperXL, prompt: metropolis-themed mushroom surrounded by the skyscrapers, isometric . modern, futuristic, highly detailed, comic. Wynik:

Teraz - porównajmy dwa rysunki poniżej (różnica: noise_enabled TAK lub NIE w KSamplerze):

Jeśli popatrzymy na wpływ szumu i jak to działa, iteracje: 3, 6, 10, to od pewnego momentu zaczyna się kształtować rysunek:

Dla porównania, DOKŁADNIE TO SAMO dla noise-enable == false:

Czyli:
- wpierw pojawia się szum
- potem szum przekształcany jest w odpowiedni kształt
- szum jest tym co jest przekształcane w "coś innego"
1.2. Latent Image a szum #
Oki, to już znamy. Ten sam seed, to samo wszystko, ale kilka losowych figur geometrycznych zamiast pustego Latent Space na starcie. To sprawia, że generacja zacznie od szumu jaki pochodzi z pierwotnego obrazka a nie 100% losowego:

A tak to wygląda dla noise_enabled (czyli zwróć z szumem); 0-1-5:

A tak to wygląda dla noise_disabled (czyli zwróć bez szumu); 0-1-5:

2. Umieśćmy grzybowe miasto w dziwnym miejscu - zabawy z inpainting i maskami #
2.1. Usunięcie tła #
Biorę przykładowego poprzedniego grzyba i usuwam mu tło węzłem Rembg (jak kiedyś):

I teraz chciałbym umieścić to w innym stylu w innych okolicznościach. Chcę umieścić to miasto wśród płomieni i strasznych lovecraftiańskich sigili i innych rzeczy. Ale pierwszy eksperyment się niezbyt udał, bo zapomniałem o masce i dodałem jedynie szum z "pustym tłem" z tyłu:

2.2. Dodanie maski i wyjaśnienie pipeline #
Po korekcje maski wynik jest taki jak bym oczekiwał:

Ale wyjaśnijmy sobie ten pipeline:
- Zacznijmy od koloru NIEBIESKIEGO.
- Wczytujemy obrazek (LoadImage),
- potem podajemy go do VAE Encode i dostajemy Latent samples (zbiór liczb w przestrzeni wektorowej, która odzwierciedla ten rysunek)
- Potem kolor CZARNY
- Bierzemy obrazek i usuwamy z niego tło - dostajemy obrazek bez tła, z kanałem alpha (przezroczystym)
- Przekształcamy obrazek z kanałem alpha na maskę w miejscu koloru przezroczystego.
- JAKO, ŻE TO PNG to musimy zrobić mask invert. W ten sposób mówimy "możesz malować wszędzie ale nie na tym co nie jest przezroczyste"
- Potem kolor CYAN (jasnoniebieski?)
- Podajemy jako maskę do SetLatentNoiseMask wynik CZARNEGO
- Podajemy jako samples (czyli próbki, latent space) wynik NIEBIESKIEGO
- Przesyłamy dane dalej do KSamplera
2.3. Zmiany: prompt, InvertMask, podaj oryginał (a nie wycięte) do VAE Encode #
Popatrzcie co się stanie, jeśli zmienię samego prompta z:
- poprzedni: "metropolis-themed mushroom structure surrounded by the skyscrapers, isometric in the eldritch hellscape full of flames, inferno, blasphemous sigils and swirls of color . surrealist, unusual colors, pointillism, frame made of fire"
- nowy: "a futuristic isometric city with misty mountains in the background, rich landscape"

- Po pierwsze, miał problemy z prawidłowym umieszczeniem tego w odpowiednim ekosystemie przez "obwódkę na dole"
- Po drugie, do takich operacji lepsze są samplery non-converging, czyli Ancestral (np. Euler Ancestral)
Ale dodanie jednego czy dwóch KSamplerów czyszczących zmienią ten rysunek w coś fajnego.
A teraz sprawdźmy co się stanie jeśli usuniemy invert mask:

Czyli jak widzicie, do "starego szumu z grzybowym miastem" dodajemy "nowy szum z górami" a tło pozostaje bez zmian od oryginału z którego wycinaliśmy.
A co się stanie, jeśli podamy nie ten input do latent space?

- Nie możemy podać czegoś gdzie nie ma NIC do Latent Space (jak Latent Image)
- powstanie nam puste, proste tło
- bo "w innych miejscach" jest już ciekawy szum a tu nie
- -> Dlatego podajemy oryginalny rysunek
2.4. VAE Encode for Inpainting #
Mamy na to też specjalny węzeł, VAE Encode for Inpainting:

- GrowMask oznacza "ile może 'pożreć' z oryginalnego rysunku"
- dzięki niej zniknęła "ta obwódka" która zawsze nam przeszkadzała
- Zamiast tych luźnych węzłów na dole (VAE Encode, SetLatentNoiseMask) można użyć żółtego 'Vae Encode For Inpainting'
I to zadziała też dla prompta z górami:

3. Controlnet (Advanced), podstawy #
3.1. Substrat #
Zrobiłem grzyba na podstawie poprzednich eksperymentów, coś, co mi się całkiem podoba:

Na podstawie pipeline (zero udziwnień, przejście KSamplerem po wejściu):

3.2. Canny - preprocesowanie substratu #
I możemy go w odpowiedni sposób dostosować do naszych potrzeb używając Controlnetu opartego o CANNY (canny edges):

Oczywiście, możemy też wybrać jedynie GŁÓWNE cechy obrazka. Tak wygląda canny po ustawieniu wysokich thresholdów (granic):

- Niższe thresholdy -> więcej detali
- Wyższe thresholdy -> tylko wysokopoziomowy kształt
I mając powyższe możemy iść dalej.
3.3. Canny - Controlnet #
Musimy:
- Wczytać model Controlnet i wybrać Canny
- Podać rysunek jako wejście
- Wystawić "positive i negative" na zewnątrz
Czyli, węzeł Controlnet Advanced:

I teraz zróbmy to o co chodziło.
Prompt: "metropolis-themed technological mushroom emits cold light to soothe corrupted burning city, everything surrounded by the skyscrapers, isometric . modern, futuristic, highly detailed, comic"
Pipeline BEZ controlnetu, na powyższym prompcie:

Pipeline Z controlnetem, na powyższym prompcie:

Na co warto zwrócić uwagę, popatrzcie na czas wykonania promptów:

Canny Controlnet BARDZO spowalnia jeśli użyjemy go na pełnej mocy na cały czas. Ale możemy Coś Z Tym Zrobić.
3.4. Lekka zmiana substratu #
Oki - niebieski do żółtego z taką mocą po prostu jest "za mocny". Zmieńmy więc jedną rzecz - zblendujmy Empty Latent Image z aktualnym Latent Image, by zmniejszyć jego siłę. Od razu lepiej; nie MUSI być takie żółte:

Dokładnie to samo z Controlnet Canny (identyczne parametry) daje następujący wynik (koszt: 230 sekund):

A jeśli jeszcze bardziej osłabię kolory Latent Image (żeby Empty Latent Space miał większą wagę), 25-75, dostanę taki rysunek:

Dużo lepiej. Sprawdźmy 10%:

A teraz zmieńmy sobie prompt. Nie chcemy cały czas pracować w gorących technologicznych miastach. Czemu nie pobawić się czymś bardziej onirycznym?
Nowy prompt: "dreamscape, oniric technological mushroom emits cold light to soothe corrupted burning city, everything surrounded by the skyscrapers, isometric . surreal, ethereal, dreamy, mysterious, fantasy, highly detailed". I blend z 10% na 12%.
Wynik:

Z tym pracujemy dalej. Pro forma, porównajmy nasze rysunki: (30% - 10% - nowy prompt i 12%):

3.5. Zabawa z Controlnetem Canny #
3.5.1. Reguła: 70% mocy a nie 100%, różnica 70% a 30% #
Niekoniecznie chcemy wymuszać na controlnecie pełną kontrolę. Zwykle ustawia się Controlnet na 70% mocy jeśli chcemy mieć bardzo podobny wynik; chcemy zostawić modelowi pewną swobodę. Tak więc po zmianie STRENGTH controlneta z 1.0 do 0.7 dostajemy nieco inny wynik, lepszy, bo model miał możliwość połączenia "swojej wizji" z "wizją oryginalnego rysunku":

Jak widać, ma więcej kolorów, "swobody" itp a dalej trzyma kształt. A ctrlnet o strength 30?

Jak widać, ma podstawowy kształt, ale niewiele więcej. Zmieńmy Canny (żółty węzeł) na low threshold 40% i high 70%, nadal controlnet 30%:

I 40-70, dla controlnet 70%:

3.5.2. Technika: 70% dla pierwszych 30% iteracji #
Najważniejsze są pierwsze kroki. Controlnet dla pierwszych 30% operacji ma większe znaczenie niż dla ostatnich 30% operacji (wiemy z poprzedniego dokumentu i jak działa denoise). Więc ustawmy sobie węzeł Controlnet (ten czarny na następnym rysunku) na pierwsze 30% iteracji:

A to dla controlnet 10% pierwszych iteracji:

Jeśli dam controlnet na OSTATNIE 50% iteracji:

(przypadkowo, to sprawia że zamiast [300, 360] sekund te operacje zajmują [200, 300] sekund)
3.5.3. Szukamy ładnego seeda #
Ogólnie, ten pipeline na nieco innych wynikach:

3.5.4. Dobra rada - wybierz non-converging sampler (Ancestral) #
Po prostu, gdy mamy controlnet kontrolujący mniej niż 100% czasu, bo to pozwoli mu się dostosować i zmienić wynik na "lepszy".
3 inne grzyby na DPMPP_2M_SDE (ancestral family):

I zmieniłem styl na 'gothic', używając prompta: gothic style dark mysterious, technological mushroom emits cold light to soothe corrupted burning city, everything surrounded by the skyscrapers, isometric . haunting, dramatic, ornate, detailed i dodając do negatywnych cheerful, optimistic .
Trochę zmieniam parametry, by były różne efekty:
