AI 이미지/ComfyUI

ComfyUI에서 ControlNet 사용방법

하늘이푸른오늘 2023. 10. 10. 00:21

이 글은 Stable Diffusion 용 웹UI의 일종인 ComfyUI에서 ControlNet을 사용하는 방법에 대한 글입니다. AUTOMATIC1111 에서 ControlNet을 사용하는 방법은 사용법1사용법2를 참고하시면 되는데, 이 글에서는 중복되는 내용은 가능한 한 다루지 않습니다. 특히, ControlNet 모델 별로 어떤 특성이 있는지에 대해서는 사용법2를 꼭 읽어보시기 바랍니다. 

참고로, 이 글은 ComfyUI의 ControlNet 과 T2I-Adapter 예제 사이트 을 기본으로 하여 부족하다 싶은 것들은 다른 사이트에서 본 정보를 추가했음을 알려드립니다.

 이 글에서 다루는 내용은 아래와 같습니다.

Scribble ControlNet

아래는 예제 사이트에 올려진 Scribble ControlNet을 사용하는 워크플로입니다. 참고로, 아래 그림을 포함하여 이 글에서 생성된 이미지, 그리고 예제 사이트에 올려진 워크플로 그림에는 모두 워크플로 정보가 포함되어 있으므로, 다운로드 받은 다음 ComfyUI 캔버스에 Drag&Drop하면 동일한 워크플로를 사용할 수 있습니다.  

Scribble ControlNet 워크플로

위의 워크플로를 자세하게 살펴보겠습니다. 아래는 ControlNet에 관한 노드를 모두 이동시키고, 기본 노드들만 남겨둔 모습입니다. 보시면 아시겠지만, 여기에 나온 것은 [Load Defaut] 버튼을 눌렀을 때 나오는 기본 워크플로와 거의 동일합니다. 다른 점은 긍정적 프롬프트의 CONDITIOING 슬롯이 KSampler에 직접 연결되지 않았다는 것 뿐입니다.

Scribble ControlNet 워크플로 중 기본 워크플로

프롬프트의 CONDITIONING 출력 슬롯은 아래 그림과 같이 [Apply ControlNet] 노드의 conditioning 입력슬롯에 연결되고, 이 것이 출력노드인 CONDITIONING을 통해 KSampler와 연결됩니다. 즉, 여기에서 알 수 있는 것은 [CLIP Text Encode] 노드를 통해 만들어진 Embedding이 [Apply ControlNet]을 통해 수정된다는 것입니다. 결국 이 노드가 ControlNet 을 적용하는 핵심입니다. 

Scribble ControlNet 워크플로 중 ControlNet 관련 부분

[Apply ControlNet] 노드는 아래와 같이 입력 슬롯 3개, 출력 슬롯 하나가 연결됩니다. 이중  conditioning/CONDITIONING 슬롯은 위에서 설명드린 것처럼 [CLIP Text Encode] 노드의 출력 슬롯, 그리고 [KSampler]의 입력 슬롯에 연결되어, 조건부여(conditioning)에 끼어드는 형태가 됩니다.

Apply ControlNet  노드

[Apply ControlNet] 노드의 control_net 입력 슬롯은 [Load ControlNet Model] 노드에 연결됩니다. 말 그대로 ControlNet 모델을 불러오는 노드입니다. 여기를 눌러보면 다운로드 받은 ControlNet 모델이 모두 표시됩니다. 그중에서 적절한 모델을 선택해 주면 됩니다. 저는 아래와 같이 control_v11p_sd15_scribble.pth 를 선택했습니다.

Load ControlNet Model 노드

참고로 SD1.5용 ControlNet 최신 모델은 여기에서 받을 수 있고, stability.ai에서 발표한 SDXL용 ControlNet 모델은 여기(2랭크 256)여기(랭크 128)에서 받을 수 있습니다. 다운로드 파일은 ComfyUI\models\controlnet 또는 extra_model_paths.yaml에서 지정한 폴더에 넣으시면 됩니다. 기타 AUTOMATIC1111에서 SDXL 용 ControlNet 사용에 관한 글을 읽어보시면 여러가지 ControlNet 모델에 대한 비교를 보실 수 있습니다.

이 노드 아래는 Load Image가 있는데, 사용하고자 하는 ControlNet 모델에 적합한 이미지를 넣어주면 됩니다. 여기에서는 scribble(낙서) 모델을 사용하므로 손으로 그린 듯한 이미지를 넣은 것입니다. 

이렇게 설정하고 [Queue Prompt] 버튼을 누르면 아래와 같은 이미지가 생성됩니다. (이 그림을 캔버스에 Drag&Drop하면 제가 변경한 워크플로를 사용할 수 있습니다)

Scribble ControlNet 적용 결과

T2I-Adapter Depthmap

다른 ControlNet 예제도 비슷합니다. 아래는 예제 사이트에 올려진 T2I-Adapter Depthmap 예제입니다. 

T2I-Adapter Depthmap 워크플로

여기도 잘 살펴보시면 아래와 같이 [Apply ControlNet] 노드가 [CLIP Text Encode]  노드와 [KSampler] 노드 사이에 끼어 있음을 알 수 있습니다. 물론 적절한 콘트롤 넷 모델과 관련 이미지를 넣어야 정상적으로 동작하고요.

T2I-Adapter Depthmap 예제 중 ControlNet 해당 부분

그런데 T2I-Adapter는 일반 ControlNet 모델보다 훨씬 효율적이라고 추천한다고 합니다. 즉, ControlNet 을 사용하면 생성속도가 상당히 떨어지는데, T2I-adapter의 경우에는 생성 속도에 거의 영향을 미치지 않는다고 합니다. 이런 차이가 나타나는 이유는 ControlNet의 경우 매 단계(step) 마다 수행되는데 비해(즉 20 step이면 20번 수행되는 거죠), T2I-adpater 는 단 한번 실행되기 때문이라고 합니다. 저도 앞으로는 가능한한 T2I-Adapter를 사용하도록 방향전환해야 겠네요. 

아래도 Depth ControlNet을 사용하는 또다른 예입니다. 모양은 비슷하지만, [Load ControlNet Model] 노드 대신 [Load ControlNet Model(diff) 노드를 사용했습니다. ControlNet 모델도 Diff controlnet 이라고 하며 일반 콘트롤넷과 다른 것 같습니다. 저는 잘 모르는 내용이라 설명을 생략하겠습니다.

DiffControlNet Loader 워크플로

여기에서는 Scribble과 Depthmap에 대해서만 설명했는데, Openpose 등 다른 ControlNet도 마찬가지 방식으로 사용할 수 있습니다. 다른 어떤 ControlNet 모델이 있는지, 어떤 특성이 있는지에 대해서는 사용법1사용법2를 읽어보시기 바랍니다.

Preprocessor(전처리기)

이상의 예제에서는 ControlNet에 필요한 이미지를 직접 [Load Image] 노드에 불러서 사용했습니다. 즉,  AUTOMATIC1111과는 달리, 일반 그림을 콘트롤넷에 사용할 수 없고, 외부에서 처리한 후 사용해야 한다는 것입니다. 아주 불편하죠. 

이를 해결하기 위해서는 전처리기 확장을 설치해야 합니다. ComfyUI Manager 커스텀 노드를 설치했다면 간단하게 설치할 수 있습니다. ComfyUI를 사용하는 분들은 꼭 설치해야할 필수 커스텀 노드입니다.

[Queue Prompt] 명령 패널 맨 아래에 있는 [Manger] 버튼을 누르면 아래와 같은 윈도가 뜨는데 여기에서 [Install Custom Nodes]를 누르면...

ComfyUI Manager Meun

아래와 같은 윈도가 뜨는데요, 오른쪽 위 검색창에 controlnet을 입력한 후, Fannovel16님이 만든 ControlNet Auxiliary Preprocessors를 찾아 맨오른쪽에 있는 [Install] 버튼을 누르면 설치됩니다. 설치후에는 ComfyUI를 새로 시작해야 하고요.

ControlNet 전처리기 설치

다시 시작한 후 우클릭하여 아래와 같이 찾아가면 사용할 수 있는 모든 전처리기를 확인할 수 있습니다. 

ControlNet 전처리기 목록

또는 빈 캔버스를 더블클릭한 후, 검색창에서 preprocessor라고 입력해도 확인할 수 있는데, 모든 전처리기가 표시된 건 아니니 위의 방법으로 확인하는 것이 좋습니다.

ControlNet 전처리기 목록

예를 들어 아래 이미지를 CannyEdgePreprocessor를 사용해 처리해 이미지를 생성하는 예를 살펴보겠습니다.

진주 귀고리를 한 소녀

아래가 전처리기를 포함한 워크플로 중 중요한 부분입니다. [Load Image]노드에서 이미지를 부른 후, [Canny Edge] 전처리기를 거쳐 [Apply ControlNet]에 이미지가 공급되는 것을 알 수 있습니다.

아래는 생성결과입니다. 물론 이 이미지를 캔버스에 떨어뜨려도 워크플로가 복원됩니다. 그런데... 영 이미지 품질이 이상하네요.  좀더 연구해 봐야겠습니다. ㅠㅠ

진주 귀고리를 한 사이보그

위는 SDXL Base 모델만 사용해서 적용한 결과이고, 아래는 DreamShaperXL 모델을 사용하고 Refiner 모델을 적용했을 때의 결과입니다. (제가 일상적으로 사용하는 워크플로를 기반으로 만들었습니다.) ControlNet 부분은 [Load ControlNet] 노드 대신 [Load ControlNet (advanced)] 를 사용한 것 외에는 동일하니까 비교해 보시는 것도 좋을 것 같습니다 .

진주 귀고리를 한 사이보그

다중 콘트롤넷

가끔은 여러가지 콘트롤넷을 겹쳐서 사용해야 할 경우가 있습니다. 이런 경우도 [Apply ControlNet] 노드와 [KSampler] 노드사이에 또 다른 [Apply ControlNet] 노드를 삽입해주면 간단하게 구현할 수 있습니다. 예를 들어 아래는 ComfyUI ControlNet 예제 사이트에 올려진 예제 워크플로입니다. 

다중 콘트롤넷 워크플로

여기에 사용되는 콘트롤넷용 제어 이미지는 아래와 같습니다.

아래는 위의 워크플로중  ControlNet 부분만 추출한 것입니다. 앞의 Group은 오픈포즈용 콘트롤넷, 뒤의 그룹은 Scribble 용 콘트롤 넷으로, CONTIONTION 출력 슬롯이 conditioning 입력 슬롯으로 연결되었음을 알 수 있을 것입니다.

다중 콘트롤넷 워크플로중 일부

이런 식으로 연결하면 3개 이상의 콘트롤넷도 얼마든지 결합해 사용할 수 있습니다. 

마지막으로... 예제사이트에는 아래 이미지를 생성하는 워크플로도 들어있습니다(아래 그림을 캔버스에 떨어뜨리세요). 이 워크플로는 Openpose 모델을 사용하여 생성한 잠재 이미지를 한번 더 돌리는 방식의 2 pass 워크플로입니다. 이 방식에 대해서는 따로 설명하지 않겠습니다.

이상입니다. 

민, 푸른하늘

====