단체 사진은 거의 완벽할 수 있습니다. 좋은 조명, 모두가 프레임 안에 있고, 간직할 만한 순간이죠.
그런데 한 사람이 눈을 깜빡인 것을 발견합니다.
개발자에게 이것은 작은 이미지 편집 작업처럼 보입니다. 하지만 실제 요구 사항은 더 까다롭습니다:
사용자가 사진에 이미 좋아하는 모든 것을 유지하면서 눈을 뜨게 하는 것.
저는 MomentRescue라는 사진 복원 프로젝트를 만들고 있습니다. 이 게시물에서는 Open Eyes 워크플로우 뒤에 숨겨진 하나의 엔지니어링 질문, 즉 요청된 변경이 아주 미미할 때 생성적 편집(generative edit)을 어떻게 제약할 수 있는지 살펴봅니다.
1. 변경 가능한 범위를 정의하기
“이 사진을 더 좋게 만들어 주세요”는 개방형 요청입니다.
“선택된 사람의 감은 눈을 복구해 주세요”는 훨씬 좁은 경계를 가집니다.
이러한 구분은 단순히 프롬프트(prompt)에서가 아니라 시스템 설계에 나타나야 합니다. 유용한 계약 조건은 다음과 같습니다:
- 작업당 하나의 선택된 인물.
- 눈 주변의 복구 영역.
- 해당 영역을 벗어난 원본 이미지 픽셀.
- 원본이 손상되지 않은 별도의 출력 파일.
모델은 의도한 것보다 더 많은 것을 생성할 수 있습니다. 사용자의 애플리케이션이 최종 이미지에 어떤 생성된 픽셀이 도달할지 결정합니다.
이것이 제약을 요청하는 것과 그것을 강제하는 것의 차이입니다.
2. 생성(Generation)과 합성(Composition) 분리하기
실용적인 개념적 파이프라인은 다음과 같습니다:
Original photo
-> detect faces and confirm the selected person
-> prepare a face crop and optional reference
...
이는 완전한 구현이나 모든 사진 복원 도구가 이런 방식으로 작동한다는 주장이 아니라, 디자인 개요입니다.
중요한 분리는 후보를 생성하는 것과 픽셀을 최종 사진에 수용하는 것 사이의 구분입니다.
불투명한 RGB 이미지의 기본 블렌딩(blend)은 다음과 같습니다:
// Illustrative RGB compositing, not production image-processing code.
function blendPixel(original, candidate, maskAlpha) {
const a = Math.max(0, Math.min(1, maskAlpha));
...
허용된 영역을 벗어난 곳에서는 maskAlpha가 반드시 0이어야 합니다. 경계면에서는 점진적인 전환이 이음매를 부드럽게 할 수 있습니다.
어려운 작업은 이 작은 공식 주변에 있습니다: 좌표 매핑(coordinate mapping), 정렬(alignment), 마스크 배치(mask placement), 그리고 안경의 가장자리 처리입니다. 소프트 마스크로는 잘못 정렬된 눈을 고칠 수 없습니다.
또한, 디코딩된 픽셀(decoded pixels)을 보존하는 것은 원본 파일을 바이트 단위로 보존하는 것과는 다릅니다. 내보내기(Exporting) 과정에서 압축 및 메타데이터가 변경될 수 있습니다.
3. 참조 이미지를 보증이 아닌 증거로 취급하세요 (Treat a reference as evidence, not a guarantee)
감은 눈은 정보를 숨깁니다. 사람의 실제 눈을 드러내는 신뢰할 수 있는 '선명하게 하기(sharpen)' 작업은 없습니다.
같은 사람의 눈이 떠진 참조 이미지는 시각적 단서를 제공합니다. 하지만 머리 각도가 매우 다른 선명한 참조 이미지라도 여전히 부적합할 수 있습니다.
참조 이미지 선택자에게 유용한 지침은 구체적입니다:
- 양쪽 눈이 보이는 같은 사람을 선택하세요.
- 유사한 머리 각도와 조명을 선호하세요.
- 동일 세션의 주변 샷을 시도해 보세요.
- 선글라스, 심한 블러(heavy blur), 또는 픽셀 수가 매우 적은 얼굴은 피하세요.
참조 이미지에 여러 사람이 포함된 경우, 인터페이스는 그곳에 있는 일치하는 사람도 확인해야 합니다.
참조 이미지는 추측을 줄여줍니다. 하지만 생성된 결과가 정확하다는 것을 확립하지는 않습니다.
4. 두 가지 규모에서 예시를 검토하세요 (Inspect an example at two scales)
여기에 기존의 MomentRescue Open Eyes 테스트가 있습니다.
이 이미지들은 합성된 사람을 사용합니다. 이는 고객 사진, 추천 또는 벤치마크가 아닌 제품 시연입니다. 결과는 다를 수 있습니다.
Before: 중앙 인물은 눈을 감고 있습니다.
After: 기존 테스트 결과입니다.
전체 사진 뷰는 “사진이 여전히 일관성이 느껴지는가?”라는 질문에 답합니다.
면밀한 검토는 여러 질문에 답합니다. 양쪽 눈이 호환되는 방향을 바라보고 있는지? 눈꺼풀이 얼굴에 잘 맞는지? 안경테가 끊김 없이 연결되어 있는지? 눈에 띄는 블렌딩 경계(blend boundary)가 보이는지?
결과는 한 관점에서는 통과하지만 다른 관점에서는 실패할 수 있습니다.
5. '완료됨'과 '좋음'을 다르게 정의하기
API 응답은 처리가 완료되었음을 알려줄 뿐, 누군가가 본래의 모습처럼 보이는지 여부는 알려주지 않습니다.
저는 세 가지 별도의 검사를 통해 집중적인 복원(focused repair)을 평가할 것입니다:
| 검사 항목 | 질문 |
|---|
| 편집 포함성 (Edit containment) | 허용된 영역 외부에 디코딩된 픽셀이 변경되었습니까? |
| ... | |
첫 번째 검사는 마스크 외부의 디코딩 이미지를 비교하여 내보내기(export) 전에 자동화할 수 있습니다. 나머지 두 가지는 여전히 시각적 판단(visual judgment)이 필요합니다.
유용한 평가 사례로는 작은 얼굴, 측면 프로필, 안경, 불일치한 레퍼런스, 그리고 여러 사람이 동시에 눈을 깜빡이는 그룹 등이 포함됩니다. 깨끗하게 연출된 데모 이미지만으로는 그러한 모든 경우에 걸친 성능을 입증할 수 없습니다.
더 광범위한 엔지니어링 교훈
좁게 범위가 한정된 AI 편집의 경우, 출력 경계(output boundary) 자체가 기능의 일부입니다.
이 질문은 방해 요소를 제거하거나, 문서 영역을 복구하거나, 제품 사진 속의 객체 하나를 변경하는 경우에도 동일하게 적용됩니다:
시스템이 실제로 다시 쓸 수 있도록 허용된 입력 부분은 무엇인가?
명확한 답변은 구현하고, 검사하며, 테스트할 구체적인 무언가를 제공합니다.
결과가 그럴듯해 보이는지 여부를 확인하는 것을 넘어, 작은 얼굴 편집에서 정체성 보존(identity preservation)을 어떻게 평가하시겠습니까?
공개 정보: 저는 MomentRescue의 개발자입니다. 이 기사 초안 작성에 AI 지원이 사용되었습니다. 합성 스니펫은 예시적인 것이며, 프로젝트의 실제 구현 방식은 아닙니다.
워크플로우 참고 자료: MomentRescue가 선택한 얼굴 복원 파이프라인 설명.