Skip to content

AD-Styles/image-segmentation-from-scratch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🖼️ Image Segmentation from Scratch: FCN → U-Net → SMP

Python PyTorch SMP Kaggle


📌 프로젝트 요약 (Project Overview)

본 프로젝트는 이미지 세그멘테이션을 단순한 라이브러리 호출 수준을 넘어, 논문 구현 → 직접 설계 → 라이브러리 활용의 3단계 심화 학습으로 완성한 포트폴리오입니다. FCN 논문을 직접 구현하며 세그멘테이션의 원리를 체득하고, U-Net 아키텍처를 밑바닥부터 설계하며 Encoder-Decoder 구조의 본질을 이해한 뒤, 실무 수준의 SMP 라이브러리로 확장하여 성능을 검증하였습니다. 단순 코드 재현이 아닌, "왜 이 구조인가"를 스스로 설명할 수 있는 이해의 깊이를 데이터로 증명하려 노력했습니다.


🎯 핵심 목표 (Motivation)

핵심 역량 적용 단계       상세 목표 및 엔지니어링 포인트
논문 구현 능력
(Paper Implementation)
Stage 1. FCN VGG16 Backbone + Skip Connection 구조를 논문 스펙대로 직접 구현하여 이진 세그멘테이션 수행
아키텍처 설계 능력
(Architecture Design)
Stage 2. U-Net Encoder-Decoder + Concat 기반 Skip Connection을 밑바닥부터 설계하여 다중 클래스 세그멘테이션으로 확장
실무 적용 능력
(Production-level Tooling)
Stage 3. SMP ResNet34 Backbone + JaccardLoss + SMP Metrics를 활용하여 실무 수준의 파이프라인 구축

1. 실험 환경 및 단계별 도전 과제 (3 Stages)

단계 모델 데이터셋 작업 유형 도전 과제
Stage 1 (🥉) FCN8s Flood Area Segmentation Binary Segmentation VGG16 기반 Skip Connection 직접 구현, 마스크 Binary화 및 데이터 전처리
Stage 2 (🥈) U-Net (Custom) Car Segmentation (5 classes) Multi-class Segmentation Encoder-Decoder 구조 직접 설계, Concat 기반 Skip Connection, mIoU 계산 로직 구현
Stage 3 (🥇) SMP U-Net Car Segmentation (5 classes) Multi-class Segmentation ResNet34 Pretrained Backbone, JaccardLoss 적용, SMP Metrics(IoU, Dice, Accuracy) 파이프라인 구축

2. 프로젝트 구조

├── src/
│   └── main.py                  # 3개 Stage 통합 학습 및 그래프 자동 저장
├── results/
│   ├── fcn_loss.png             # Stage 1: Train/Val Loss 곡선
│   ├── fcn_iou.png              # Stage 1: IoU 곡선
│   ├── fcn_pa.png               # Stage 1: Pixel Accuracy 곡선
│   ├── unet_loss.png            # Stage 2: Train/Val Loss 곡선
│   ├── unet_iou.png             # Stage 2: mIoU 곡선
│   ├── unet_pa.png              # Stage 2: Pixel Accuracy 곡선
│   ├── smp_loss.png             # Stage 3: Train/Val Loss 곡선
│   ├── smp_iou_dice.png         # Stage 3: mIoU + Dice 곡선
│   └── smp_pa.png               # Stage 3: Pixel Accuracy 곡선
├── .gitignore                   # 불필요한 파일 업로드 방지
├── LICENSE                      # MIT License (AD-Styles)
├── README.md                    # 프로젝트 리포트
└── requirements.txt             # 라이브러리 설치 목록

3. 모델 아키텍처 상세 (Architecture Details)

🔹 Stage 1. FCN8s — 논문 직접 구현

FCN(Fully Convolutional Network)은 이미지 전체를 픽셀 단위로 분류하는 세그멘테이션의 시초 구조입니다.

  • Backbone: VGG16 (Pretrained) — Block3, Block4, Block5로 분리
  • 추가 Conv: Conv6 (512→4096), Conv7 (4096→4096)
  • Skip Connection: Pool3, Pool4의 Feature Map을 1×1 Conv로 채널 조정 후 덧셈(+) 연산으로 결합
  • Upsampling: ConvTranspose2d — 2배 × 2회 + 8배 × 1회 = 원본 해상도 복원
  • Loss: BCEWithLogitsLoss (이진 분류)
  • 평가지표: IoU, Pixel Accuracy
Input (B,3,H,W)
    → VGG16 Block3 → p3 (B,256,H/8,W/8)
    → VGG16 Block4 → p4 (B,512,H/16,W/16)
    → VGG16 Block5 → Conv6 → Conv7 → score (B,1,H/32,W/32)
    → Upsample×2 + p4 skip → Upsample×2 + p3 skip → Upsample×8
    → Output (B,1,H,W)

🔹 Stage 2. U-Net — 밑바닥부터 직접 설계

U-Net은 FCN과 달리 Encoder 각 단계의 Feature Map을 Decoder에 Concat하여 공간 정보를 더 정밀하게 복원합니다.

  • Encoder: 4단계 Double Conv(3×3) + MaxPool(2×2) — 채널: 64→128→256→512
  • Bottleneck: Double Conv — 512→1024
  • Decoder: 4단계 ConvTranspose2d(2×2) + Encoder Feature Map Concat(torch.cat) + Double Conv
  • Final Layer: 1×1 Conv → 클래스 수만큼 채널 출력
  • Loss: CrossEntropyLoss (다중 클래스)
  • 평가지표: mean IoU (클래스별 IoU 평균), mean Pixel Accuracy
Encoder:  [3]→64→128→256→512→[Bottleneck]→1024
Decoder:  1024→512(+cat e4)→256(+cat e3)→128(+cat e2)→64(+cat e1)→num_classes

FCN의 Skip Connection(+덧셈)과의 차이: U-Net은 Concat을 사용하여 채널 정보를 보존하므로 세밀한 경계 복원에 유리합니다.


🔹 Stage 3. SMP U-Net — 실무 수준 파이프라인

segmentation_models_pytorch 라이브러리를 활용하여 검증된 아키텍처와 손실 함수를 실무 수준으로 적용했습니다.

  • Backbone: ResNet34 (ImageNet Pretrained)
  • Loss: smp.losses.JaccardLoss (= IoU Loss) — IoU를 직접 최적화
  • Metrics: smp.metrics — Confusion Matrix(TP/FP/FN/TN) 기반 IoU, Dice Coefficient(F1), Accuracy
  • Multi-class vs Multi-label 개념 정리:
구분 Multi-class Multi-label
픽셀당 클래스 수 1개 (상호 배타적) 여러 개 (공존 가능)
마스크 형태 (B, H, W) (B, C, H, W)
활성화 함수 Softmax Sigmoid
손실 함수 CrossEntropy / JaccardLoss(multiclass) BCEWithLogitsLoss

4. 실험 결과 (Results)

최종 성능 요약

Stage 모델 Val Loss Val IoU Val Pixel Accuracy
Stage 1 FCN8s 0.27 0.72 0.89
Stage 2 U-Net (Custom) 0.54 0.28 0.80
Stage 3 SMP U-Net (ResNet34) 0.22 0.91 0.98

📈 Stage 1. FCN8s — Flood Area Binary Segmentation

학습 손실 (Train/Val Loss) IoU 곡선 Pixel Accuracy 곡선
loss iou pa
  • 최종 성능: Val Loss 0.27 / Val IoU 0.72 / Val Pixel Accuracy 0.89
  • 엔지니어링 인사이트: Val 곡선이 Train보다 지속적으로 높게 수렴하는 패턴이 관찰되었습니다. 290장이라는 소규모 데이터셋임에도 과적합 없이 일반화가 잘 이루어졌으며, 이는 VGG16 Pretrained Backbone의 강력한 특징 추출 능력 덕분입니다. 또한 인터넷 크롤링 데이터 특성상 RGBA, Grayscale 등 채널 불일치 이미지 3장을 사전 필터링하는 데이터 품질 관리 과정이 학습 안정성에 직접적인 영향을 미쳤습니다.

📈 Stage 2. U-Net — Car Multi-class Segmentation (Custom)

학습 손실 (Train/Val Loss) mIoU 곡선 Pixel Accuracy 곡선
loss iou pa
  • 최종 성능: Val Loss 0.54 / Val mIoU 0.28 / Val Pixel Accuracy 0.80
  • 엔지니어링 인사이트: mIoU가 0.28로 상대적으로 낮게 나타난 것은 모델 한계가 아닌 데이터셋 한계(211장, 5 classes) 에 기인합니다. 주목할 점은 15 Epoch 시점에도 mIoU가 지속 상승 중이었다는 것으로, Epoch을 늘리면 추가 개선 여지가 있음을 확인했습니다. FCN 대비 Concat 기반 Skip Connection이 차량 부품처럼 경계가 복잡한 영역에서 공간 정보를 더 정밀하게 복원함을 곡선 패턴을 통해 확인했습니다.

📈 Stage 3. SMP U-Net — Car Multi-class Segmentation (Library)

학습 손실 (Train/Val Loss) mIoU / Dice 곡선 Pixel Accuracy 곡선
loss iou pa
  • 최종 성능: Val Loss 0.22 / Val mIoU 0.91 / Val Dice 0.97 / Val Pixel Accuracy 0.98
  • 엔지니어링 인사이트: Stage 2(mIoU 0.28) 대비 Stage 3(mIoU 0.91)의 압도적인 성능 차이는 ResNet34 ImageNet Pretrained Backbone의 위력을 수치로 증명합니다. 또한 JaccardLoss(IoU를 직접 최적화)가 손실 함수와 평가 지표를 정렬(Alignment)시켜 단 5 Epoch 만에 mIoU 0.90을 돌파하는 빠른 수렴을 이끌어냈습니다. Dice와 mIoU가 함께 0.95 이상으로 수렴한 것은 클래스 불균형 상황에서도 모든 클래스를 고르게 잘 학습했음을 의미합니다.

💡 회고록 (Retrospective)

이번 프로젝트에서는 세그멘테이션을 단순히 라이브러리 API 호출 수준으로 익히는 것이 아닌, 논문의 수식과 그림을 코드로 직접 옮기는 구현 능력과, 그 구조가 왜 그렇게 설계되었는지를 이해하는 통찰력을 함께 키우는 데 집중했습니다.

  • Stage 1 (FCN): 처음 FCN 논문을 마주했을 때 가장 낯설었던 개념은 Skip Connection이었습니다. Pool3, Pool4의 Feature Map을 왜 다시 꺼내 쓰는가에 대한 답을 직접 구현하며 찾았습니다. 깊은 레이어일수록 의미(Semantic) 정보는 풍부하지만 공간(Spatial) 정보는 소실됩니다. Skip Connection은 이 두 정보를 합산하여 경계가 살아있는 세그멘테이션 맵을 만드는 핵심 장치임을 코드 레벨에서 체득했습니다.

  • Stage 2 (U-Net): FCN과의 결정적 차이는 Skip Connection 방식에 있었습니다. 덧셈(+)은 정보를 혼합하지만 Concat은 보존합니다. 채널을 그대로 이어붙임으로써 Decoder가 Encoder의 세밀한 공간 정보를 손실 없이 참조할 수 있게 되고, 이것이 차량 부품처럼 경계가 복잡한 대상에서 U-Net이 FCN보다 우수한 이유임을 직접 비교하며 확인했습니다.

  • Stage 3 (SMP): 직접 구현 이후 라이브러리를 사용하니 그 설계 의도가 명확하게 읽혔습니다. JaccardLoss가 단순히 "좋은 손실 함수"가 아니라 평가 지표인 IoU와 수식적으로 동일한 방향을 최적화한다는 점, 그리고 SMP Metrics의 Confusion Matrix 기반 설계가 클래스별 오분류 패턴을 분석하는 데 얼마나 유용한지를 이해할 수 있었습니다. 이 경험을 통해 라이브러리를 도구로만 쓰는 것과 그 내부 원리를 이해하고 쓰는 것의 차이가 실무 문제 해결 능력에서 얼마나 큰 격차를 만드는지를 실감했습니다.

세 단계를 거치며 얻은 가장 큰 수확은 기술 스택이 아닌 "구조를 읽는 눈" 입니다. 새로운 아키텍처를 마주했을 때 논문이든 코드든 그 설계 의도를 파악하고 직접 구현할 수 있는 능력, 그리고 라이브러리의 추상화 뒤에 숨겨진 수식을 이해하고 활용하는 능력이 이번 프로젝트를 통해 한 단계 성장했다고 자신 있게 말할 수 있습니다.

About

Implementing FCN & U-Net from scratch, then scaling with segmentation_models_pytorch — covering binary and multi-class segmentation on real-world datasets. / FCN, U-Net 논문 직접 구현부터 SMP 라이브러리 활용까지 — 실제 데이터셋으로 이진/다중 클래스 세그멘테이션을 단계적으로 학습한 기록.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages