AI 이미지/워크플로 따라하기

Stable Diffusion 무한 줌 이미지 만들기 - ComfyUI

하늘이푸른오늘 2023. 10. 11. 17:36

무한 줌 아트는 어떤 이미지가 끝없이 줌인 또는 줌아웃하는 듯한 착각을 불러 일으키는 시각 예술입니다. 아래가 그러한 예입니다. 이 글은 스테이블 디퓨전의 웹UI 중 하나인 ComfyUI를 사용해서 이러한 이미지를 생성하는 방법에 대한 글입니다.

무한줌 이미지

사이 처음에는 AUTOMATIC1111 으로 무한 줌 이미지를 만드는 방법을 올리려고 했습니다.  제가 구독하고 있는 Stable Diffusion Art 사이의 글을 참고로 해서요. 간략히 정리하면, AUTOMATIC1111에서 Infinite zoom 확장을 설치한 다음, 적절한 시간마다 원하는 프롬프트를 입력하면 된다는 내용입니다. 그다지 어렵지 않을 걸로 생각했습니다.

그런데, 딱 첫번째 실험을 하려고 [Generate]버튼을 눌렀더니 에러가 발생했습니다.  그래서 그냥 포기하고 ComfyUI로 생성하는 방법을 공부하기로 했습니다.

이 글에서 다루는 내용은 아래와 같습니다. ComfyUI의 원리에 대해서는 관심이 없으실 경우, 그냥 사용방법부터 보시면 됩니다.

ComfyUI Impact Pack 커스톰 노드 설치

먼저 커스톰 노드중 하나인 Impact Pack 을 설치해야 합니다. 그냥 ComfyUI\custom_nodes 폴더에 들어가서 아래 명령을 실행시킨 후, ComfyUI를 다시 시작하면 됩니다.

git clone https://github.com/ltdrdata/ComfyUI-Impact-Pack.git

그런데 이보다는 ComfyUI Manger 를 먼저 설치하고, 그 다음 다른 커스톰 노드를 설치하는 것이 관리하기 좋습니다. [ComfyUI Manager] -> [Install Custom Nodes]를 누르면 아래와 같은 화면이 뜨는데, 오른쪽 위 검색창에 impact를 입력한 후, ComfyUI Impact Pact의 오른쪽 [Install] 버튼을 누르면 설치가 됩니다. 

ComfyUI Impact Pack 커스톰 노드 설치

또한 동일한 방법으로 Efficiency Nodes for ComfyUI 커스톰 노드를 추가해줍니다. 이렇게 모든 커스톰 노드를 설치한 후, ComfyUI를 완전히 새로 시작해 주어야 사용할 수 있습니다.

워크플로 생성 및 설명

먼저 아래와 같이 [Efficient Loader] 노드와 [KSampler (Efficient)] 노드를 추가합니다.  이 커스톰 노드를 사용하는 것이 편하기 때문입니다. 물론 원리만 이해한다면 기본 노드로 대체해도 됩니다.

  • Efficient Loader - [Load Chechpoint] 노드, [CLIP Text Encode] 노드, [Load Latent Image] 노드 등, 모델에 관련되어 기본적으로 필요한 노드를 모두 합친 노드입니다.
  • KSampler (Efficient) - KSampler의 기능에 [Image Preview] 노드 및 [VAE Decode] 노드 등, 이미지 생성에 기본적으로 필요한 노드를 모두 합친 노드입니다.

그 다음 아래와 같이 연결해주고, 모델은 적당한 걸로 선택합니다. 저는 RealisticVision을 사용하며, 이미지 크기는 768x768로 설정했습니다. 제 설정은 아래와 같습니다.

모델: RealisticVisionv20
Prompt: a stunning cosmic scene featuring Earth, the Moon, and the milky way galaxy, Earth and its satellite shimmer brightly againtst the backdrop of a star-filled galaxy. Majestic, celestial, intricate. Digital art inspired by the work of NASA, 8K UHD, highly detailed, radiant colors
부정적 프롬프트: deformed iris, deformed pupils, semi-realistic, cgi, 3d, render, sketch, cartoon, drawing, anime, mutated hands and fingers, deformed, distorted, disfigured, poorly drown, bad anatomy
이미지 크기 : 768x768

모델 설정

다음으로 [KSampler(Efficient)] 노드의 IMAGE 출력 슬롯에 [Image Sender] 노드와 [Save Image] 노드를 연결하고 [Queue Prompt] 버튼을 누르면 아래와 같이 이미지가 생성됩니다. [Image Sender] 는 Add Node -> Impact Pack -> util -> ImageSender에 들어가면 찾을 수 있습니다. 빈 캔버스를 더블클릭하고 send로 검색해도 됩니다.

  • ImageSender - 생성된 이미지를 [ImageReceiver] 노드에 전달해주는 노드입니다. 

Image Sender 노드 추가

아래는 이렇게 해서 생성된 최초의 이미지입니다.

a stunning cosmic scene featuring Earth, the Moon, and the milky way galaxy

최초의 이미지를 만든 후에는 그 다음에는 이 이미지를 축소하면서 외부를 채워주는 방식으로 Zoom Out을 한 상태의 영상을 추가해 주여야합니다. 이렇게 계속 되면 무한 Zoom out하는 듯한 이미지를 만들 수 있죠. 

이를 위해 먼저 다음과 같이 노드를 추가하고 그림과 같이 IMAGE 출력슬롯과 image 입력슬롯을 연결해 줍니다.

  • ImageReceiver - [ImageSender] 노드에서 생성한 이미지를 받는 노드입니다. [Image Sender]에서 이미지를 받자마자 [Image Receiver]에도 동일한 영상이 전달됩니다.
  • ImageScale - 이미지 크기를 변경시키는 노드입니다. 주로 확대에 사용되지만, 여기에서는 이미지를 축소하는데 사용됩니다.
  • ImagePadForOutpainting - 이미지 바깥쪽을 채워주는 기능을하는 노드입니다.

Image Receiver 노드

여기에서 [Pad Image for Outpainting] 노드에서는 left/top/right/bottom을 각각 256씩으로 설정해주고, feathering,  즉 이미지가 서로 섞이게 하는 범위를 128 정도로 넓혀줍니다.

이렇게 되면 처음 생성했던 768*768짜리 이미지가 [Upscale Image] 노드를 거치면서 512x512로 줄어들었다가,  [Pad Image for Outpainting]를 통해 바깥쪽이 256씩 확대되어 최종적으로 1024x1024 짜리 이미지가 만들어지게 됩니다. 

물론 이렇게 채워진 바깥쪽은 그냥 까만색 이미지일 뿐이죠. 여기를 채워넣어야 합니다. 채워넣는 것은 ControlNet Inpaint 모델을 사용합니다. 아래와 같이 세가지 노드를 추가하고 아래 그림과 같이 연결해줍니다. 여기에서 [Load ControlNet Model] 노드에는 "control_v11p_sd15_inpaint.pth"를 불러오도록 설정해 줍니다.

  • ControlNetApply - ControlNet을 적용하는 핵심 노드입니다. 조건부여(conditioning)을 입력받아서 ControlNet을 적용한 변경 조건부여를 출력합니다.
  • ControlNetLoader - ControlNet  모델을 불러오는 노드입니다.
  • InpaintPreprocessor - ControlNet용 이미지를 전처리하는 노드중 하나입니다. 

ControlNet Inpaint 노드

이제 위에서 만든 노드들과 아래와 같이 연결해 줍니다. [Pad Image for Outpainting] 노드와 [InpaintPreprocessor] 노드를 링크로 연결해 주면 됩니다.

이미지 인페인트 노드들

이제 이렇게 생성된 이미지를 다시 원래의 이미지에 끼워넣어주어야 합니다. 먼저 아래 두개의 노드를 추가하고 아래 그림과 같이 연결해 줍니다.

  • VAEEncode - 일반 이미지를 VAE로 인코딩하여 Latent 이미지로 만들어주는 노드입니다. Img2img에서 가장 중요한 노드중 하나입니다.
  • SetLatentNoiseMask - 잠재(Latent) 이미지에 잡음을 추가해주는 노드입니다.

VAE Encode 노드 연결

여기에서 [VAE ENcode] 노드의 입력 pixels 슬롯은  [Pad Image for Outpainting] 노드의 IMAGE 출력 슬롯에, [Set Latent Noise Mask]노드의 입력 mask 슬롯은 [Pad Image for Outpainting] 노드의 MASK 출력 슬롯에 연결하는 것에 주의하세요.

그 다음 이렇게 생성된 Inpaint ControlNet을 원래의 이미지 생성 워크플로 속에 끼워넣습니다. 아래와 같이 연결해 주면 됩니다.

  • [Efficient Loader]의 CONDITIONING+ 출력슬롯          - [Apply ControlNet] 노드의 conditioning 입력슬롯
  • [Apply ControlNet] 노드의 CONDITIONING 출력슬롯 - [KSampler(Efficient)]노드의 positive 입력슬롯
  • [Efficient Loader]의 VAE 출력슬롯                                - [VAE Encode] 노드의 vae 입력 슬롯
  • [Set Latent Noise Mask]의 LATENT 출력슬롯              - [KSampler(Efficient)]노드의 latent_image 입력슬롯  

Inpaint ControlNet 워크플로를 본 워크플로에 삽입

이렇게 되면, [Efficient Loader]에 있는 모델 및 프롬프트와, Inpaint ControlNet 에서 생성된 이미지를 합성한 이미지가 생성되게 됩니다.

아래 이미지중 좌측 위가 기본 워크플로만으로 생성했던 이미지이고, 우측 위는 이 이미지를 가운데 축소해 넣은 다음 생성된 이미지, 좌측 아래는 이 이미지를 다시 축소해 생성한 이미지, 우측 아래는 다시 축소한 이미지입니다. 장 보시면 앞 사진이 가운데 부분에 축소해 들어가는 것을 확인하실 수 있을 겁니다.

이런식으로 계속 돌리게 되면 끝없이 우주속을 떠돌아 다니는 이미지를 만들 수 있을 겁니다. 하지만, 이렇게 계속 가면 재미없으니, 새로운 장면으로 바꿔줍니다. 아래가 프롬프트입니다. 

프롬프트: A crystal-clear brook babbling through an enchanged forest waking up from winter, the first blossoms of spring adorning the trees, Magical, life-filled, highly detailed digital painting inspired by the art of Eyvind Earle. vibrant and naturalistic colors.

아래는 다른 것은 건드리지 않고 프롬프트만 바꾼 후, 4번을 돌린 결과입니다. 처음엔 우주의 모습이 보이지만, 점점 축소되어서 결국엔 깊은 숲 속만 나타납니다. 

다음은 새로운 프롬프트입니다. 이번엔 흐르는 강물 옆으로 멋진 건축물이 있는 풍경입니다.

프롬프트: An architectural marvle of a modern house built into a hillside, surrounded by a meticulously landscaped garden with flowing water featuers. Innovative, sleek, serene. Photorealistic digital art in the style of Santiago Calatrava. Highly detailed, harmonious colors. 

이런 식으로 적당한 간격마다 프롬프트를 바꿔주고 계속 반복해주면 무한 줌 이미지를 만들 수 있습니다.

원래 이런 종류의 영상은 시나리오, 플롯 이 중요합니다. 잘 설계할 수록 멋진 결과물을 얻을 수 있죠. 그런데 저는 그냥 원본 영상에서 나오는 내용을 그냥 복사해서 사용했습니다. 아래는 연이어 사용했던 프롬프트들입니다.

프롬프트: A modern living room with industrial accents, esposed brick walls, leather furniture, and minimalist decor. The large factory-style windows let in an abundance of natural light. Edgy, sleek, trendy. Inspired by the digital art of Marc Tan. 4K UHD, highly detailed. bold colors

프롬프트: A vast, luxurious Arabian bedroom in sultan's palace, resplendent with silk drapes, orante lanterns casting dappled light, a bed fit for royalty. Regal, opulent. Oil painting in the tradition of Ludwig Deutsch. 4K UHD, rich texture

프롬프트: lush green field at the dawn of spring, with the first colorful buds sprrouting from the ground and a gentle morning sun piercing the fresh air. Vibrant, soothing, nature awakening. Impressionist style by Claude Monet. 4K UHD, high resolution

프롬프트: Bird's eye view of the Earth from space, featuring a glowing horizon and continets visible amidst clouds. Mesmerizing, majestic, detailed. Photorealistic digital art by the style of Earth observatory images. Highly detailed. 4K UHD. soft lighting

사용 방법

여기에서는 워크플로를 하나하나 따라하지 않고 그냥 사용하는 방법만 설명합니다. 위에서 워크플로를 따라서 만들었다면 다음으로 넘어가셔도 됩니다.

먼저 아래 이미지를 다운로드 받은 뒤, ComfyUI 빈 캔버스에 떨어뜨리면 이 워크플로가 그대로 올라옵니다.

무한 줌 워크플로

이 상태에서 첫 화면을 작성할 프롬프트를 입력하고 [Generate Image]를 누릅니다.  생성된 이미지가 마음에 안들면 여러번 반복해도 됩니다. 어떤 프롬프트를 입력할 지 모르겠다면, 바로 윗 절을 보시면 중간중간 프롬프트가 있으니 참고하세요.

첫번째 이미지가 완성되면 워크플로를 조금 바꿔줍니다. 아래는 연결방법입니다. 

  • [Efficient Loader]의 CONDITIONING+ 출력슬롯          - [Apply ControlNet] 노드의 conditioning 입력슬롯
  • [Apply ControlNet] 노드의 CONDITIONING 출력슬롯 - [KSampler(Efficient)]노드의 positive 입력슬롯
  • [Efficient Loader]의 VAE 출력슬롯                                - [VAE Encode] 노드의 vae 입력 슬롯
  • [Set Latent Noise Mask]의 LATENT 출력슬롯              - [KSampler(Efficient)]노드의 latent_image 입력슬롯  

Inpaint ControlNet 워크플로를 본 워크플로에 삽입

이 워크플로를 사용하면  씨드번호가 어떤 걸로 고정이 되어 있을텐데, 필요하면 -1 이나 다른 번호로 바꿔도 됩니다.

이렇게 연결시킨 후, 같은 프롬프트로 4-5번 정도 실행시키고, 프롬프트를 다른 것으로 바꿔서 4-5번 시키고... 이렇게 계속 반복하면 됩니다. 총 비디오 길이를 고려해서 반복해주시면 됩니다. 

참고: 만약 생성해 가다가 프롬프트 오류 등으로 생성한 이미지가 마음에 안들 경우, 편법이긴 하지만 수정할 방법이 있습니다. 정상적인 영상중 마지막 영상을 ComfyUI/input  폴더에 복사해서 넣고 (이 폴더는 img2img/인페인팅 등 이미지 입력 파일이 들어있습니다), 그중 하나를 지우고 복사해온 영상을 지운 파일 이름으로 바꿔줍니다. 그 다음 [Image Receiver] 노드에서 그 파일을 선택해주면 됩니다(선택해도 변경되지 않는 것처럼 보입니다). 

비디오 생성하기(Zoom Video Composer)

지금까지 만든 이미지들은 사이가 너무 벌어져 있습니다. 이대로 gif  등으로 합치면 앞 장면과 이어지는 장면이 연속적일 수가 없죠. 그래서 이미지 사이들을 좀더 채워주고, 이미지가 아닌 mp4 동영상으로 만들어줄 방법이 필요합니다. Zoom Video Composer가 이러한 역할을 수행합니다(물론 다른 프로그램도 있을 수 있습니다).

Zoom Video Composer는 아래의 저장소에서 받을 수 있습니다.

https://github.com/mwydmuch/ZoomVideoComposer

여기를 들어가보면, 이미지와 이미지 사이를 내삽해줄 때 속도가 일정하다고 하고요, 이미지 블렌딩(섞임)을 처리해줘서 부드럽게 이어지도록 해주며 속도/해상도/프레임 속도/줌 방향/이징(애니메이션 변화 제어) 등을 지원해주고, 필요하다면 음악도 추가할 수 있는 등 여러가지 장점이 있다고 합니다. 다만 줌 비율이 일정해야 하고 줌의 중심은 이미지 중심점이어야 한다고 하는데, 이 글에서 만들어지는 이미지는 이런 조건을 만족하니까 문제가 없네요.

Zoom Video Composer를 사용하려면 Python이 미리 설치되어 있어야 합니다. Python 설치는 따로 설명드리지 않습니다.

  • 이 파일을 다운로드 받아서 적당한 곳에 압축을 풉니다.
  • 해당 폴더에서 명령프롬프트(cmd) 를 실행합니다.
  • pip install -r requirements.txt 명령을 실행합니다.
  • 위에서 생성한 이미지를 적당한 서브폴더를 생성해서 넣습니다. 저는"ZoomVideoComposer-0.3.2\input"를 만들어 넣어주었습니다. 
  • 이때 이미지는 모두 사전순으로 정렬이 되어 있어야 합니다. ComfyUI의 일반적인 설정이라면 문제없습니다.

마지막으로 명령프롬프트에서 아래 명령을 입력합니다. 여기에서 input 은 이미지를 보관한 서브 디렉토리명, -m 0.2 는 이미지 주변 20%를 blending 해서 경계가 두드러지지 않도록 하는 옵션이고, -d 60 는 비디오 총 길이를 60초로 생성하라는 뜻이고, -e easeInOutSine 는 처음 시작은 느리게진행하다가 점점 빨라졌다가 끝날때 다시 느려지는 효과를 말합니다. 

python zoom_video_composer.py input -m 0.2 -d 60 -e easeInOutSine

아래는 이렇게 생성한 비디오입니다.

줌아웃 영상

보시는 것처럼 이 비디오는 줌 아웃을 합니다. 반대로 줌 인을 하는 비디오는 아래처럼 입력하면 됩니다.  

python zoom_video_composer.py input -d 60 -e easeInOutSine --direction in --reverse-images

아래는 이렇게 생성한 비디오입니다.

줌인 영상

github  사이트에 가시면 기타 다른 옵션도 있으니 필요하시면 확인하세요.

또 다른 예제

아래는 새로 테스트해 본 영상입니다. 여기에서는 Dreamshaper 모델을 사용했고, 이미지 크기를 1024*768로 맞췄습니다. 아래 이미지를 넣으면 워크플로를 확인하실 수 있는데, [Upscale] 노드를 지나면 512x384 로 줄어들고, [Pad image for Outpainting] 노드에서는 좌우로 512/2 = 256 픽셀만큼 늘리고, 위 아래로 384/2 = 192 픽셀만큼 늘려줘서 크기를 딱 맞추도록 했습니다.

무한 줌 워크플로가 포함된 황금 사원

무한 줌인 이미지

여기에서 사용한 프롬프트는 아래와 같습니다. 보시는 것처럼 뒷부분은 거의 똑같고, 앞부분은 서로 약간씩 겹치도록 해서 부드럽게 전이되도록 했습니다. 예를 들어 첫번째 프롬프트와 두번째 프롬프트는 temple이 공통이고, 두번째와 세번째 프롬프트는 waterfall이 공통입니다. 

inside golden temple, magical scene, dazzling glow, bright lighting, 8k, intricate, elegant, highly detailed, majestic, digital photography, art by artgerm and ruan jia and greg rutkowski, hdr

temple in waterfall, magical scene, dazzling glow, bright lighting, 8k, intricate, elegant, highly detailed, majestic, digital photography, art by artgerm and ruan jia and greg rutkowski, hdr

waterfall and jungle, magical scene, dazzling glow, bright lighting, 8k, intricate, elegant, highly detailed, majestic, digital photography, art by artgerm and ruan jia and greg rutkowski, hdr

jungle and green meadow, magical scene, dazzling glow, bright lighting, 8k, intricate, elegant, highly detailed, majestic, digital photography, art by artgerm and ruan jia and greg rutkowski, hdr

green meadow and lake, magical scene, dazzling glow, bright lighting, 8k, intricate, elegant, highly detailed, majestic, digital photography, art by artgerm and ruan jia and greg rutkowski, hdr

lake and desert, magical scene, sunlight, bright lighting, 8k, intricate, elegant, highly detailed, majestic, digital photography, art by artgerm and ruan jia and greg rutkowski, hdr

desert and barren wasteland, magical scene, sunlight, bright lighting, 8k, intricate, elegant, highly detailed, majestic, digital photography, art by artgerm and ruan jia and greg rutkowski, hdr

barren wasteland with snow, magical scene, sunlight, bright lighting, 8k, intricate, elegant, highly detailed, majestic, digital photography, art by artgerm and ruan jia and greg rutkowski, hdr

cozy living room with big windows and sofas, magical scene, sunlight, bright lighting, 8k, intricate, elegant, highly detailed, majestic, digital photography, art by artgerm and ruan jia and greg rutkowski, hdr

cozy and bright living room, magical scene, sunlight, bright lighting, 8k, intricate, elegant, highly detailed, majestic, digital photography, art by artgerm and ruan jia and greg rutkowski, hdr

이상입니다.

민, 푸른하늘

====