이미지 task에서 Data augmentation은 성능 향상에 큰 도움을 줄 수 있다.
따라서 기존에도 Keras의 ImageDataGenerator을 사용하여 간단한 방법으로 이미지를 증강시켰다.
하지만 이 방법은 모델 학습, 평가 시마다 이미지를 읽어와 원하는 size에 맞추어 resize를 한 다음에 진행하기에 이미지의 크기가 클 때 시간이 오래 걸린다.
이를 방지하기 위하여 이미지를 resize하여 다시 저장한 다음 추가적인 이미지 처리 라이브러리를 이용하여 증강시켜야 한다.
프로젝트를 진행하며 여기까지는 생각이 닿았는데 라벨 폴더 별로 나누어진 이미지를 resize하여 다시 라벨 값에 맞추어 분류하는 법은 따로 알지 못했고 잘 정리된 코드 역시 없었기에 직접 구현하여 코드를 공유한다.
OpenCV를 이용하여 라벨 폴더별로 데이터 가져오기
먼저 필요한 라이브러리를 import 한다.
가져올 데이터는 아래의 폴더에 저장되어 있다.
os.path.join()을 이용하여 이미지 폴더 경로를 지정하여 주었다.
폴더 별로 상위 4개의 이미지를 확인한 결과 라벨 분류가 제대로 된 걸 알 수 있다.(사실 보기엔 전부 비슷해 보이긴 하다.)
폴더별로 이미지를 가져와 넘파이 배열로 만들기
지정된 경로에서 이미지가 잘 받아와 지는 걸 확인했으므로 이를 전부 받아와 하나의 넘파이 배열로 만들면 된다.
이때 주의할 점으로 이미지 하나를 받아올 때마다 사이즈를 바꿔서 저장해서 기존 이미지에서 resize된 이미지를 가져와야 한다. 또한 openCV를 사용하는 경우 BGR채널로 가져오게 되는데 이를 보기 좋게 RGB로 바꾸어 주는 것이 좋다.
기존의 이미지에서 (60, 60)의 크기로 일관된 사이즈의 넘파이 배열로 가져온 다음 저장하였다.
file = joblib.load("파일경로")
저장된 pkl 파일은 위 코드와 같은 방식으로 가져올 수 있다.
이미지를 랜덤하게 16개 그려본 결과 큰 문제없이 reize되었다는걸 확인할 수 있다.
Keras 역시 채널 변환이 없다는 점을 제외하면 OpenCV와 큰 차이가 없다.
전체 코드
import os
import numpy as np
import matplotlib.pyplot as plt
import tensorflow.keras as keras
import cv2
import joblib
path="D:\Image_data"
labels = os.listdir(path)
labels
['0_', '1_', '2_', '3_']
img_0_path = os.path.join(path, labels[0])
img_1_path = os.path.join(path, labels[1])
img_2_path = os.path.join(path, labels[2])
img_3_path = os.path.join(path, labels[3])
fig = plt.figure(figsize=(14, 10))
for i in range(1, 17, 4):
image = cv2.imread(os.path.join(img_0_path, os.listdir(img_0_path)[i]))
image_1 = cv2.imread(os.path.join(img_1_path, os.listdir(img_1_path)[i]))
image_2 = cv2.imread(os.path.join(img_2_path, os.listdir(img_2_path)[i]))
image_3 = cv2.imread(os.path.join(img_3_path, os.listdir(img_3_path)[i]))
ax = plt.subplot(4, 4, i)
ax.axes.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)
plt.imshow(image)
plt.title("Class 0")
ax = plt.subplot(4, 4, i+1)
ax.axes.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)
plt.imshow(image_1)
plt.title("Class 1")
ax = plt.subplot(4, 4, i+2)
ax.axes.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)
plt.imshow(image_2)
plt.title("Class 2")
ax = plt.subplot(4, 4, i+3)
ax.axes.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)
plt.imshow(image_3)
plt.title("Class 3")
OpenCV(4.5.1) ..\modules\core\src\alloc.cpp:73: error: (-4:Insufficient memory) Failed to allocate 36578304 bytes in function 'cv::OutOfMemoryError'
폴더를 하나씩 돌며 이미지를 읽어보면 원래 픽셀 값(4032, 3024)로 읽어 들일 시 첫 번째 폴더를 읽지 못하고 메모리가 터짐
보간법은 가장 빠른 최근접 이웃을 사용하여(60, 60)size로 만들었으며 데이터 사이즈를 줄이기 위하여 float32로 자료형을 바꾸었다.
또한 openCV는 색깔 채널이 BGR로 들어가 있으므로 이를 RGB순으로 만들어 주었다.
img_list=np.array([])
label_list=[]
for i in os.listdir(path):
print("Progressing...")
for j in os.listdir(os.path.join(path, i)):
img = cv2.imread(os.path.join(path, i, j))
img = cv2.resize(img, (60, 60), interpolation=cv2.INTER_NEAREST)
img = np.float32(img)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = img/255.0
img_list = np.append(img_list, img)
label_list.append(i)
img_list = np.reshape(img_list, (-1, 60, 60, 3))
Progressing...
Progressing...
Progressing...
Progressing...
joblib.dump(img_list, "CV2_60.pkl")
['CV2_60.pkl']
image = joblib.load("./CV2_float32.pkl")
fig = plt.figure(figsize=(14, 10))
for i in range(1, 17):
ax = plt.subplot(4, 4, i)
ax.axes.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)
plt.imshow(image[i])
Keras 역시 openCV와 size와 채널 변환이 없다는 점을 제외하면 큰 차이가 없다.
img_list=np.array([])
label_list=[]
for i in os.listdir(path):
print("Progressing...")
for j in os.listdir(os.path.join(path, i)):
img = keras.utils.load_img(os.path.join(path, i, j), target_size=(32, 32))
img = np.float32(img)
img = img/255.0
img_list = np.append(img_list, img)
label_list.append(i)
img_list = np.reshape(img_list,(-1, 32, 32, 3))
joblib.dump(img_list, "Keras_150.pkl")
깃허브 링크:
https://github.com/hykhhijk/Rock-classifier/blob/master/Image%20load%2C%20resize%2C%20save.ipynb
'Notes' 카테고리의 다른 글
timm 정리 (0) | 2024.08.25 |
---|---|
기존 딥러닝 개발환경 복제하기 (0) | 2024.06.24 |
[Poetry] toml, lock파일 기반 가상환경 설치하기 (0) | 2023.07.24 |
[Poetry] Poetry를 사용해 프로젝트 버전 관리하기 (0) | 2023.05.01 |
Albumentations 라이브러리를 이용하여 데이터 증강하기 (0) | 2022.06.19 |