AI가 이미지에서 워터마크를 제거하는 방법 — 개발자를 위한 이미지 인페인팅 (Image Inpainting) 가이드
요약
이미지 인페인팅 기술을 통해 워터마크를 제거하고 이미지를 재구성하는 원리를 설명합니다. 워터마크 탐지를 위한 마스크 생성 단계와 손상된 픽셀을 복원하는 인페인팅 과정을 기술적 관점에서 분석합니다.
핵심 포인트
- 워터마크 제거는 단순 삭제가 아닌 픽셀의 재구성 과정임
- 인페인팅은 세그멘테이션과 재구성의 결합된 문제임
- 마스크 생성에는 수동 방식과 템플릿 매칭 방식이 존재함
- 딥러닝을 활용한 현대적 인페인팅 기술의 발전 과정을 다룸
만약 당신이 온라인 도구에 사진을 업로드하고 몇 초 만에 워터마크가 사라지는 것을 본 적이 있다면, 그것은 이미지 인페인팅 (image inpainting) 기술이 작동하는 것을 본 것입니다. 마치 마법처럼 보입니다. 하늘, 얼굴, 또는 제품 사진 위에 놓여 있던 반투명한 로고가 그냥... 사라지고, 그 아래의 픽셀들은 설득력 있게 재구성된 것처럼 보입니다.
이 포스트는 내부에서 실제로 어떤 일이 일어나고 있는지 분석합니다. 우리는 고전적인 픽셀 채우기 방식부터 현대적인 딥러닝 (deep-learning) 접근 방식까지의 발전 과정을 다루고, 실제 코드를 살펴보고, 이러한 시스템을 직접 구축하거나 통합할 때 마주하게 될 엔지니어링 트레이드오프 (engineering tradeoffs)에 대해 논의할 것입니다.
윤리에 관한 짧은 참고 사항: 워터마크 제거에는 정당한 용도가 있습니다 — 자신의 자산을 정리하거나, 오래된 스캔 사진을 복원하거나, 초안에서 자신의 브랜딩을 제거하거나, 권한을 가진 이미지를 처리하는 것 등입니다. 허가 없이 타인의 저작권이 있는 저작물을 사용하기 위해 워터마크를 제거하는 것은 이에 해당하지 않습니다. 아래의 기술들을 다른 이미지 편집 기능과 마찬가지로 취급하십시오.
핵심 문제: 그것은 "제거"가 아니라 "재구성"입니다
워터마크는 떼어낼 수 있는 레이어가 아닙니다. 이미지가 래스터화 (rasterized) 되면, 워터마크의 픽셀은 하위 이미지에 구워져(baked into) 버립니다. 그것을 "제거"한다는 것은 실제로 다음을 의미합니다:
- 탐지 (Detecting): 워터마크 픽셀이 어디에 있는지 찾아내는 것 (이를 통해 마스크 (mask) 생성).
- 재구성 (Reconstructing): 해당 마스크 처리된 픽셀 아래에 이미지가 아마도 어떤 모습이었을지 복원하는 것.
2단계가 어려운 부분이며, 이는 주변 픽셀의 단서를 사용하여 이미지의 누락되거나 손상된 영역을 채우는 **인페인팅 (inpainting)**이라 불리는 고전적인 컴퓨터 비전 (computer-vision) 문제입니다.
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 입력 이미지 │ → │ + 워터마크 │ → │ 인페인팅 │ → 깨끗한 이미지
│ (마크 포함) │ │ 마스크 │ │ 모델 │
...
따라서 "AI 워터마크 제거기"는 실제로 두 가지 문제가 사슬처럼 연결된 것입니다: 세그멘테이션 (segmentation) (마크 찾기)과 인페인팅 (inpainting) (구멍 채우기). 각각이 어떻게 진화했는지 살펴보겠습니다.
1단계 — 마스크 생성
인페인팅 (inpainting) 모델에게 어떤 픽셀을 교체해야 하는지 알려주는 이진 마스크 (binary mask)가 필요합니다. 워터마크의 종류에 따라 몇 가지 전략이 있습니다.
수동 또는 UI 지원 마스킹 (Manual or UI-assisted masking)
일반 사용자용 도구의 경우, 사용자가 브러시로 워터마크 위를 칠합니다. 단순하고 신뢰할 수 있는 방식입니다. 무언가를 감지할 필요 없이, 사용자가 작업할 위치를 정확히 알려주기 때문입니다. 대부분의 "브러시 및 지우기" 편집기가 이 방식을 사용합니다.
템플릿 매칭 (Template matching) (알려진 반복 로고의 경우)
동일한 워터마크가 반복적으로 찍혀 있다면 (예: 스톡 이미지 사이트의 대각선 패턴), 하나의 인스턴스를 템플릿으로 추출한 뒤 정규화된 상호 상관 (normalized cross-correlation)을 사용하여 모든 발생 위치를 찾을 수 있습니다.
import cv2
import numpy as np
...
이 방식은 빠르고 결정론적 (deterministic)이지만, 워터마크의 정확한 외형을 이미 알고 있을 때만 작동합니다.
학습된 세그멘테이션 (Learned segmentation)
텍스트 오버레이, 다양한 로고, 서명과 같은 임의의 워터마크의 경우, (워터마크가 있는 이미지, 마스크) 쌍으로 학습된 작은 세그멘테이션 (segmentation) 모델 (U-Net 또는 유사 모델)이 유연한 해답이 됩니다. 더 어려운 케이스는 마크가 색상과 배경이 혼합된 형태인 반투명 (translucent) 워터마크입니다. 이 경우 좋은 마스크는 단순히 On/Off 상태가 아니라 픽셀당 불투명도 (opacity) 정보를 포함해야 하며, 인페인터 (inpainter)는 이를 사용하여 워터마크 색상을 맹목적으로 덮어쓰는 대신 빼기 (subtract) 할 수 있습니다.
2단계 — 구멍 채우기: 인페인팅의 진화
고전적 시대: 확산 및 패치 기반 (The classical era: diffusion and patch-based)
OpenCV는 여전히 cv2.inpaint를 통해 두 가지 고전적인 알고리즘을 제공합니다.
- Telea (Fast Marching Method) — 경계면에서 안쪽으로 전파됩니다. 얇은 긁힘이나 작은 점에 효과적입니다.
- Navier-Stokes — 해당 영역을 유체 흐름 (fluid-flow) 문제로 취급하여, 가장자리 정보를 구멍 안으로 전달합니다.
# 반지름 3 — 얇은 긁힘 / 작은 점에 적합
result = cv2.inpaint(img, mask, 3, cv2.INPAINT_TELEA)
이 알고리즘들은 즉각적이며 GPU가 필요하지 않지만, 넓은 영역에서는 한계가 있습니다. 큰 간극 사이에서 흐릿하게 번지며 전역적 구조 (global structure)를 무시합니다. 질감이 있는 배경 위에 200×80 크기의 로고가 붙어 있는 경우, 이 방식은 눈에 띄는 번짐 현상을 만들어냅니다.
패치 기반 (Patch-based) 방식 (Photoshop의 Content-Aware Fill에서 사용되는 PatchMatch)은 이미지의 다른 곳에서 유사한 패치를 복사함으로써 훨씬 더 나은 성능을 보여주었습니다. 하지만 이 방식은 누락된 콘텐츠가 프레임 내의 어딘가에는 존재한다는 것을 전제로 합니다. 잔디나 하늘의 경우에는 이 전제가 참이지만, 워터마크에 의해 절반이 가려진 얼굴의 경우에는 거짓이 됩니다.
딥러닝 시대 (The deep-learning era)
이 시점부터 결과물이 실제 재구성 (reconstruction)처럼 보이기 시작했습니다. 알아둘 만한 몇 가지 이정표는 다음과 같습니다:
| 방식 (Method) | 핵심 아이디어 (Key idea) | 강점 (Strength) |
|---|---|---|
| Context Encoders (2016) | 인페인팅을 위한 최초의 CNN 인코더-디코더 (encoder-decoder) | 전역적 문맥 (global context) 학습 |
| ... |
복잡한 영역(반사광, 패턴이 있는 셔츠 등)에 걸쳐 있는 워터마크를 설득력 있게 채울 수 있는 이유는, 이 모델들이 자연스러운 이미지가 어떻게 생겼는지에 대한 **강력한 사전 지식 (strong prior)**을 학습했기 때문입니다. 주변 문맥이 주어지면, 모델은 그럴듯한 연속성을 환각 (hallucinate)해냅니다. 그것이 정확히 원래의 픽셀은 아닐지라도, 대개 지각적으로 충분히 가까워서 구분할 수 없을 정도입니다.
자세히 보기: 부분 합성곱 (Partial Convolutions)
부분 합성곱 (partial convolutions)의 획기적인 통찰은 우아합니다. 일반적인 합성곱 (regular convolution)은 이미지 위로 커널 (kernel)을 슬라이딩하며 커널 아래의 모든 것 — 즉, 무시하도록 설정한 마스크 처리된 (유효하지 않은) 픽셀까지 포함하여 — 을 혼합합니다. 이것이 단순한 CNN 인페인팅이 워터마크의 색상을 바깥쪽으로 번지게 만드는 이유입니다.
대신 부분 합성곱은 유효한 (마스크 처리되지 않은) 픽셀로부터만 출력을 계산하고 정규화 (renormalize)합니다:
import torch
import torch.nn as nn
import torch.nn.functional as F
...
마스크는 레이어를 거칠 때마다 줄어들며 (구멍이 가장자리부터 "먹혀" 들어감), 모든 단계에서 네트워크는 실제로 볼 수 있도록 허용된 정보만을 혼합합니다. 그 결과: 워터마크의 색상이 복구된 영역으로 번지는 현상이 발생하지 않습니다.
자세히 보기: LaMa
LaMa (Large Mask inpainting)는 품질과 속도 사이의 최적의 균형점을 제공하기 때문에 가장 먼저 찾게 될 핵심 도구입니다. LaMa의 비결은 **Fast Fourier Convolutions (FFC)**에 있습니다. FFC는 공간 도메인(spatial domain)에서만 컨볼루션(convolution)을 수행하는 대신, 주파수 도메인(frequency domain)에서 정보를 혼합하여 첫 번째 레이어부터 각 레이어에 본질적으로 **전역 수용 영역 (global receptive field)**을 부여합니다.
이것이 워터마크에 왜 중요할까요? 워터마크는 종종 이미지의 넓은 영역을 가로지릅니다. 일반적인 CNN은 수용 영역이 워터마크 전체를 한 번에 "볼" 수 있을 만큼 커지려면 많은 레이어를 쌓아야 합니다. 반면 FFC는 즉시 전체를 파악합니다. 이것이 LaMa가 이전의 CNN들보다 반복되는 구조나 긴 선(예: 울타리나 벽돌 담장을 가로지르는 워터마크)을 단 한 번의 순전파 (forward pass)만으로 훨씬 더 잘 재구성하는 이유입니다.
GPU를 사용하여 로컬에서 사전 학습된(pretrained) LaMa를 실행할 수 있습니다:
# pip install simple-lama-inpainting
from simple_lama_inpainting import SimpleLama
from PIL import Image
...
확산 모델 (Diffusion models): 아름답지만 비용이 많이 듭니다
최신 인페인팅 기술은 마스킹되지 않은 컨텍스트 (unmasked context)를 조건(condition)으로 하는 사전 학습된 확산 모델 (Stable Diffusion의 인페인팅 변형 등)을 사용합니다. 결과물은 놀라울 수 있으며 텍스트 프롬프트("맑고 푸른 하늘")를 따를 수도 있습니다. 하지만 각 생성 과정에는 수십에서 수백 번의 디노이징 (denoising) 단계가 필요하므로, 지연 시간 (latency)과 비용이 LaMa보다 한 자릿수(order of magnitude) 더 높습니다. 처리량이 높은 (high-throughput) 서비스를 구축할 때, 확산 모델은 보통 매우 어려운 케이스나 업스케일링된 최종 패스 (final passes)를 위해 남겨둡니다.
엔지니어링의 현실
이 기술을 기반으로 제품을 만들거나 평가하고 있다면, 모델은 전체 작업의 약 3분의 1에 불과할 수 있습니다. 나머지는 엔지니어링입니다:
지연 시간 (Latency) 및 처리량 (Throughput). 괜찮은 GPU에서 1024px 이미지에 대한 LaMa의 순전파는 몇 백 밀리초(ms) 정도 걸립니다. 확산 모델 인페인팅은 몇 초가 걸립니다. 배치 크기 (Batch size), 이미지 해상도 제한, 그리고 GPU 풀링 (GPU pooling)이 단위 경제성 (unit economics)을 결정짓는 핵심 요소가 됩니다.
마스크 품질이 전부입니다. 여기에는 "쓰레기가 들어가면 쓰레기가 나온다 (Garbage in, garbage out)"라는 원칙이 잔혹할 정도로 적용됩니다. 마스크가 너무 타이트하면 워터마크 잔여물이 남고, 너무 느슨하면 실제 디테일이 지워집니다. 소비자용 도구들은 UI(브러시 크기)나 학습된 세그멘테이션 (segmentation)을 통해 이를 숨깁니다.
반투명 워터마크 vs 불투명 워터마크. 불투명한 흰색 로고는 하나의 문제일 뿐이지만, 불투명도가 30%인 회색 로고는 또 다른 문제입니다. 후자는 단순히 그 위를 덧칠하는 것이 아니라, 오버레이 (overlay)를 추정하고 빼내는 과정이 필요합니다.
안전 및 저장. 사용자들은 민감한 이미지를 서버에 업로드하는 것에 대해 (당연하게도) 불안함을 느낍니다. 인메모리 (in-memory) 처리 및 즉각적인 삭제, 휘발성 세션 (ephemeral sessions) 지원, 그리고 궁극적으로는 클라이언트 측 추론 (client-side inference, WebGPU / WASM) 모두 신뢰 구축에 있어 중요합니다.
만약 이 모든 인프라를 직접 구축하고 싶지 않다면, 세그멘테이션 + 인페인팅 (inpainting) 파이프라인을 간단한 API와 웹 UI 뒤에 패키징하여 제공하는 호스팅 옵션들이 있습니다. 예를 들어, Watermark Remover AI는 이를 드래그 앤 드롭 도구와 API 액세스로 제공하며, 이는 직접 구축을 결정하기 전에 기술을 평가하기에 편리합니다.
직접 시도해보기: 최소한의 파이프라인
다음은 사용자가 제공한 마스크와 LaMa를 사용하여 마스크 + 인페인팅을 결합한 독립적인 스케치입니다:
from simple_lama_inpainting import SimpleLama
from PIL import Image, ImageDraw
...
다음 단계로 권장하는 연습 과제: 손으로 그린 마스크를 반투명 로고를 감지하는 임계값 처리 (thresholding) 단계로 교체한 다음, 재구성 품질 (알려진 깨끗한 버전 대비 PSNR/SSIM)을 측정해 보세요.
마무리
AI 워터마크 제거는 현대 컴퓨터 비전이 두 가지 아이디어 — 위치를 파악하기 위한 **세그멘테이션 (segmentation)**과 재구성을 위한 인페인팅 (inpainting) — 를 어떻게 조합하는지, 그리고 인페인팅 측면이 로컬 픽셀 확산 (local pixel diffusion) → 패치 복사 (patch copying) → 부분 컨볼루션 (partial convolutions) → FFC 기반 (LaMa) → 확산 모델 (diffusion models)로 어떻게 발전해 왔는지, 그리고 각 단계가 품질과 속도 및 비용 사이에서 어떻게 트레이드오프 (trade-off)를 이루는지 보여주는 깔끔한 사례 연구입니다.
가져가야 할 핵심 멘탈 모델 (mental model): 모델은 "진정한" 픽셀을 복구하는 것이 아닙니다. 주변 문맥 (context)에 따라 학습된 그럴듯한 자연 이미지의 분포 (distribution)로부터 샘플링하는 것입니다. 이것이 결과물이 완벽해 보이면서도 여전히 조작된 것일 수 있는 이유이며, 픽셀 수준의 정확도가 중요한 분야 (포렌식, 의료, 법률 등)에서 이러한 출력물을 _정답 (ground truth)_이 아닌 _재구성 (reconstructions)_으로 취급해야 하는 이유입니다.
파이프라인을 직접 구축하지 않고 최종 사용자 결과물을 확인하고 싶다면, Gemini Watermark Remover 데모를 시도해 보세요. 본인이 소유한 이미지를 넣고 마스크 (mask) + 인페인팅 (inpainting) 파이프라인이 작동하는 과정을 지켜볼 수 있습니다. 그 다음 다시 돌아와서 여러분만의 것을 구축해 보세요.
여러분이 즐겨 사용하는 인페인팅 (inpainting) 모델은 무엇인가요? WebGPU가 성숙해짐에 따라 더 많은 팀이 클라이언트 측 추론 (client-side inference)으로 이동할지 궁금합니다. 댓글로 알려주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기