이전에 구현했던 한식 분류 모델을 Dash를 이용해 간단하게 웹 사이트로 구현했다. 뿐만 아니라 구현한 웹 사이트를 AWS를 이용해 배포까지 완료했다.
가능한 심플하게 만들어 봤는데 디잔인에 소질이 없어서... 그래도 코딩을 시작할 때 웹 디자인으로 시작을 해서 Dash로 제작할 때 매우 어렵지는 않았다. 핸드폰으로 가능하다...
배포까지 완료가 됐지만 예측 결과에서 차이가 발생했다.
Kaggle을 이용해서 학습을 할 때 한식 이미지 데이터셋을 Kaggle에 업로드를 하고 위치를 데이터프레임 형식으로 처리를 했다. 마찬가지로 직접 수집한 예측용 이미지 72장 역시 Kaggle에 업로드를 하고 위치를 데이터프레임 형식으로 처리해 예측을 했었다. 따라서 아래의 코드를 이용해서 학습을 진행했다. 데이터프레임에서 배치 사이즈만큼 이미지 위치를 가져와서 cv2로 이미지를 읽는다. 또한, GPU를 이용한 환경에서 진행을 했었다.
BATCH_SIZE = 32
IMAGE_SIZE = 300
class Food_Dataset(Sequence):
def __init__(self, image_filenames, labels, batch_size=BATCH_SIZE, augmentor=None, shuffle=False, pre_func=None):
self.image_filenames = image_filenames
self.labels = labels
self.batch_size = batch_size
self.augmentor = augmentor
self.pre_func = pre_func
self.shuffle = shuffle
if self.shuffle:
pass
def __len__(self):
return int(np.ceil(len(self.image_filenames)/BATCH_SIZE))
def __getitem__(self, index):
image_name_batch = self.image_filenames[index * self.batch_size:(index + 1) * self.batch_size]
if self.labels is not None:
label_batch = self.labels[index * self.batch_size:(index + 1) * self.batch_size]
image_batch = np.zeros((image_name_batch.shape[0], IMAGE_SIZE, IMAGE_SIZE, 3), dtype='float32')
for image_index in range(image_name_batch.shape[0]):
image = cv2.imread(image_name_batch[image_index])
if image is None:
# print(f"이미지 오류: {image_name_batch[image_index]}")
continue
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = cv2.resize(image, (IMAGE_SIZE, IMAGE_SIZE))
if self.augmentor is not None:
image = self.augmentor(image=image)['image']
if self.pre_func is not None:
image = self.pre_func(image)
image_batch[image_index] = image
if self.labels is None:
return image_batch
else:
return image_batch, label_batch
def on_epoch_end(self):
if(self.shuffle):
self.image_filenames, self.labels = sklearn.utils.shuffle(self.image_filenames, self.labels)
else:
pass
하지만 배포를 위해 제작한 코드에서는 사진을 db에 저장을 하고 가져오는 것이 아닌 서버에 임시로 저장하고 그 이미지를 메모리 상에서 처리하는 방식이다. 따라서 위의 코드가 아닌 아래의 코드를 이용해서 처리를 한다. 뿐만 아니라 GPU가 아닌 CPU로 처리를 하기 때문에 속도 측면에서만 아닌 성능에서도 차이가 분명하게 있는 것 같다.
즉, 이미지 전처리, 속도, 성능 부분에서 많은 차이가 있다.
def preprocess_images(contents):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
np_array = np.frombuffer(decoded, np.uint8)
image = cv2.imdecode(np_array, cv2.IMREAD_COLOR)
image = cv2.resize(image, (IMAGE_SIZE, IMAGE_SIZE))
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = preprocessing_func(image)
return np.expand_dims(image, axis=0)
현재는 배포까지는 완료한 상황이다. 이후 사진을 DB에 저장하는 방식을 이용해 전체적으로 수정을 해볼 생각이다. 단, GPU를 이용하는 방법은 현재까지는 어렵다고 보고있다.
현재 상황
Kaggle에서 72장 처리 11초
로컬에서 72장 처리 76초
배포 환경에서 1장 처리 12~15초가 걸리고 있다.
속도에서의 차이가 가장 크게 느껴지며, 성능에 있어서는 제육볶음 -> 불고기, 파김치 -> 부추김치 이처럼 비슷하게 생긴 음식에 있어서 비슷한 음식으로 예측을 한다.