코딩 및 기타/이미지
DeepLab v1
정지홍
2025. 1. 26. 13:24
DeepLab v1
- semantic segmentation문제를 해결하기 위해서 google에서 개발한 모델이다.
- 주요특징
- 1. atrous convolution 을 사용하여, pooling없이 receptive field를 확장할 수 있다.
- 2. Fully convolutional network 기반이다.
( 기존의 fully connected layer를 제거하고, 모든 레이어를 convolutional layer 바꾸어서 입력 크기에 상관없이 동작하게 함. ) - 3. Conditional Random Field ( 조건부 무작위장 )
- 위의 fully convolutonal network기반 출력은 간혹 경계가 부정확하거나 가장자리에서 세부 사항이 손실된다.
그래서 이를 해결하기 위해 CRF로 후처리를 하여, 세그멘테이션 결과를 정교화 시킴
- 위의 fully convolutonal network기반 출력은 간혹 경계가 부정확하거나 가장자리에서 세부 사항이 손실된다.
- 4. Multi-Scale Feature Extraction
- deepLab v1에서는 고정된 단일 스케일의 receptive field만 사용하는 대신 여러 스케일에서의 특징을 학습해서 다양한 크기의 객체를 더 잘 처리할 수 있다.
- DeepLab v1의 한계
- atrous convolution은 해상도를 유지하며 학습이 가능하나 계산비용이 높다.
- 실시간 응용 어려움
- CRF는 경계를 세밀하게 보정하지만, 별도의 후처리 단계로 작동해서 시스템 전체가 느려질수 있다.
- deeplab v1의 구성요소
- backbone network
- 기본적으로 VGG 16 을 사용한다. 그리고 VGG 16 의 풀링 레이어 뒤에 atrous convolution을 삽입해서 공간 해상도 보존
- 손실함수로 cross-entropy loss를 사용하여 segmentation 정확도를 향상
- backbone network
DeepLab v1의 동작 원리
- 1. atrous convolution 를 사용하여 더 넓은 문맥에서 정보를 수집함.
- 2. fully connected layer대신에 convolution layer만을 사용하였다.
- 즉, VGG 16의 마지막 Fully Connected Layer를 convolution layer로 바꾸어 사용함.
- 이로 인해 풀링으로 감소된 공간 해상도를 atrous convolution로 보완
- 즉, VGG 16의 마지막 Fully Connected Layer를 convolution layer로 바꾸어 사용함.
- 3. 후처리 단계로 Conditional Random Field ( 조건부 무작위장 )를 사용하였다. ( Unary Potential )
- 이는 주변 픽셀 간의 상관관계를 이용해서 각 픽셀의 클래스를 최정화한다.
특히나 경계 근처에서 불확실한 픽셀의 클래스를 조정함.
- 이는 주변 픽셀 간의 상관관계를 이용해서 각 픽셀의 클래스를 최정화한다.
- 4. 다중 스케일 특징을 학습해서 다양한 크기의 객체를 처리할 수 있게한다.
import tensorflow as tf
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Input, Conv2DTranspose, Softmax, Concatenate
from tensorflow.keras.models import Model
from tensorflow.keras.utils import plot_model
# VGG-16 백본 모델을 구축하는 함수
# 입력: 이미지 입력 크기 (input_shape)
# 출력: VGG-16의 마지막 convolution layer (block5_conv3)
def build_vgg16_backbone(input_shape):
inputs = Input(shape=input_shape)
# Block 1
x = Conv2D(64, (3, 3), activation='relu', padding='same')(inputs)
x = Conv2D(64, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), strides=(2, 2))(x)
# Block 2
x = Conv2D(128, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(128, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), strides=(2, 2))(x)
# Block 3
x = Conv2D(256, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(256, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(256, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), strides=(2, 2))(x)
# Block 4
x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), strides=(2, 2))(x)
# Block 5
x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv3')(x)
model = Model(inputs, x, name="VGG16_Backbone")
return model
# DeepLab v1 모델을 VGG-16 백본을 기반으로 구축하는 함수
# 입력: 이미지 크기 (input_shape), 클래스 수 (num_classes)
# 출력: DeepLab v1 모델
def build_deeplabv1_vgg16(input_shape=(512, 512, 3), num_classes=21):
base_model = build_vgg16_backbone(input_shape)
# VGG-16의 마지막 convolution layer (block5_conv3) 가져오기
x = base_model.get_layer("block5_conv3").output
# Atrous Convolution 적용 (다중 스케일 정보 추출)
atrous_rates = [6, 12, 18, 24]
atrous_layers = [Conv2D(512, (3, 3), padding='same', dilation_rate=rate, activation='relu')(x) for rate in atrous_rates]
# Atrous Convolution 결과 합치기
x = Concatenate()(atrous_layers)
x = Conv2D(512, (1, 1), activation='relu', padding='same')(x)
# Upsampling (16배 upsampling)
x = Conv2DTranspose(num_classes, kernel_size=16, strides=16, padding='same')(x)
x = Softmax()(x)
model = Model(inputs=base_model.input, outputs=x)
# 모델 구조 시각화 (Graphviz 사용)
plot_model(model, to_file='deeplabv1_vgg16.png', show_shapes=True, show_layer_names=True)
return model
# 모델 생성
model = build_deeplabv1_vgg16()
# 모델 구조 출력
model.summary()

