
1. U-Net을 처음 구현했을 때의 가장 큰 오해
U-Net은 이미지 세그멘테이션의 교과서처럼 소개된다. Encoder–Decoder 구조, Skip Connection, 픽셀 단위 예측까지 모두 명확하다. 처음 Python으로 U-Net을 구현했을 때도 학습은 잘 되었고, 검증 데이터에서도 성능은 나쁘지 않았다. 문제는 실제 공정 이미지에 적용하는 순간 발생했다. 결과는 분명 “나뉘어” 있었지만, 현장에서 쓸 수 있는 분할은 아니었다.
2. 세그멘테이션이 실패하는 지점은 객체 내부가 아니었다
실패의 대부분은 객체 내부가 아니라 **경계(boundary)**에서 발생했다. 경계가 흔들리거나, 미세하게 어긋나거나, 프레임마다 요동쳤다. 공정 라인에서는 이 미세한 차이가 곧바로 불량 판정이나 후속 로직 오류로 이어졌다. 이때 깨달았다. 세그멘테이션의 성능은 IoU 점수가 아니라 경계 안정성으로 판단해야 한다는 사실을.
3. 데이터 증강이 오히려 독이 되었던 경험
논문과 튜토리얼에서는 데이터 증강이 필수처럼 소개된다. 하지만 실제 공정 이미지에 회전, 스케일, 왜곡을 적용하자 모델은 “현실에 없는 형태”까지 학습하기 시작했다. 결과적으로 경계가 부풀거나 찌그러지는 현상이 반복됐다. 이후 증강은 극단적으로 제한했고, 실제 발생 가능한 변형만 허용하는 쪽으로 방향을 바꿨다.
4. 기본 U-Net 구조가 현장에서 버거웠던 이유
기본 U-Net은 모든 픽셀을 동일한 중요도로 다룬다. 그러나 실제 이미지에서는 중요 영역과 의미 없는 영역이 명확히 나뉜다. 이 차이를 반영하지 않으면 모델은 배경에 쓸데없이 에너지를 소비한다. 그래서 구조를 바꾸기보다, 손실 함수와 마스크 가중치 설계를 먼저 손봤다. 이 결정이 성능 개선의 출발점이었다.
5. 실제 공정에 적용된 세그멘테이션 파이프라인
최종적으로 정착된 구조는 다음과 같았다.
입력 정규화 → ROI 제한 → U-Net 추론 → 경계 안정화 → 후처리 검증.
특히 ROI 제한은 매우 중요했다. 전체 이미지를 세그멘테이션하는 대신, 의미 있는 영역만 잘라서 처리하자 결과의 일관성이 크게 개선되었다.
6. Python 기반 U-Net 세그멘테이션 예제 코드
import torch
import torch.nn as nn
class UNet(nn.Module):
def __init__(self):
super().__init__()
self.encoder = nn.Conv2d(3, 64, 3, padding=1)
self.decoder = nn.Conv2d(64, 1, 3, padding=1)
def forward(self, x):
x = self.encoder(x)
x = self.decoder(x)
return x
코드 부가 설명
이 코드는 구조 설명을 위한 최소 형태다. 실제 공정에서는 채널 수를 줄이고, 레이어 깊이를 제한해 과적합과 경계 진동을 최소화했다. 또한 출력은 바로 사용하지 않고, 연속 프레임 기준으로 안정성을 평가한 뒤 채택했다.
7. 모바일과 데스크톱에서 세그멘테이션 결과가 다르게 보이는 이유
모바일에서는 픽셀 단위 오류가 거의 보이지 않는다. 반면 데스크톱에서는 경계의 톱니 현상이나 미세한 누락이 바로 드러난다. 이 차이 때문에 최종 검수는 항상 데스크톱 기준으로 진행했고, 모바일에서는 영역 비율 변화만 추가로 확인했다.
8. U-Net이 특히 약했던 실제 환경 조건
가장 어려웠던 조건은 조명 변화가 있는 환경이었다. 밝기 변화는 객체의 형태를 바꾸지 않지만, 픽셀 값은 크게 흔든다. 이 상황에서 U-Net은 경계를 흔들며 반응했다. 해결책은 복잡하지 않았다. 입력 단계에서 밝기 분포를 강제로 압축해 모델이 형태에만 집중하도록 유도했다.
9. 세그멘테이션 자동화를 포기한 지점
모든 이미지를 자동으로 세그멘테이션하려는 시도는 실패했다. 특정 케이스에서는 모델이 분할을 잘못해도 자신 있게 출력했다. 그래서 최종 시스템은 결과를 확정하지 않고, 신뢰도 기준을 넘는 경우만 후속 단계로 전달하도록 설계했다. 이 한 단계가 전체 시스템 오류를 크게 줄였다.
10. 실제 공정에서 남긴 기준과 버린 기준
남긴 기준은 명확했다.
모델 성능보다 결과 안정성,
복잡한 구조보다 예측 가능한 단순함,
높은 점수보다 일관된 실패 패턴.
반대로 “U-Net이면 충분하다”는 생각은 완전히 버렸다.
11. 결론: U-Net은 출발점이지 정답이 아니다
Python으로 이미지 세그멘테이션을 구현하며 얻은 결론은 분명하다. U-Net은 훌륭한 출발점이지만, 현장에 그대로 가져다 쓰면 실패한다. 세그멘테이션의 핵심은 구조가 아니라 어디까지를 믿고, 어디서부터를 의심할 것인가를 정하는 기준이다. 그 기준이 서지 않으면, 어떤 모델도 공정을 버티지 못한다.
'Computer Vision + Python > 이미지 향상 & 세그멘테이션 (연구자)' 카테고리의 다른 글
| Python으로 셀카/증명사진 자동 보정(Selfie Beautification) 구현 (0) | 2025.12.26 |
|---|---|
| Python으로 이미지에서 반사/글레어 제거(Reflection Removal) 기법 (0) | 2025.12.25 |
| Python으로 이미지에서 배경 제거(Background Removal) 및 합성 (0) | 2025.12.24 |
| Python으로 저해상도 이미지 해상도 복원(Super-Resolution) 구현하기 (0) | 2025.12.23 |
| Python으로 이미지 노이즈 제거(Denoising) 및 선명도 향상 실전 가이드 (0) | 2025.12.22 |