Hair Removal로 접근했지만, 실제 문제는 Upper-Clothes Overwrite였다

ControlNet 기반 이미지 생성 파이프라인에서 마스크 정의를 재설계한 기술 회고

1. 문제 정의: Hair Removal 문제가 아니라 Garment Overwrite 문제였다

이번 작업의 시작점은 비교적 단순했다.
긴 머리카락이 상의 전면 일부를 가리고 있었고, 이를 자연스럽게 보정하는 것이 목표였다.
처음에는 이 문제를 hair removal로 해석했다. 즉, 머리카락 영역을 추출한 뒤 해당 영역을 inpainting으로 제거하거나 복원하면 해결될 것이라고 판단했다.

하지만 실제 디버깅 과정에서 확인한 것은, 이 문제를 hair removal로 정의하는 순간 파이프라인 전체가 잘못된 방향으로 흘러간다는 점이었다.

이번 작업의 실제 목적은 다음에 더 가까웠다.

  • 머리카락 자체를 정교하게 지우는 것
  • 머리카락 뒤에 있던 원래 옷을 그대로 복원하는 것

이 둘보다는,

  • 머리카락이 가린 상의 전면을 다시 생성해서
  • 최종 결과에서 상의가 머리카락보다 앞에 있는 것처럼 보이게 만드는 것

즉, 이번 문제는 제거 중심의 task가 아니라
upper-clothes overwrite / garment front regeneration에 가깝다.

이 차이를 정확히 구분하지 못하면 segmentation, mask generation, conditioning, compositing이 모두 어긋나게 된다.


2. 기존 파이프라인 구조: Hair-Centered Editing 관점의 흐름

당시 파이프라인은 전반적으로 hair-centered editing 구조에 가까웠다.
핵심 흐름은 대략 다음과 같았다.

  • hair mask 생성
  • 필요 시 SAM2 기반 refinement
  • face protect
  • Stable Diffusion inpainting
  • ControlNet conditioning
  • 후처리 및 합성

이 구조는 “헤어 영역을 편집하거나 생성하는 작업”에는 잘 어울린다.
실제로 hair segmentation, hair boundary refinement, face identity preservation 같은 작업에서는 꽤 자연스러운 구조다.

문제는 내가 해결하려는 대상이 더 이상 hair 자체가 아니었다는 점이다.
최종적으로 만들고 싶은 이미지는 머리카락이 없어진 상태의 상의 전면이었고,
이를 위해서는 hair 영역 자체보다 상의 전면의 재생성 대상 정의가 더 중요했다.

즉, 기존 파이프라인은 구조적으로 다음 질문에 최적화돼 있었다.

“머리카락을 어디까지 수정할 것인가?”

하지만 실제로 내가 던져야 했던 질문은 이쪽이었다.

“어떤 상의 영역을 새로 그려야 머리카락이 없어진 것처럼 보일까?”

겉보기에는 유사하지만, 생성 파이프라인에서는 완전히 다른 질문이다.


3. 초기 가정: Hair Mask만 정교하면 해결될 것이라는 착각

초기에는 비교적 직관적으로 생각했다.

  1. 머리카락 영역을 segmentation으로 정확하게 추출한다.
  2. 해당 영역을 refinement한다.
  3. 그 결과를 inpainting에 넣는다.
  4. ControlNet으로 구조를 보정한다.

이 접근은 표면적으로는 맞아 보인다.
실제로 이미지 위에 시각적으로 겹쳐져 있는 장애물이 머리카락이기 때문에,
그 영역만 정교하게 처리하면 문제가 해결될 것처럼 보이기 때문이다.

하지만 이 접근에는 근본적인 한계가 있었다.

  • 머리카락을 제거하는 것과
  • 머리카락이 없어진 것처럼 보이는 상의를 만드는 것은

동일한 작업이 아니다.

특히 긴 머리카락이 어깨선, 목선, 가슴 전면 일부를 넓게 가리고 있는 경우에는
단순한 hair removal이 아니라 가려진 의상 전면의 재구성이 핵심이 된다.

즉, “무엇을 삭제할 것인가” 중심의 마스킹은
“무엇을 다시 그릴 것인가” 중심의 생성 문제를 충분히 설명하지 못한다.


4. 핵심 오류 1: Visible Clothing Mask를 그대로 생성 마스크로 사용한 점

트러블슈팅 과정에서 가장 먼저 드러난 핵심 문제는
현재 사용 중인 생성 마스크가 visible clothing mask에 가까웠다는 점이다.

실제로 확인한 마스크는 다음과 같은 특징을 보였다.

  • 상의 마스크가 머리카락 실루엣을 따라 움푹 파여 있음
  • 머리카락이 걸친 부분은 옷 영역에서 제외됨
  • 즉, “현재 화면에서 보이는 옷”만을 기준으로 정의됨

이 마스크는 segmentation 관점에서는 합리적이다.
왜냐하면 segmentation 모델은 일반적으로 보이는 영역을 기준으로 클래스를 분리하기 때문이다.

하지만 생성 관점에서는 이 마스크가 오히려 문제를 만든다.
이 마스크를 생성에 그대로 쓰면 모델은 다음처럼 해석하게 된다.

  • 머리카락이 지나간 자리 자체는 구조적으로 유지해야 하는 영역
  • 옷은 그 경계를 피해 이어져야 하는 영역

그 결과 상의 전면이 하나의 연속된 면으로 재생성되지 못하고,
머리카락 실루엣을 기준으로 움푹 파인 구조가 계속 유지된다.

즉, visible mask는 “무엇이 지금 보이는가”를 알려줄 수는 있지만,
“무엇을 다시 그려야 하는가”를 정의해주지는 못한다.

이번 작업에서 진짜 필요했던 것은
hair occlusion을 무시한 amodal upper-clothes front mask였다.


5. 핵심 오류 2: Hair-Centered Mask Logic이 생성 목표를 제한한 점

기존 파이프라인의 핵심 로직은 hair-centered였다.
즉, 문제를 해석하는 기준점 자체가 hair mask에 맞춰져 있었다.

이 구조에서는 자연스럽게 다음과 같은 흐름이 만들어진다.

  • hair mask를 얼마나 정확히 뽑을 것인가
  • hair boundary를 얼마나 정교하게 다듬을 것인가
  • hair overlap을 얼마나 잘 분리할 것인가

하지만 이번 작업에서 중요한 것은 hair 자체의 정밀한 추출이 아니었다.
오히려 필요한 것은 머리카락과 겹친 상체 영역을 상의 쪽 regenerate 대상으로 귀속시키는 것이었다.

즉, 중심 질문이 바뀌어야 했다.

기존 질문

  • hair를 어디까지 분리할 것인가

필요한 질문

  • 상의 전면을 어디까지 다시 그릴 것인가

이 차이가 중요했던 이유는, 생성 모델은 결국 마스크가 정의한 영역을 기준으로 이미지를 다시 만들기 때문이다.
중심이 hair면 hair edit으로 흐르고, 중심이 clothes면 clothes overwrite로 흐른다.

이번 사례는 마스크 설계의 중심 객체가 바뀌면 태스크 해석 자체가 달라진다는 점을 보여줬다.


6. 핵심 오류 3: ControlNet Conditioning이 원본 Hair Edge를 다시 살릴 가능성

초기에는 ControlNet을 사용하고 있었기 때문에, 구조 보정은 어느 정도 해결될 수 있을 것이라고 기대했다.
실제로 ControlNet은 pose, edge, depth 같은 구조 조건을 강하게 반영하는 데 유리하다.

문제는 무슨 구조를 조건으로 넣고 있느냐였다.

edge 기반 conditioning을 사용할 경우, 원본 이미지에서 추출한 edge map에는 머리카락 실루엣도 함께 포함된다.
이 경우 내가 제거하고 싶었던 hair edge가 오히려 다시 생성 단계의 구조 조건으로 입력될 수 있다.

즉, ControlNet은 구조를 보정해 주는 도구지만,
그 구조가 잘못 정의되어 있으면 오히려 문제를 강화한다.

이번 사례에서 필요한 conditioning은 다음 성격에 가까워야 했다.

  • 원본 hair edge를 그대로 보존하는 conditioning
  • 머리카락 경계를 유지하는 conditioning

이 아니라,

  • upper body silhouette 중심 conditioning
  • clothes overwrite를 방해하지 않는 masked edge
  • hair silhouette를 덜 강조하는 구조 조건

즉, ControlNet의 유무보다 중요한 것은
ControlNet이 어떤 구조를 “보존해야 할 것”으로 인식하고 있느냐였다.


7. 핵심 오류 4: Post-Process를 메인 해결책처럼 바라본 점

후처리 단계는 흔히 마지막 품질 보정 장치처럼 느껴진다.
artifact cleanup, 경계 보정, 일부 잔상 제거 등에서 실제로 유효하기도 하다.

하지만 이번 작업에서는 후처리를 메인 해결책처럼 바라보면 안 됐다.
왜냐하면 현재 문제는 단순 artifact 문제가 아니라 재생성 대상 정의 자체가 잘못된 상태였기 때문이다.

즉, 메인 generation이 다음처럼 잘못 되어 있으면:

  • regenerate mask가 hair silhouette를 따라 파여 있고
  • conditioning이 hair edge를 보존하고 있고
  • composite 목적이 hair editing 관점에 묶여 있으면

후처리로 해결 가능한 범위를 이미 넘어선다.

후처리는 어디까지나 올바른 생성 결과를 조금 더 정리하는 단계이지,
생성 방향이 틀어진 파이프라인을 역전시키는 단계는 아니다.

이번 사례는 “후처리에서 어떻게든 잡겠지”라는 사고가 얼마나 위험한지도 보여줬다.


8. 해결 방향: Hair Removal에서 Upper-Clothes Overwrite로 파이프라인 재해석

문제를 다시 정의한 뒤, 해결 방향도 자연스럽게 달라졌다.
핵심은 파이프라인 전체를 hair removal 관점이 아니라 upper-clothes overwrite 관점으로 다시 해석하는 것이다.

구체적으로는 다음이 필요하다.

8.1 Regenerate Mask 재설계

최종 regenerate mask는 좁은 hair overlap 영역이 아니라,
상의 전면 전체 + 머리카락과 겹치는 상체 영역이 되어야 한다.

즉 마스크는 다음 조건을 만족해야 한다.

  • 양 어깨와 가슴 중앙부가 끊기지 않을 것
  • hair silhouette를 따라 움푹 파이지 않을 것
  • 목 아래 상의 전면이 하나의 연속된 면으로 정의될 것
  • hair overlap도 regenerate 대상에 포함될 것

8.2 Preserve 대상 축소

이번 작업에서 preserve의 핵심은 hair가 아니라 face다.
즉 face identity는 유지하되, hair 자체는 반드시 원형 유지할 필요가 없다.

이렇게 해야 generated clothes가 결과 이미지에서 더 앞 레이어처럼 보일 수 있다.

8.3 Conditioning 재설계

edge 기반 conditioning을 계속 쓴다면,
그 edge가 hair silhouette를 다시 강하게 보존하지 않도록 조정해야 한다.

즉 conditioning의 기준도
“원본 hair 구조 유지”가 아니라
“upper body structure 유지”로 바뀌어야 한다.

8.4 Composite 목적 변경

최종 합성도 “generated hair를 올리는 것”이 아니라
generated upper clothes를 front layer처럼 덮어쓰기 방향으로 바뀌어야 한다.

이 관점 전환이 이뤄져야 파이프라인 전체가 같은 목표를 향하게 된다.


9. 이번 트러블슈팅에서 얻은 기술적 교훈

이번 작업에서 얻은 교훈은 비교적 명확하다.

9.1 생성 태스크에서는 Segmentation Mask와 Generation Mask를 분리해서 생각해야 한다

segmentation은 보이는 영역을 분리하는 데 적합하다.
하지만 generation은 종종 보이지 않지만 다시 그려져야 하는 영역을 정의해야 한다.

즉 segmentation 결과를 그대로 generation mask로 가져오는 것은 위험할 수 있다.

9.2 문제 정의가 틀리면 모델 선택과 파라미터 튜닝은 한계가 있다

ControlNet, inpainting, face protect, 후처리 등은 모두 강력한 도구다.
하지만 regenerate 대상이 잘못 설정되어 있으면, 그 위의 튜닝은 구조적 한계를 벗어나기 어렵다.

9.3 “무엇을 제거할 것인가”보다 “무엇을 새로 그릴 것인가”가 더 중요할 수 있다

이번 이슈의 핵심 전환점은 바로 이 질문이었다.
머리카락을 어떻게 지울지가 아니라,
결국 어떤 상의 레이어를 다시 만들 것인지를 먼저 정의해야 했다.

9.4 Post-Process는 방향 수정이 아니라 미세 보정이다

메인 generation이 맞아야 후처리가 의미를 가진다.
후처리는 잘못된 regenerate target을 바로잡는 수단이 아니다.


10. 결론

이번 작업은 겉보기에는 단순한 hair occlusion 보정처럼 보였지만,
실제로는 문제 정의와 마스크 설계가 얼마나 파이프라인 전체를 좌우하는지를 보여준 사례였다.

처음에는 hair removal 문제라고 생각했다.
하지만 디버깅을 거치면서 실제 문제는 upper-clothes overwrite, 즉 상의 전면 재생성에 더 가까웠다는 점이 분명해졌다.

이 차이를 인식한 뒤에는 자연스럽게 다음이 보였다.

  • 왜 기존 마스크가 문제였는지
  • 왜 ControlNet이 해결해주지 못했는지
  • 왜 후처리에 기대면 안 되는지
  • 왜 segmentation 결과를 그대로 generation에 쓰면 안 되는지

앞으로 유사한 이슈를 다룰 때는,
먼저 눈에 띄는 가림 객체를 제거하는 관점보다
최종 이미지에서 어떤 레이어를 다시 생성해야 하는가를 기준으로 문제를 정의해야 한다.

이번 트러블슈팅은 그 기준을 다시 세우게 만든 사례였다.

+ Recent posts