[Day 59-62] 이미지 전처리

임종우·2022년 12월 8일
0

ai_school_TIL

목록 보기
34/34

12.05 ~ 12.07.
CNN에 대해서도 배웠지만, 이미지 전처리도 배웠다. 이 역시 아주 중요한 것 같다.


이미지 전처리

CNN에서 이미지 데이터에 대한 분류 예측 문제를 다루어보았다.
이때, 이미지 데이터에도 전처리가 필요하다.

이미지 데이터의 전처리 과정은 상당히 다양한 라이브러리와 함수를 이용해 진행할 수 있다.

가장 중요한 과정들을 개략적으로 살펴보자면,
1. 이미지 데이터 읽어오기
2. 이미지 사이즈 조절 및 색상 조절, 스케일링
3. 이미지 증강 및 전처리
4. 데이터셋 만들기

로 요약할 수 있을 것 같다.

해당 과정들을 함수로 직접 만들어 진행해보기도 했지만, tf.keras의 기능들을 사용하면 손쉽게 진행할 수도 있었다.
cv2나 PIL을 이용해 이미지를 읽고, 사이즈 및 색상을 조절한 후
ImageDataGenerator를 통해 이미지 증강 및 데이터셋 만들기 작업을 한 번에 처리할 수 있었다.


이미지 읽어오기 및 기본 처리

matplotlib.pyplot

  • plt.imread()
    이미지 파일을 이미지로 읽어온다.

  • plt.imshow()
    읽어온 이미지를 출력한다.
    이때, 이미지의 구성요소에 대해 기억해보면 [height, width, channel]이었다.
    따라서 img[0:0:1]등의 방법으로 1번 인덱스(R) 채널의 이미지만 읽어올 수도 있다.

PIL

-> from PIL import Image

  • PIL.Image.open
    image 파일을 읽어들인다.

  • .size
    이미지 파일의 사이즈를 확인한다.

  • .resize()
    이미지 파일의 사이즈를 변경한다.

  • .save()
    이미지 파일을 저장한다.

OpenCV

  • img = cv2.imread()
    cv2에서 imread로 읽어온 이미지는, PIL에서 읽어온 것과 다르게 array 형태이다.
    따라서 이미지를 출력해주기 위해서는 plt.imshow()를 사용한다.
    또한, nparray형태이므로, 슬라이싱으로 반만 읽어와서 절반으로 잘린 형태의 이미지를 출력하는 것도 가능하다.

  • cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    OpenCV의 경우, 컬러 채널이 RGB가 아닌 BGR의 형태를 취하고 있다.
    따라서 이미지를 RGB 형태로 다뤄주기 위해서는, cvtColor를 통해 cv2.COLOR_BGR2RGB를 적용해주어야 한다.

  • cv2.imread(img, cv2.IMREAD_~~~~)
    다양한 옵션을 주면서 이미지를 읽어올 수 있다.
    IMREAD_UNCHANGED
    IMREAD_GRAYSCALE
    등이 존재한다.

  • cv2.resize()
    역시 이미지의 사이즈를 조절할 수 있다.

tf.keras.layers.Rescaling

  • tf.keras.layers.Rescaling
    값을 정규화 할 수 있다.

다음과 같이 사용한다.

normalization_layer = layers.Rescaling(1./255)

이렇게 레이어로 만들어준 후 모델의 입력층에 추가하면 된다.
혹은 map함수를 사용하여 적용할 수도 있다.


이미지 증강

PIL

-> from PIL import ImageFilter

  • img.filter()
    이렇게 사용하는데, 그 안에 들어가는 인자가 ImageFilter의 모듈이다.
    - ImageFilter.BLUR : 흐리게 만든다.
    - ImageFilter.GaussianBlur : 가우시안 필터를 통해 흐리게 만든다. (픽셀의 거리에 따라 가중치를 두어 계산하는 방식)
    - ImageFilter.CONTOUR : 등고선을 추출한다.
    - ImageFilter.EMBOSS : EMBOSS 효과를 적용한다.

OpenCV

  • cv2.blur()
    이미지를 흐리게 만든다.

  • cv2.adaptiveThreshold()
    이미지의 임계값을 특정 임계값을 기준으로 크고 작은 값으로 구분하여 이진화한다.
    adaptiveThreshold는 적응적 이진화 이므로, 이 임계값이 주변 픽셀의 강도에 의해 결정된다.

tf.keras.layers

  • layers.RandomFlip()
    학습과정에서 이미지를 상하 혹은 좌우 반전시킨다.
  • layers.RandomRotation()
    학습 과정에서 랜덤으로 이미지를 선택하여 회전시킨다.
  • layers.RandomZoom()
    학습 과정에서 랜덤으로 이미지를 선택하여 확대 혹은 축소한다.

-> 해당 레이어들을 모델 내부에 포함시킨 후 학습을 진행하면 이미지 증강의 효과를 얻을 수 있다.


파이프라인

이제는 해당 기능들 혹은 다른 기능들을 한번에 수행할 수 있는 파이프라인 같은 역할을 하는 함수들을 살펴보자.

image_dataset_from_directory

  • tf.keras.utils.image_dataset_from_directory링크
    -> 디렉토리 경로를 주면 해당 디렉토리 안의 이미지 파일들을 dataset 형식으로 만들어준다. image_size를 지정해줄 수도 있고, validation_set을 나누어주는 기능도 제공한다.
  • 다만 이미지 증강 기능을 수행할 수 없는 것 같다!
  • 사용예제
train_ds = tf.keras.utils.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="training",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)
  
val_ds = tf.keras.utils.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="validation",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)
  • subset
    Subset of the data to return. One of "training", "validation" or "both". Only used if validation_split is set. When subset="both", the utility returns a tuple of two datasets (the training and validation datasets respectively).

이렇게 나누어진 데이터셋에 .class_names 를 통하여 class의 종류를 확인할 수 있다.

음... flow_from_directory 랑 비슷한 역할인 것 같은데?

ImageDataGenerator

  • from tensorflow.keras.preprocessing.image import ImageDataGenerator
    특정 경로에 있는 이미지들을 데이터셋으로 만들어주는 generator를 생성해준다.

이미지를 데이터셋으로 만들어 주는 것이 아닌, generator를 생성해주는 함수이다! 다양한 이미지 증강을 적용하여 이미지들을 데이터셋으로 만들어주는 generator를 생성한다.

그리고 이거랑 flow_from_directory랑도 많이 헷갈렸는데, ImageDataGenerator로 만든 generator에서, flow_from_directory를 사용해서 데이터셋을 만드는 것이다!

사용예시

# ImageDataGenerator 를 통해 이미지를 로드하고 전처리 합니다.
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# validation_split 값을 통해 학습:검증 비율을 8:2 로 나눕니다.
datagen = ImageDataGenerator(rescale=1/255.0, validation_split=0.2)
datagen

인자

  • 이미지의 조정 및 증강에 관련한 다양한 인자를 넣어줄 수 있다.
  • rescale
  • horizontal_flip : 좌우반전
  • vertical_flip : 상하반전
  • rotation_range : 회전
  • zoom_range : 확대 혹은 축소
  • width_shift_range, height_shift_range : 이동
  • shear_range : 눕히기
  • brightness_range(min, max) : 밝기 조절
  • channel_shift_range : RGB 픽셀 값을 변경

-> ImageDataGenerator를 통해 데이터를 만들 때, 해당 인자들을 포함하여 이미지 증강을 수행할 수 있다.

  • validation_split 값을 넣어주어, 이미지 데이터를 생성할때 validation set의 비율을 어느정도로 할지 결정할 수 있다.

flow_from_directory

ImageDataGenerator의 메소드로, 이미지를 특정 경로에서 불러와서 numpy array로 만들어주는 함수이다.
Generator에서 해당 메소드를 사용하면 특정 경로에 있는 이미지들을 통해 증강된 데이터들의 batches를 생성한다.

아까 위에서 살펴본 image_dataset_from_directory와 비슷하다.

사용예시

# flow_from_directory 를 통해 이미지를 불러옵니다.
# training 데이터셋을 생성합니다.
# class_mode 에는 이진분류이기 때문에 binary 를 넣어줍니다.
trainDatagen = datagen.flow_from_directory(directory = 'cell_images/',
                                           target_size = (height, width),
                                           class_mode = 'binary',
                                           batch_size = 64,
                                           subset='training')

포함되는 인자로는 다음이 있다.

  • directory : 이미지파일이 위치하는 경로
  • target_size : 이미지 파일을 어떤 사이즈로 만들 것인지
  • class_mode : One of "categorical", "binary", "sparse", "input", or None. Default: "categorical".
  • batch_size : Size of the batches of data (default: 32).

이렇게 만든 데이터셋에서는 다음을 확인할 수 있다.

  • .num_classes
  • .classes
  • .class_indices

기타

os

  • os.walk
    해당 디렉토리 아래에 있는 디렉토리와 파일들의 이름을 모두 반환하는 generator를 생성한다.

사용예제

import os
for dirpath, dirnames, filenames in os.walk('cell_images/'):
    print(dirpath, dirnames)
  • os.listdir()
    해당 경로에 있는 모든 파일과 폴더명 리스트를 반환한다.

참고자료

profile
ai school 기간 동안의 TIL!

0개의 댓글