12.05 ~ 12.07.
CNN에 대해서도 배웠지만, 이미지 전처리도 배웠다. 이 역시 아주 중요한 것 같다.
CNN에서 이미지 데이터에 대한 분류 예측 문제를 다루어보았다.
이때, 이미지 데이터에도 전처리가 필요하다.
이미지 데이터의 전처리 과정은 상당히 다양한 라이브러리와 함수를 이용해 진행할 수 있다.
가장 중요한 과정들을 개략적으로 살펴보자면,
1. 이미지 데이터 읽어오기
2. 이미지 사이즈 조절 및 색상 조절, 스케일링
3. 이미지 증강 및 전처리
4. 데이터셋 만들기
로 요약할 수 있을 것 같다.
해당 과정들을 함수로 직접 만들어 진행해보기도 했지만, tf.keras의 기능들을 사용하면 손쉽게 진행할 수도 있었다.
cv2나 PIL을 이용해 이미지를 읽고, 사이즈 및 색상을 조절한 후
ImageDataGenerator를 통해 이미지 증강 및 데이터셋 만들기 작업을 한 번에 처리할 수 있었다.
plt.imread()
이미지 파일을 이미지로 읽어온다.
plt.imshow()
읽어온 이미지를 출력한다.
이때, 이미지의 구성요소에 대해 기억해보면 [height, width, channel]이었다.
따라서 img[0:0:1]등의 방법으로 1번 인덱스(R) 채널의 이미지만 읽어올 수도 있다.
-> from PIL import Image
PIL.Image.open
image 파일을 읽어들인다.
.size
이미지 파일의 사이즈를 확인한다.
.resize()
이미지 파일의 사이즈를 변경한다.
.save()
이미지 파일을 저장한다.
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
다음과 같이 사용한다.
normalization_layer = layers.Rescaling(1./255)
이렇게 레이어로 만들어준 후 모델의 입력층에 추가하면 된다.
혹은 map함수를 사용하여 적용할 수도 있다.
-> from PIL import ImageFilter
img.filter()
ImageFilter.BLUR
: 흐리게 만든다.ImageFilter.GaussianBlur
: 가우시안 필터를 통해 흐리게 만든다. (픽셀의 거리에 따라 가중치를 두어 계산하는 방식)ImageFilter.CONTOUR
: 등고선을 추출한다.ImageFilter.EMBOSS
: EMBOSS 효과를 적용한다.cv2.blur()
이미지를 흐리게 만든다.
cv2.adaptiveThreshold()
이미지의 임계값을 특정 임계값을 기준으로 크고 작은 값으로 구분하여 이진화한다.
adaptiveThreshold는 적응적 이진화 이므로, 이 임계값이 주변 픽셀의 강도에 의해 결정된다.
layers.RandomFlip()
layers.RandomRotation()
layers.RandomZoom()
-> 해당 레이어들을 모델 내부에 포함시킨 후 학습을 진행하면 이미지 증강의 효과를 얻을 수 있다.
이제는 해당 기능들 혹은 다른 기능들을 한번에 수행할 수 있는 파이프라인 같은 역할을 하는 함수들을 살펴보자.
tf.keras.utils.image_dataset_from_directory
링크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)
이렇게 나누어진 데이터셋에 .class_names
를 통하여 class의 종류를 확인할 수 있다.
음... flow_from_directory 랑 비슷한 역할인 것 같은데?
from tensorflow.keras.preprocessing.image import ImageDataGenerator
이미지를 데이터셋으로 만들어 주는 것이 아닌, 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
인자
-> ImageDataGenerator를 통해 데이터를 만들 때, 해당 인자들을 포함하여 이미지 증강을 수행할 수 있다.
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')
포함되는 인자로는 다음이 있다.
이렇게 만든 데이터셋에서는 다음을 확인할 수 있다.
.num_classes
.classes
.class_indices
os.walk
사용예제
import os
for dirpath, dirnames, filenames in os.walk('cell_images/'):
print(dirpath, dirnames)
os.listdir()
참고자료