🔸 데이터셋 내려받고 압축 풀기
import wget
url = "http://www.robots.ox.ac.uk/~vgg/data/pets/data/images.tar.gz"
wget.download(url)
url = "http://www.robots.ox.ac.uk/~vgg/data/pets/data/annotations.tar.gz"
wget.download(url)
🔸 파일경로 분할
import os
input_dir = "images/"
target_dir = "annotations/trimaps/"
input_img_paths = sorted([os.path.join(input_dir, fname)
for fname in os.listdir(input_dir)
if fname.endswith(".jpg")])
target_paths = sorted([os.path.join(target_dir, fname)
for fname in os.listdir(target_dir)
if fname.endswith(".png") and not fname.startswith(".")])
input_img_paths[:3]
🔸 이미지 로드: keras.utils.load_img
import matplotlib.pyplot as plt
from keras.utils import load_img, img_to_array
plt.axis("off")
plt.imshow(load_img(input_img_paths[9]))
🔸 분할마스크 확인: keras.utils.img_to_array
img = img_to_array(load_img(target_paths[9], color_mode="grayscale"))
plt.axis("off")
plt.imshow(img)
🔸🔸 데이터 준비: 파일을 넘파이 배열로 로드하고(동일사이즈로), 훈련과 검증 세트 나누기
import numpy as np
import random
img_size = (200, 200)
num_imgs = len(input_img_paths)
random.Random(1337).shuffle(input_img_paths)
random.Random(1337).shuffle(target_paths)
#----------------------------------------------------------------------#
# 이미지 사이즈 동일하게 조정
# 원래레이블값:1,2,3/ 0,1,2가 되도록 수정
def path_to_input_image(path):
return img_to_array(load_img(path, target_size=img_size))
def path_to_target(path):
img = img_to_array(load_img(path, target_size=img_size, color_mode="grayscale"))
img = img.astype("uint8") - 1
return img
#----------------------------------------------------------------------#
# 데이터 넘파이 배열로 로드
# 전체이미지개수, (이미지 사이즈), 3혹은 1차원
input_imgs = np.zeros((num_imgs,) + img_size + (3,), dtype="float32")
targets = np.zeros((num_imgs,) + img_size + (1,), dtype="uint8")
for i in range(num_imgs):
input_imgs[i] = path_to_input_image(input_img_paths[i])
targets[i] = path_to_target(target_paths[i])
#----------------------------------------------------------------------#
# 훈련, 검증 데이터로 분리
num_val_samples = 1000
train_input_imgs = input_imgs[:-num_val_samples]
train_targets = targets[:-num_val_samples]
val_input_imgs = input_imgs[-num_val_samples:]
val_targets = targets[-num_val_samples:]
🔸🔸 모델 정의
import keras
from keras import layers
def get_model(img_size, num_classes):
inputs = keras.Input(shape = img_size + (3,))
x = layers.Rescaling(1./255)(inputs)
x = layers.Conv2D(64, 3, strides=2, activation="relu", padding="same")(x)
x = layers.Conv2D(64, 3, activation="relu", padding="same")(x)
x = layers.Conv2D(128, 3, strides=2, activation="relu", padding="same")(x)
x = layers.Conv2D(128, 3, activation="relu", padding="same")(x)
x = layers.Conv2D(256, 3, strides=2, padding="same", activation="relu")(x)
x = layers.Conv2D(256, 3, activation="relu", padding="same")(x)
x = layers.Conv2DTranspose(256, 3, activation="relu", padding="same")(x)
x = layers.Conv2DTranspose(256, 3, activation="relu", padding="same", strides=2)(x)
x = layers.Conv2DTranspose(128, 3, activation="relu", padding="same")(x)
x = layers.Conv2DTranspose(128, 3, activation="relu", padding="same", strides=2)(x)
x = layers.Conv2DTranspose(64, 3, activation="relu", padding="same")(x)
x = layers.Conv2DTranspose(64, 3, activation="relu", padding="same", strides=2)(x)
# 각 출력을 3개의 범주 중 하나로 분류하기 위해 3개의 유닛과 소프트맥스사용
outputs = layers.Conv2D(num_classes, 3, activation="softmax",padding="same")(x)
model = keras.Model(inputs, outputs)
return model
model = get_model(img_size=img_size, num_classes=3)
model.summary()
🔸🔸 모델 적용
model.compile(optimizer="rmsprop", loss="sparse_categorical_crossentropy")
callbacks = [keras.callbacks.ModelCheckpoint("oxford_segmentation.keras",
save_best_only=True)]
history = model.fit(train_input_imgs, train_targets,
epochs=50,
callbacks=callbacks,
batch_size=64,
validation_data=(val_input_imgs, val_targets))
🔸 그래프
epochs = range(1, len(history.history["loss"]) + 1)
loss = history.history["loss"]
val_loss = history.history["val_loss"]
plt.figure()
plt.plot(epochs, loss, "bo", label="Training loss")
plt.plot(epochs, val_loss, "b", label="Validation loss")
plt.title("Training and validation loss")
plt.legend()
🔸 분할마스크 예측
from tensorflow.keras.utils import array_to_img
i = 4
test_image = val_input_imgs[i]
plt.axis("off")
plt.imshow(array_to_img(test_image))
model = keras.models.load_model("oxford_segmentation.keras")
mask = model.predict(np.expand_dims(test_image, 0))[0]
# test_image = val_input_imgs[4]
# np.expand_dims(val_input_imgs[4], 0).shape >>>(1, 200, 200, 3)
# 0번 밖에 없음(예측을 1장만 함)
def display_mask(pred):
mask = np.argmax(pred, axis=1)
# mask *= 127
plt.axis("off")
plt.imshow(mask)
display_mask(mask)
** 이미지출처
https://drek4537l1klr.cloudfront.net/chollet2/Figures