일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- aiffel exploration
- logistic regression
- docker attach
- airflow
- CellPin
- 도커
- Jupyter notebook
- AIFFEL
- 사회조사분석사2급
- IVI
- ssh
- HookNet
- cs231n
- GIT
- 히비스서커스
- docker
- 코크리
- Pull Request
- 프로그래머스
- docker exec
- Decision Boundary
- vscode
- cocre
- Multi-Resolution Networks for Semantic Segmentation in Whole Slide Images
- WSSS
- numpy
- 기초확률론
- 티스토리챌린지
- 오블완
- 백신후원
- Today
- Total
히비스서커스의 블로그
[Numpy] numpy로 이미지 처리하기 2 본문
binary semantic segmentation을 keras framework로 이미지 처리를 numpy로 진행할 시 마주친 여러 문제들을 정리해보았다. 개인적인 견해와 상황이므로 정확하지 않을 수 있으니 참고만 해주길 바란다.
keras semantic segmentation 시 generator에서 주의해야 할 사항
먼저 이미지 데이터 타입으로 unit8, uint16, uint32, float32 등 여러 가지 타입이 존재하지만 가장 많이 쓰는 것은 unit8 (min=0, max=255)과 float32(8bit의 지수, 23bit의 소수)인 듯 하다. 주어진 이미지와 마스크는 데이터 타입이 uint8이었다. 또한, binary segmentation을 시도하는 중이었기에 mask의 최대값은 1이었다.
1. numpy 데이터 타입을 float 32로 해줄 것
2. 이미지 데이터는 255로 나누어줄 것
class generator(keras.utils.Sequence):
def __init__(self, batch_size, img_size, zip_path_list, is_train):
self.batch_size = batch_size
self.img_size = img_size
self.zip_path_list = zip_path_list
self.augment = train_aug() if is_train == True else test_aug()
def __len__(self):
return len(self.zip_path_list) // self.batch_size
def __getitem__(self, idx):
i = idx * self.batch_size
batch_patch_pairs = self.zip_path_list[i : i + self.batch_size]
batch_x = np.zeros((self.batch_size,) + self.img_size + (3,), dtype='float32')
batch_y = np.zeros((self.batch_size,) + self.img_size + (1,), dtype='float32')
for j, path in enumerate(batch_patch_pairs):
img_path = path[0]
mask_path = path[1]
batch_x[j] = cv2.imread(img_path)
batch_y[j] = np.expand_dims(cv2.imread(mask_path, 0),2)
batch_aug = self.augment(image=batch_x[j], mask=batch_y[j])
batch_x[j] = batch_aug['image']/255
batch_y[j] = batch_aug['mask']
return batch_x, batch_y
먼저 dtype=float32로 해주어야 하는 이유는 keras의 segmentation model을 쓰기 위해서는 데이터 타입이 float32이어야 한다. uint8로 그대로 해주었을 경우 에러가 발생하였다.
이미지 데이터를 255로 나누어주는 이유는 데이터 자체를 matplotlib.pyplot에서 불러올 때 imshow에서 바로 볼 수 있게 하기 위함이다.
loss function이 negative로 나오는 경우
loss function을 분명 양의 값만을 가질 수 밖에 없는 diceloss와 binarycrossentropy를 사용하였음에도 불구하고 에러가 음의 값을 가진 경우가 나오게 되었다. 이유를 찾아보니 mask의 값이 0에서 1의 값을 가지는지 다시 확인을 해보라고 stackoverflow에 나와있었다.
따라서, 이때 다시 점검해봐야할 사항은 데이터와 이미지 generator를 거치고 나온 데이터 두 가지이다.
데이터 점검
데이터에서 이미지와 마스크의 값을 다시 한 번 점검해보아야 한다.
이때 주로 점검할 때 유용한 방법은 먼저 shape과 dtype 한번 더 살펴보고 numpy의 값들을 딕셔너리로 변환하여 값을 카운트 해보는 것이다.
import numpy as np
import glob
import cv2
mask_path_list = sorted(glob.glob('mask_path/*.png')) # mask path를 변경
for mask_path in mask_path_list:
mask = cv2.imread(mask_path)
print(f'mask_path : {mask_path}')
print(f'mask shape : {mask.shape}, mask dtype : {mask.dtype}')
unique, counts = np.unique(cv2.imread(mask_path, 0), return_counts = True)
uniq_cnt_dict = dict(zip(unique, counts))
print(f'mask element count : {uniq_cnt_dict}', '\n')
generator 나온 데이터 점검
generator를 거치며 __getitem__에서 새로운 numpy 배열을 만들고 기존의 값을 삽입하는데 이 과정에서 데이터의 값이 달라질 수 있다. 이를 유념하여 generator를 거친 후 만들어진 데이터를 __getitem__으로 몇 개만 가져와서 위와 동일한 작업을 해주면 이상이 있는지 확인하면 용이하다.
# BATCH_SIZE, INPUT_SHAPE, TRAIN_ZIP은 미리 설정해줄 것
train_gen = generator(BATCH_SIZE, INPUT_SHAPE, TRAIN_ZIP, is_train=True)
batch_x, batch_y = train_gen.__getitem__(0)
for idx in range(0, 4):
print('mask shape : ', batch_y[idx].shape, 'mask dtype : ', batch_y[idx].dtype)
unique, counts = np.unique(batch_y[idx], return_counts = True)
uniq_cnt_dict = dict(zip(unique, counts))
print(f'mask element count : {uniq_cnt_dict}', '\n')
이와 같이 점검을 통해 이미지, 마스크 numpy의 shape과 dtype, 그리고 내부 원소들의 값들을 확인하여 에러가 발생할 만한 요소가 있는지 확인하고 수정해주면 해결이 될 것이다.
-히비스서커스-
'Programming > Python' 카테고리의 다른 글
[Python] python으로 xml파일 parsing 및 저장 (feat. findall) (0) | 2021.10.05 |
---|---|
[Numpy] numpy로 이미지 처리하기 3 (2) | 2021.09.09 |
[Python] 한 줄 코드 및 GPU 분산처리 코드 (0) | 2021.08.26 |
[Numpy] numpy로 이미지 처리하기 (2) | 2021.06.30 |
[Python] python으로 multiprocessing 해보기 (2) | 2021.06.30 |