3-3. 레퍼런스와 영역 프롬프트
ControlNet은 구조를 그림으로 지시했다. 이번에는 화풍과 생김새를 그림으로 지시하고, 화면의 어느 부분에 무엇을 그릴지를 나눠서 지시한다. 그림을 프롬프트처럼 쓰는 방법과, 프롬프트를 자리마다 따로 주는 방법이다.
그림을 프롬프트로: IP-Adapter
"이 그림 같은 느낌으로"를 글로 쓰기는 어렵다. 색감, 붓질, 분위기를 단어로 다 적을 수 없다. 그림을 직접 보여 주면 된다.
원리
1-5에서 텍스트가 디노이저에 들어가는 길을 봤다. 글 → 텍스트 인코더 → 토큰 벡터 → 크로스 어텐션. 같은 길을 그림용으로 하나 더 놓는다.
프롬프트 ──→ [텍스트 인코더] ──→ 토큰 벡터 ──→ 크로스 어텐션 ─┐
├→ 더한다
참조 그림 ──→ [이미지 인코더] ──→ 그림 벡터 ──→ 크로스 어텐션 ─┘
- 이미지 인코더: 그림을 벡터로 바꾼다. CLIP의 그림 쪽 절반을 쓴다. CLIP은 그림과 글을 같은 공간에 놓도록 학습했으니, 그림 벡터도 "프롬프트 같은 것"으로 쓸 수 있다.
- 따로 둔 크로스 어텐션: 텍스트용 어텐션은 그대로 두고, 그림용 어텐션을 새로 달아 학습한다. 두 결과를 더한다.
원래 디노이저는 얼려 둔다. 새로 단 어텐션과 작은 변환 층만 학습한다. ControlNet과 같은 생각이다. 원본을 건드리지 않고 옆에 붙인다.
무엇이 전해지나
참조 그림의 전반적인 인상이 전해진다. 색감, 화풍, 분위기, 대략의 구성, 인물의 대략적인 생김새.
정확한 형태는 전해지지 않는다. 그림이 벡터 몇십 개로 요약되기 때문이다. 자세를 그대로 가져오려면 ControlNet을 쓴다. 둘은 역할이 다르다.
| ControlNet | IP-Adapter | |
|---|---|---|
| 전하는 것 | 구조. 어디에 무엇이 있는가 | 인상. 어떤 느낌인가 |
| 넣는 그림 | 뼈대, 윤곽선, 깊이 | 완성된 그림 |
| 들어가는 길 | 디노이저의 각 단계에 더해 줌 | 크로스 어텐션 |
둘을 함께 쓰는 것이 흔하다. 포즈는 ControlNet으로, 화풍은 IP-Adapter로.
설정
| 설정 | 뜻 |
|---|---|
| 가중치 (weight) | 그림 쪽 어텐션 결과를 몇 배로 더할지. 높이면 참조 그림을 강하게 따른다 |
| 시작과 끝 | 어느 걸음 구간에 적용할지 |
| 적용 방식 | 화풍만, 구성만, 둘 다 |
가중치를 너무 올리면 참조 그림을 복사하다시피 해서 프롬프트가 안 듣는다. 0.5~0.8에서 시작한다.
적용 방식이 가능한 이유는 디노이저의 층마다 역할이 다르기 때문이다. 어떤 층은 구성에, 어떤 층은 화풍에 주로 관여한다. 그림 벡터를 특정 층에만 넣으면 그 성질만 전해진다.
얼굴 전용
얼굴을 닮게 그리는 변종이 있다. 일반 이미지 인코더 대신 얼굴 인식 모델이 뽑은 벡터를 쓴다. 얼굴 인식 모델은 "같은 사람인가"를 구분하도록 학습했으니, 그 벡터에는 생김새의 특징이 압축되어 있다.
실제 사람의 얼굴을 쓸 때는 주의하자. 본인의 동의 없이 남의 얼굴로 그림을 만드는 것은 많은 나라에서 법으로 금지되어 있다.
캐릭터 일관성에 쓸 수 있나
한 캐릭터를 여러 장면에 그릴 때 쓸 수 있다. 다만 한계가 있다.
- 대략 닮는다. 옷의 무늬, 머리 장식 같은 세부는 자주 달라진다.
- 참조 그림의 자세와 구도가 함께 딸려 온다. 정면 그림을 넣으면 정면으로 그리려고 한다.
정확한 일관성이 필요하면 캐릭터 LoRA(4단계)나 편집 모델(3-4)을 쓴다. IP-Adapter는 학습 없이 바로 쓸 수 있다는 것이 장점이다.
영역 프롬프트
인물 둘을 그린다. 한 명은 붉은 머리에 검은 옷, 다른 한 명은 푸른 머리에 흰 옷. 태그 모델에 이것을 쓰면 색이 뒤섞인다(2-3).
왜 섞이나
크로스 어텐션에서 그림의 모든 위치가 프롬프트의 모든 토큰을 본다. "붉은"이라는 토큰은 왼쪽 인물 자리에서도, 오른쪽 인물 자리에서도 보인다. 어느 인물의 것인지 구분할 방법이 CLIP에는 약하다. 그래서 속성이 새어 나간다.
해법: 자리마다 다른 프롬프트
화면을 영역으로 나누고, 영역마다 프롬프트를 따로 준다.
전체: 2girls, classroom
왼쪽 절반: red hair, black dress
오른쪽 절반: blue hair, white dress
원리는 크로스 어텐션을 영역으로 가리는 것이다. 왼쪽 영역의 그림 토큰은 왼쪽 프롬프트의 토큰만 본다. 오른쪽은 오른쪽만 본다. "붉은"이 오른쪽으로 새어 나갈 길이 없다.
ComfyUI에서는 조건(CONDITIONING)에 마스크를 붙이는 노드로 한다. 영역별 조건을 만들어 하나로 합친 뒤 KSampler에 넣는다.
요령
- 전체 프롬프트를 함께 준다. 영역만 주면 두 영역이 따로 놀아서 이어 붙인 그림처럼 된다. 배경, 조명, 화풍은 전체 프롬프트에 쓴다.
- 영역을 조금 겹친다. 경계가 딱 끊기면 선이 생긴다.
- ControlNet과 함께 쓴다. 포즈로 두 인물의 위치를 정하고, 그 위치에 맞춰 영역을 나눈다.
최신 모델에서는
문장을 이해하는 텍스트 인코더를 쓰는 모델은 이 문제가 훨씬 덜하다. "왼쪽 소녀는 붉은 머리에 검은 옷, 오른쪽 소녀는 푸른 머리에 흰 옷"이라고 쓰면 대개 그대로 그린다(2-3). 영역 프롬프트는 주로 태그 모델에서 필요한 기법이다.
도구를 고르는 기준
3단계에서 지금까지 나온 도구를 정리한다.
| 통제하고 싶은 것 | 도구 |
|---|---|
| 기존 그림을 바탕으로 | img2img (3-1) |
| 그림의 일부만 | 인페인팅 (3-1) |
| 자세, 구도, 윤곽 | ControlNet (3-2) |
| 화풍, 분위기 | IP-Adapter |
| 자리마다 다른 내용 | 영역 프롬프트 |
| 모델이 모르는 캐릭터나 화풍을 정확히 | LoRA (4단계) |
이것들은 서로 겹쳐 쓴다. 디노이저에 들어가는 길이 각각 다르기 때문에 가능하다.
해 볼 것
- 같은 프롬프트에 참조 그림만 바꿔 세 장을 뽑는다. 무엇이 따라오나?
- IP-Adapter 가중치를 0.3, 0.6, 1.0으로 바꿔 본다.
- 태그 모델에서 인물 둘의 머리색과 옷을 한 프롬프트로 지정한 것과 영역으로 나눈 것을 비교한다.
예상 결과
- 색감과 화풍이 참조 그림을 따라간다. 내용은 프롬프트를 따른다.
- 0.3은 색감만 살짝 닮는다. 0.6은 화풍이 뚜렷하게 닮는다. 1.0은 구도까지 참조 그림을 닮고 프롬프트가 잘 안 듣는다.
- 한 프롬프트로 쓴 쪽은 색이 자주 섞인다. 영역으로 나눈 쪽은 지정한 대로 나온다.
확인 문제
- IP-Adapter가 참조 그림의 정확한 자세를 전하지 못하는 이유는?
- 영역 프롬프트가 속성이 섞이는 것을 막는 원리는?
- 캐릭터의 포즈는 사진에서, 화풍은 다른 그림에서 가져오고 싶다. 무엇을 함께 쓰나?
풀이
- 그림이 벡터 몇십 개로 요약되어 크로스 어텐션으로 들어가기 때문이다. 전반적인 인상만 남고 위치 정보는 거의 사라진다.
- 크로스 어텐션을 영역으로 가려서, 각 영역의 그림 토큰이 그 영역의 프롬프트 토큰만 보게 한다.
- 포즈 ControlNet과 IP-Adapter를 함께 쓴다.