N432. Image Segmentation & Data Augmentation

ssu_hyunยท2021๋…„ 11์›” 14์ผ
0

[codestates] AI Bootcamp

๋ชฉ๋ก ๋ณด๊ธฐ
46/62

๐Ÿ† ํ•™์Šต๋ชฉํ‘œ

  • Image Segmentation ๊ฐœ๋…์„ ์ดํ•ดํ•˜๊ณ  ๋Œ€ํ‘œ ๋ชจ๋ธ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Image Augmentation์˜ ๊ฐœ๋…์„ ์ดํ•ดํ•˜๊ณ , ๊ธฐ๋ณธ์ ์ธ ์ฆ๊ฐ•๋ฐฉ์‹์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Object Recognition ๊ฐœ๋…์„ ์ดํ•ดํ•˜๊ณ , ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.



0. warm-up : oxford cs231n


*transposed convolutional layer




1. ์ด๋ฏธ์ง€ ๋ถ„ํ• (Image Segmentation)

๋ถ„ํ• (segmentation)
๋ถ„ํ• ์ด๋ž€ ์ด๋ฏธ์ง€๋ฅผ ํ”ฝ์…€ ์ˆ˜์ค€์—์„œ ๋ถ„๋ฅ˜ํ•˜๋Š” ๋ฌธ์ œ์ด๋‹ค.
์‹ ๊ฒฝ๋ง์„ ์ด์šฉํ•ด ๋ถ„ํ• ํ•˜๋Š” ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๋ฐฉ๋ฒ•์€ ๋ชจ๋“  ํ”ฝ์…€ ๊ฐ๊ฐ์„ ์ถ”๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. (SlidingSliding WindowWindow) ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Ÿฌํ•œ ์‹์œผ๋กœ๋Š” ํ”ฝ์…€ ์ˆ˜๋งŒํผ forward ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์•ผ ํ•˜์—ฌ ๊ธด ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๊ฒŒ ๋œ๋‹ค. (์ •ํ™•ํžˆ๋Š” ํ•ฉ์„ฑ๊ณฑ ์—ฐ์‚ฐ์—์„œ ๋งŽ์€ ์˜์—ญ์„ ์“ธ๋ฐ์—†์ด ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ์ด ๋ฌธ์ œ๊ฐ€ ๋œ๋‹ค.)์ด๋Ÿฌํ•œ ๋‚ญ๋น„๋ฅผ ์ค„์—ฌ์ฃผ๋Š” ๊ธฐ๋ฒ•์ด ๋ฐ”๋กœ FCN(FullyConvolutionalNetwork)FCN(Fully Convolutional Network)์ด๋‹ค. ์ด๋Š” ๋‹จ ํ•œ๋ฒˆ์˜ forward ์ฒ˜๋ฆฌ๋กœ ๋ชจ๋“  ํ”ฝ์…€์˜ ํด๋ž˜์Šค๋ฅผ ๋ถ„๋ฅ˜ํ•ด์ฃผ๋Š” ๋†€๋ผ์šด ๊ธฐ๋ฒ•์ด๋‹ค.(์ž…๋ ฅ ์ด๋ฏธ์ง€์˜ ๋ชจ๋“  ํ”ฝ์…€ ๊ฐ’์— ๋Œ€ํ•ด classification scores๋ฅผ ๋งค๊ธด ๊ฐ’์ด ์ถœ๋ ฅ๋˜์–ด ๋ชจ๋“  ํ”ฝ์…€์— ๊ฐ๊ฐ crossentropycross entropy๋ฅผ ์ ์šฉํ•˜์—ฌ loss๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ํ‰๊ท ๋‚ด๊ณ  backpropagationback propagationํ•จ์œผ๋กœ์จ ํ›ˆ๋ จ์„ ์ง„ํ–‰ํ•œ๋‹ค.) ์œ„ ๊ทธ๋ฆผ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ ์‚ฌ๋ฌผ ์ธ์‹์—์„œ ์‚ฌ์šฉํ•œ ์‹ ๊ฒฝ๋ง์˜ ์™„์ „์—ฐ๊ฒฐ ๊ณ„์ธต์—์„œ๋Š” ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ์˜ ๊ณต๊ฐ„ ๋ณผ๋ฅจ(๋‹ค์ฐจ์› ํ˜•ํƒœ)์„ 1์ฐจ์›์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ(flattenflatten) ํ•œ ์ค„๋กœ ๋Š˜์–ด์„  ๋…ธ๋“œ๋“ค์ด ์ฒ˜๋ฆฌํ–ˆ์œผ๋‚˜, FCNFCN์—์„œ๋Š” ๊ณต๊ฐ„ ๋ณผ๋ฅจ์„ ์œ ์ง€ํ•œ ์ฑ„ ๋งˆ์ง€๋ง‰ ์ถœ๋ ฅ๊นŒ์ง€ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋งˆ์ง€๋ง‰์— ๊ณต๊ฐ„ ํฌ๊ธฐ๋ฅผ ํ™•๋Œ€ํ•˜๋Š” ์ฒ˜๋ฆฌ๋ฅผ ๋„์ž…ํ–ˆ๋‹ค๋Š” ๊ฒƒ๋„ ํŠน์ง•์ด๋‹ค. ์ด ํ™•๋Œ€ ์ฒ˜๋ฆฌ๋กœ ์ธํ•ด ์ค„์–ด๋“  ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅ ์ด๋ฏธ์ง€์™€ ๊ฐ™์€ ํฌ๊ธฐ๊นŒ์ง€ ๋‹จ๋ฒˆ์— ํ™•๋Œ€ํ•  ์ˆ˜ ์žˆ๋‹ค.



1.1 U-Net

main idea

1) Contracting Path : ์ด๋ฏธ์ง€์˜ context(๋งฅ๋ฝ) ํŒŒ์•…

2) Expanding Path : feature map์„ upsampling ํ•˜๊ณ  1)์—์„œ ํฌ์ฐฉํ•œ feature map์˜ context์™€ concatenation(๊ฒฐํ•ฉ) โ†’ ์ด๋Š” ๋”์šฑ ์ •ํ™•ํ•œ localization์„ ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.




2. ๋ฐ์ดํ„ฐ ์ฆ๊ฐ• (Data Augmentation)

  • ๋ฌด์ž‘์œ„(๊ทธ๋Ÿฌ๋‚˜ ์‚ฌ์‹ค์ ์ธ) ๋ณ€ํ™˜์„ ์ ์šฉํ•˜์—ฌ ํ›ˆ๋ จ ์„ธํŠธ์˜ ๋‹ค์–‘์„ฑ์„ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๊ธฐ์ˆ 
  • ๊ฐ–๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ์…‹์„ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ augmentํ•˜์—ฌ ์‹ค์งˆ์ ์ธ ํ•™์Šต ๋ฐ์ดํ„ฐ์…‹์˜ ๊ทœ๋ชจ๋ฅผ ํ‚ค์šธ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•
  • AugmentationAugmentation = ์›๋ž˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ€ํ’€๋ ค์„œ ๋” ์ข‹์€ ์„ฑ๋Šฅ์„ ๋งŒ๋“ ๋‹ค๋Š” ๋œป
  • ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์•„์ง„๋‹ค๋Š” ๊ฒƒ์€ overfitting์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ๊ฐ–๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ์…‹์ด ์‹ค์ œ ์ƒํ™ฉ์—์„œ์˜ ์ž…๋ ฅ๊ฐ’๊ณผ ๋‹ค๋ฅผ ๊ฒฝ์šฐ, augmentation์„ ํ†ตํ•ด ์‹ค์ œ ์ž…๋ ฅ๊ฐ’๊ณผ ๋น„์Šทํ•œ ๋ฐ์ดํ„ฐ ๋ถ„ํฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•™์Šตํ•œ ๋ฐ์ดํ„ฐ๋Š” ๋…ธ์ด์ฆˆ๊ฐ€ ๋งŽ์ด ์—†๋Š” ์‚ฌ์ง„์ด์ง€๋งŒ ํ…Œ์ŠคํŠธ ์ด๋ฏธ์ง€๋Š” ๋‹ค์–‘ํ•œ ๋…ธ์ด์ฆˆ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ํ…Œ์ŠคํŠธ์—์„œ ์ข‹์€ ์„ฑ๋Šฅ์„ ๋‚ด๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋…ธ์ด์ฆˆ์˜ ๋ถ„ํฌ๋ฅผ ์˜ˆ์ธกํ•˜๊ณ  ํ•™์Šต ๋ฐ์ดํ„ฐ์— ๋…ธ์ด์ฆˆ๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ ๋ชจ๋ธ์ด ๋…ธ์ด์ฆˆ์— ์ž˜ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.
    => Data augmentation๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋Š˜๋ฆด ๋ฟ ์•„๋‹ˆ๋ผ ๋ชจ๋ธ์ด ์‹ค์ œ๋กœ ํ™˜๊ฒฝ์—์„œ ์ž˜ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค€๋‹ค.
  • ์ค‘์š”ํ•œ ์ด์œ 
    1) Preprocessing & augmentation์„ ํ•˜๋ฉด ๋Œ€๋ถ€๋ถ„ ์„ฑ๋Šฅ์ด ์ข‹์•„์ง„๋‹ค.
    2) ์›๋ณธ์— ์ถ”๊ฐ€๋˜๋Š” ๊ฐœ๋…์ด๋‹ˆ ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง€์ง€ ์•Š๋Š”๋‹ค.
    3) ์‰ฝ๊ณ  ํŒจํ„ด์ด ์ •ํ•ด์ ธ ์žˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ ์ฆ๊ฐ•์„ ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• : Keras ์ „์ฒ˜๋ฆฌ ๋ ˆ์ด์–ด, tf.image



2.1 Keras ์ „์ฒ˜๋ฆฌ ๋ ˆ์ด์–ด


ํฌ๊ธฐ ๋ฐ ๋ฐฐ์œจ ์กฐ์ •

  • ํฌ๊ธฐ ์กฐ์ • : tf.keras.layers.Resizing
  • ๋ฐฐ์œจ ์กฐ์ • : tf.keras.layers.Rescaling
### Resizing & Rescaling
IMG_SIZE = 180

resize_and_rescale = tf.keras.Sequential([
  layers.experimental.preprocessing.Resizing(IMG_SIZE, IMG_SIZE),
  layers.experimental.preprocessing.Rescaling(1./255)  # ํ”ฝ์…€ ๊ฐ’์„ [0,1]๋กœ ํ‘œ์ค€ํ™” / [-1,1]์„ ์›ํ•  ๊ฒฝ์šฐ, Rescaling(1./127.5, offset=-1)
])


### ๊ฒฐ๊ณผ ํ™•์ธ
result = resize_and_rescale(image)
_ = plt.imshow(result)


### ํ”ฝ์…€ ๊ฐ’์ด [0,1]๋กœ ํ‘œ์ค€ํ™”๋˜์—ˆ๋Š”์ง€ ํ™•์ธ
print("Min and max pixel values:", (result.numpy().min(), result.numpy().max()))
"""
>>> Min and max pixel values: (0.0, 1.0)
"""

๋ฐ์ดํ„ฐ ์ฆ๊ฐ•

### ๋ช‡ ๊ฐœ์˜ ์ „์ฒ˜๋ฆฌ ๋ ˆ์ด์–ด๋ฅผ ๋™์ผํ•œ ์ด๋ฏธ์ง€์— ๋ฐ˜๋ณต์  ์ ์šฉ
data_augmentation = tf.keras.Sequential([
  layers.experimental.preprocessing.RandomFlip("horizontal_and_vertical"),
  layers.experimental.preprocessing.RandomRotation(0.2),
])

# Add the image to a batch
image = tf.expand_dims(image, 0)

plt.figure(figsize=(10, 10))
for i in range(9):
  augmented_image = data_augmentation(image)
  ax = plt.subplot(3, 3, i + 1)
  plt.imshow(augmented_image[0])
  plt.axis("off")

์ด๋Ÿฌํ•œ ๋‹ค์–‘ํ•œ ์ „์ฒ˜๋ฆฌ ๋ ˆ์ด์–ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ 2๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

์˜ต์…˜ 1: ์ „์ฒ˜๋ฆฌ ๋ ˆ์ด์–ด๋ฅผ ๋ชจ๋ธ์˜ ์ผ๋ถ€๋กœ ๋งŒ๋“ค๊ธฐ

[์œ ์˜์‚ฌํ•ญ]

  • ๋ฐ์ดํ„ฐ ์ฆ๊ฐ•์€ ๋‚˜๋จธ์ง€ ๋ ˆ์ด์–ด์™€ ๋™๊ธฐ์ ์œผ๋กœ ๊ธฐ๊ธฐ์—์„œ ์‹คํ–‰๋˜๋ฉฐ GPU ๊ฐ€์†์„ ์ด์šฉํ•œ๋‹ค.
  • model.save๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋ธ์„ ๋‚ด๋ณด๋‚ผ ๋•Œ ์ „์ฒ˜๋ฆฌ ๋ ˆ์ด์–ด๊ฐ€ ๋ชจ๋ธ์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„๊ณผ ํ•จ๊ป˜ ์ €์žฅ๋œ๋‹ค. ๋‚˜์ค‘์— ์ด ๋ชจ๋ธ์„ ๋ฐฐํฌํ•˜๋ฉด ๋ ˆ์ด์–ด ๊ตฌ์„ฑ์— ๋”ฐ๋ผ ์ด๋ฏธ์ง€๊ฐ€ ์ž๋™์œผ๋กœ ํ‘œ์ค€ํ™”๋œ๋‹ค.
    ์ด๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์ธก ๋…ผ๋ฆฌ๋ฅผ ๋‹ค์‹œ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๋…ธ๋ ฅ์„ ๋œ ์ˆ˜ ์žˆ๋‹ค.
  • ์ฐธ๊ณ ) ๋ฐ์ดํ„ฐ ์ฆ๊ฐ•์€ ํ…Œ์ŠคํŠธํ•  ๋•Œ ๋น„ํ™œ์„ฑํ™”๋˜๋ฏ€๋กœ ์ž…๋ ฅ ์ด๋ฏธ์ง€๋Š”
    model.fit(model.evaluate ๋˜๋Š” model.predict๊ฐ€ ์•„๋‹˜) ํ˜ธ์ถœ ์ค‘์—๋งŒ ์ฆ๊ฐ•๋œ๋‹ค.
model = tf.keras.Sequential([
  resize_and_rescale,
  data_augmentation,
  layers.Conv2D(16, 3, padding='same', activation='relu'),
  # ํŠน๋ณ„ํ•œ ๊ธฐ์ค€์€ ์—†์Šต๋‹ˆ๋‹ค. 16๊ฐœ๋ฅผ ํ•ด๋„ ๋˜๊ณ , 32๊ฐœ๋ฅผ ํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๊ฐ€์ง€๋กœ ํ•ด๋ณด๊ณ  ์„ฑ๋Šฅ์ด ๋” ์ข‹์€ ์ชฝ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
  # (,3) -> (3, 3)
  layers.MaxPooling2D(),
  # Rest of your model
])

์˜ต์…˜ 2: ๋ฐ์ดํ„ฐ์„ธํŠธ์— ์ „์ฒ˜๋ฆฌ ๋ ˆ์ด์–ด ์ ์šฉํ•˜๊ธฐ

[์œ ์˜์‚ฌํ•ญ]

  • ๋ฐ์ดํ„ฐ ์ฆ๊ฐ•์€ CPU์—์„œ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ด๋ฃจ์–ด์ง€๋ฉฐ ์ฐจ๋‹จ๋˜์ง€ ์•Š๋Š”๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด Dataset.prefetch๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ GPU์—์„œ ๋ชจ๋ธ ํ›ˆ๋ จ์„ ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ์™€ ์ค‘์ฒฉํ•  ์ˆ˜ ์žˆ๋‹ค.(tf.data API๋กœ ์„ฑ๋Šฅ ํ–ฅ์ƒํ•˜๊ธฐ๊ฐ€์ด๋“œ์—์„œ ๋ฐ์ดํ„ฐ์„ธํŠธ ์„ฑ๋Šฅ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ๋‹ค.)
  • ์ด ๊ฒฝ์šฐ, ์ „์ฒ˜๋ฆฌ ๋ ˆ์ด์–ด๋Š” model.save๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ๋ชจ๋ธ๊ณผ ํ•จ๊ป˜ ๋‚ด๋ณด๋‚ด์ง€์ง€ ์•Š๋Š”๋‹ค. ์ €์žฅํ•˜๊ธฐ ์ „์— ์ด ๋ ˆ์ด์–ด๋ฅผ ๋ชจ๋ธ์— ์—ฐ๊ฒฐํ•˜๊ฑฐ๋‚˜ ์„œ๋ฒ„์ธก์—์„œ ๋‹ค์‹œ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค. ํ›ˆ๋ จ ํ›„, ๋‚ด๋ณด๋‚ด๊ธฐ ์ „์— ์ „์ฒ˜๋ฆฌ ๋ ˆ์ด์–ด๋ฅผ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ฐธ๊ณ ) ๋ฐ์ดํ„ฐ ์ฆ๊ฐ•์€ ํ›ˆ๋ จ ์„ธํŠธ์—๋งŒ ์ ์šฉํ•ด์•ผ ํ•œ๋‹ค.
### Dataset.map
aug_ds = train_ds.map(
  lambda x, y: (resize_and_rescale(x, training=True), y))


batch_size = 32
AUTOTUNE = tf.data.experimental.AUTOTUNE

def prepare(ds, shuffle=False, augment=False):
  # Resize and rescale all datasets
  ds = ds.map(lambda x, y: (resize_and_rescale(x), y), 
              num_parallel_calls=AUTOTUNE)  # ์–ด๋–ป๊ฒŒ ๋™์‹œ์— ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๋ฅผ ํ•  ๊ฒƒ์ธ๊ฐ€?

  if shuffle:
    ds = ds.shuffle(1000)

  # Batch all datasets
  ds = ds.batch(batch_size)

  # Use data augmentation only on the training set
  if augment:
    ds = ds.map(lambda x, y: (data_augmentation(x, training=True), y), 
                num_parallel_calls=AUTOTUNE)

  # Use buffered prefecting on all datasets
  return ds.prefetch(buffer_size=AUTOTUNE)


train_ds = prepare(train_ds, shuffle=True, augment=True)
val_ds = prepare(val_ds)
test_ds = prepare(test_ds)


### ๋ชจ๋ธ ํ›ˆ๋ จ
model = tf.keras.Sequential([
  layers.Conv2D(16, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(32, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(64, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Flatten(),
  layers.Dense(128, activation='relu'),
  layers.Dense(num_classes)
])


model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),  # 5๊ฐœ์˜ ๋ ˆ์ด๋ธ”(๋‹ค์ค‘ ๋ถ„๋ฅ˜)
              metrics=['accuracy'])


epochs=5
history = model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=epochs
)


loss, acc = model.evaluate(test_ds)
print("Accuracy", acc)

์‚ฌ์šฉ์ž ์ •์˜ ๋ฐ์ดํ„ฐ ์ฆ๊ฐ•

๋‹ค์Œ์œผ๋กœ ์†Œ๊ฐœ๋˜๋Š” ๋‘ ๋ ˆ์ด์–ด๋Š” ํ™•๋ฅ ์— ๋”ฐ๋ผ ์ด๋ฏธ์ง€์˜ ์ƒ‰์ƒ์„ ๋ฌด์ž‘์œ„๋กœ ๋ฐ˜์ „ํ•œ๋‹ค.

layers.Lambda ๋ ˆ์ด์–ด

def random_invert_img(x, p=0.5):
  if  tf.random.uniform([]) < p:
    x = (255-x)
  else:
    x
  return x
  
def random_invert(factor=0.5):
  return layers.Lambda(lambda x: random_invert_img(x, factor))

random_invert = random_invert()

plt.figure(figsize=(10, 10))
for i in range(9):
  augmented_image = random_invert(image)
  ax = plt.subplot(3, 3, i + 1)
  plt.imshow(augmented_image[0].numpy().astype("uint8"))
  plt.axis("off")


์„œ๋ธŒ ํด๋ž˜์Šค ์ƒ์„ฑ

class RandomInvert(layers.Layer):
  def __init__(self, factor=0.5, **kwargs):
    super().__init__(**kwargs)
    self.factor = factor

  def call(self, x):
    return random_invert_img(x)


_ = plt.imshow(RandomInvert()(image)[0])

์œ„์˜ layers.preprocessing ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” ํŽธ๋ฆฌํ•˜๋‹ค. ๋ณด๋‹ค ์„ธ๋ฐ€ํ•œ ์ œ์–ด๋ฅผ ์œ„ํ•ด์„œ๋Š” tf.data ๋ฐ tf.image๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ ์œ ํ•œ ๋ฐ์ดํ„ฐ ์ฆ๊ฐ• ํŒŒ์ดํ”„๋ผ์ธ ๋˜๋Š” ๋ ˆ์ด์–ด๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. (TensorFlow ์• ๋“œ์˜จ ์ด๋ฏธ์ง€: ์ž‘์—… ๋ฐ TensorFlow I/O: ์ƒ‰ ๊ณต๊ฐ„ ๋ณ€ํ™˜๋„ ํ™•์ธํ•ด๋ณผ ๊ฒƒ)


2.2 tf.image


๋ฐ์ดํ„ฐ ์ฆ๊ฐ•

### ๊ฝƒ ๋ฐ์ดํ„ฐ์„ธํŠธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
(train_ds, val_ds, test_ds), metadata = tfds.load(
    'tf_flowers',
    split=['train[:80%]', 'train[80%:90%]', 'train[90%:]'],
    with_info=True,
    as_supervised=True,
)


### ์ž‘์—…ํ•  ์ด๋ฏธ์ง€ ๊ฒ€์ƒ‰
image, label = next(iter(train_ds))
_ = plt.imshow(image)
_ = plt.title(get_label_name(label))


### ์›๋ณธ ์ด๋ฏธ์ง€์™€ ์ฆ๊ฐ• ์ด๋ฏธ์ง€๋ฅผ ๋‚˜๋ž€ํžˆ ์‹œ๊ฐํ™” & ๋น„๊ต
def visualize(original, augmented):
  fig = plt.figure()
  plt.subplot(1,2,1)
  plt.title('Original image')
  plt.imshow(original)

  plt.subplot(1,2,2)
  plt.title('Augmented image')
  plt.imshow(augmented)
  
  
### ์ด๋ฏธ์ง€ ๋’ค์ง‘๊ธฐ : ์ด๋ฏธ์ง€๋ฅผ ์ˆ˜์ง ๋˜๋Š” ์ˆ˜ํ‰์œผ๋กœ ๋’ค์ง‘๊ธฐ
flipped = tf.image.flip_left_right(image)
visualize(image, flipped)

### ์ด๋ฏธ์ง€๋ฅผ ํšŒ์ƒ‰์กฐ๋กœ ๋งŒ๋“ค๊ธฐ
grayscaled = tf.image.rgb_to_grayscale(image)
visualize(image, tf.squeeze(grayscaled))
_ = plt.colorbar()

### ์ด๋ฏธ์ง€ ํฌํ™”์‹œํ‚ค๊ธฐ : ์ฑ„๋„ ๊ณ„์ˆ˜๋ฅผ ์ œ๊ณตํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ํฌํ™”์‹œํ‚จ๋‹ค.(smoothing ํšจ๊ณผ)
saturated = tf.image.adjust_saturation(image, 3)
visualize(image, saturated)

### ์ด๋ฏธ์ง€ ๋ฐ๊ธฐ ๋ณ€๊ฒฝํ•˜๊ธฐ : ๋ฐ๊ธฐ ๊ณ„์ˆ˜๋ฅผ ์ œ๊ณตํ•˜์—ฌ ์ด๋ฏธ์ง€์˜ ๋ฐ๊ธฐ๋ฅผ ๋ณ€๊ฒฝ
bright = tf.image.adjust_brightness(image, 0.4)
visualize(image, bright)

### ์ด๋ฏธ์ง€ ์ค‘์•™ ์ž๋ฅด๊ธฐ : ์ด๋ฏธ์ง€๋ฅผ ์ค‘์•™์—์„œ ์›ํ•˜๋Š” ์ด๋ฏธ์ง€ ๋ถ€๋ถ„๊นŒ์ง€ ์ž๋ฅด๊ธฐ
cropped = tf.image.central_crop(image, central_fraction=0.5)
visualize(image,cropped)

### ์ด๋ฏธ์ง€ ํšŒ์ „ํ•˜๊ธฐ : 90๋„ ํšŒ์ „
rotated = tf.image.rot90(image)
visualize(image, rotated)


๋ฐ์ดํ„ฐ์„ธํŠธ์— ์ฆ๊ฐ• ์ ์šฉํ•˜๊ธฐ

Dataset.map ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์ฆ๊ฐ•์„ ๋ฐ์ดํ„ฐ์„ธํŠธ์— ์ ์šฉ

def resize_and_rescale(image, label):
  image = tf.cast(image, tf.float32)
  image = tf.image.resize(image, [IMG_SIZE, IMG_SIZE])
  image = (image / 255.0)
  return image, label
  
  
def augment(image,label):
  image, label = resize_and_rescale(image, label)
  # Add 6 pixels of padding
  image = tf.image.resize_with_crop_or_pad(image, IMG_SIZE + 6, IMG_SIZE + 6) 
   # Random crop back to the original size
  image = tf.image.random_crop(image, size=[IMG_SIZE, IMG_SIZE, 3])
  image = tf.image.random_brightness(image, max_delta=0.5) # Random brightness
  image = tf.clip_by_value(image, 0, 1)
  return image, label
  
  
### ๋ฐ์ดํ„ฐ์„ธํŠธ ๊ตฌ์„ฑ
train_ds = (
    train_ds
    .shuffle(1000)
    .map(augment, num_parallel_calls=AUTOTUNE)
    .batch(batch_size)
    .prefetch(AUTOTUNE)
) 

val_ds = (
    val_ds
    .map(resize_and_rescale, num_parallel_calls=AUTOTUNE)
    .batch(batch_size)
    .prefetch(AUTOTUNE)
)

test_ds = (
    test_ds
    .map(resize_and_rescale, num_parallel_calls=AUTOTUNE)
    .batch(batch_size)
    .prefetch(AUTOTUNE)
)



3. ๊ฐ์ฒด ์ธ์‹ (Object Recognition)

  • ์‚ฌ์ „ ํ•™์Šต(pre-trained)๋œ ์ด๋ฏธ์ง€ ๋ถ„๋ฅ˜ ์‹ ๊ฒฝ๋ง์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์ค‘ ๊ฐ์ฒด ๊ฒ€์ถœํ•˜๊ธฐ
  • Colab ์‹ค์Šต

0๊ฐœ์˜ ๋Œ“๊ธ€