{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nimport matplotlib.pyplot as plt\n\nfrom tensorflow.keras.layers import Input, Activation, Conv2D, Flatten, Dense, MaxPooling2D, Dropout, Add, LeakyReLU, UpSampling2D\nfrom tensorflow.keras.models import Model, load_model\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau\nfrom tensorflow.keras.utils import Sequence\n\nfrom PIL import TiffImagePlugin\n\nimport openslide\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\n#for dirname, _, filenames in os.walk('/kaggle/input'):\n#    for filename in filenames:\n#        print(os.path.join(dirname, filename))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"#경로가 제대로 된 게 맞는지 리스팅 해보자.\n'''\n참고자료 : https://itholic.github.io/python-listdir-glob/\n'''\n#os.listdir('/kaggle/input/prostate-cancer-grade-assessment/train_images/')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nopenslide 라이브러리를 이용하면 tiff 파일을 열 수 있다.\n'''\n\nexample = openslide.OpenSlide('/kaggle/input/prostate-cancer-grade-assessment/train_images/6d1a11077fe4183a4109d649cf319923.tiff')\npatch = example.read_region((5000,6700), 0 , (256,256))\n\ndisplay(patch)\n\nexample.close()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"example2 = openslide.OpenSlide('/kaggle/input/prostate-cancer-grade-assessment/train_label_masks/002a4db09dad406c85505a00fb6f6144_mask.tiff')\npatch = example2.read_region((5000,6700), 0 , (256,256))\n\ndisplay(patch)\n\nexample2.close()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data = pd.read_csv('../input/prostate-cancer-grade-assessment/train.csv')\ndata","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\n우선 마스크가 있는 데이터만 골라내고자 한다.\n'''\ndata['mask'] = ''\ndata","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nos.path.isfile('파일이름')으로 마스크가 존재하는 데이터인지 체크하자.\n마스크가 있는 데이터는 'yes'로 표기해두고,\n마스크가 없는 데이터는 'no'로 표기해두도록 하자.\n\n참고자료 : \nhttps://stackoverflow.com/questions/38876816/change-value-of-a-dataframe-column-based-on-a-filter\n'''\n\n\nfor im_id in data['image_id']:\n    if os.path.isfile('../input/prostate-cancer-grade-assessment/train_label_masks/' + im_id + '_mask.tiff'):\n        data.loc[data['image_id'] == im_id, 'mask'] = 'yes'\n    else:\n        data.loc[data['image_id'] == im_id, 'mask'] = 'no'\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nmask가 없는 데이터들을 출력한다.\n'''\ndata[data['mask'] =='no']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\n마스크가 없는 데이터를 (row를) 모조리 삭제해주자.\n'''\ndata = data.drop(data[data['mask'] == 'no'].index)\ndata","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\n이미지를 numpy array로 바꾸는 방법은 세 가지가 있다.\n1) PIL의 Image 라이브러리를 사용하는 방법\n2) cv2의 imread를 사용하는 방법\n3) skimage.io의 imread를 사용하는 방법\n\n세 가지를 모두 실행해보니, 3번 방법만 tiff파일을 np array로 바꿀 수 있었다.\n그런데 확실히..파일 하나가 너무나도 크다.\n\n그리고, 이미지마다 shape가 제각각이어서 학습을 어떻게 시켜야 할지도 감이 잘 안온다.\n'''\nimport skimage.io as io\n\nimg = io.imread('/kaggle/input/prostate-cancer-grade-assessment/train_images/6d1a11077fe4183a4109d649cf319923.tiff')\nimg.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img = io.imread('/kaggle/input/prostate-cancer-grade-assessment/train_images/001c62abd11fa4b57bf7a6c603a11bb9.tiff')\nimg.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\n데이터셋을 train set, validation set으로 나눠보자.\nsklearn의 train_test_split을 쓰면 쉽게 진행할 수 있다.\n\n참고자료: \nhttps://blog.naver.com/PostView.nhn?blogId=siniphia&logNo=221396370872&parentCategoryNo=&categoryNo=22&viewDate=&isShowPopularPosts=true&from=search\nhttps://rfriend.tistory.com/519\n'''\nfrom sklearn.model_selection import train_test_split\n\ndata_train, data_val = train_test_split(data, test_size = 0.2, random_state = 1030)\ndata_val, data_test = train_test_split(data_val, test_size=0.2, random_state = 1030)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(data_train.shape)\nprint(data_test.shape)\nprint(data_val.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for data in data_train.head()['image_id']:\n    print(data)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\ntrain set의 각 이미지를 numpy array형태로 바꾸자.\n바꾸고 나면 각 이미지를 256 * 256으로 resize 해보자.\n'''\nimport cv2\nfrom PIL import Image\n\nfig, axs = plt.subplots(1,5, figsize = (100,100))\nit = 0\n\nfor img_id in data_train.tail()['image_id']:\n    img = io.imread('/kaggle/input/prostate-cancer-grade-assessment/train_images/'+ img_id +'.tiff')\n    resized = cv2.resize(img, dsize=(256, 256), interpolation=cv2.INTER_CUBIC)\n    \n    print(resized.shape)\n    \n    \n    \n    axs[it].imshow(resized)\n    it = it+1\n    \n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nQ. 왜 마스크는 아무것도 뜨지 않는가?\nA. 마스크는 WSI(Whole Slide Imaging)같은 이미지가 아니다.\n배열에 0~255의 값을 담는 대신, 0~6의 값만 담는다.\n0~6은 각각 다른 클래스 라벨을 의미한다. (이 데이터셋 description에 상세 정보가 나와 있다.)\n그렇기 때문에 mask를 시각화 하는 시도를 하더라도 거의 0에 가까운 숫자들만 있기 때문에\n아주 어둡게 나타나게 된다.\ncolor map을 쓰면 이런 이슈를 해결할 수 있다.\n0~6까지 각각 다른 color을 할당해주자.\n\n★★ imshow 함수를 쓸 때 colormap이 먹히도록 만들려면\n이미지를 nparray로 만들어줘야 한다.\nnp.asarray(이미지변수명)[:, :, 0]\n그런데 맨 뒷 대괄호 안의 내용의 의미는 뭐지?\n참고자료 : https://www.kaggle.com/tanulsingh077/prostate-cancer-in-depth-understanding-eda-model\n\n'''\nimport cv2\nfrom PIL import Image\nimport matplotlib\n\nfig, axs = plt.subplots(1,5, figsize = (200,200))\nit = 0\n\nfor img_id in data_train.tail()['image_id']:\n    img = io.imread('/kaggle/input/prostate-cancer-grade-assessment/train_label_masks/'+ img_id +'_mask.tiff')\n    resized = cv2.resize(img, dsize=(256, 256), interpolation=cv2.INTER_CUBIC)\n    \n    print(resized.shape)\n    \n    cmap = matplotlib.colors.ListedColormap(['black', 'gray', 'green', 'yellow', 'orange', 'red'])\n    \n    axs[it].imshow(np.asarray(resized)[:,:,0], cmap = cmap, interpolation='nearest', vmin=0, vmax=5)\n    it = it+1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"os.makedirs('./train_img')\nos.makedirs('./train_mask')\nos.makedirs('./val_img')\nos.makedirs('./val_mask')\nos.makedirs('./test_img')\nos.makedirs('./test_mask')\nos.listdir('./')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from tqdm.notebook import tqdm\n\n'''\n지금까지 진행한 바는 다음과 같다.\n1. 원본 이미지와 마스크 이미지를 numpy array화 시키기\n2. 원본 이미지와 마스크 이미지를 256*256*3으로 resizing하기\n3. 마스크 이미지에 colormap 입히기\n4. 변환시킨 원본 이미지와 마스크 이미지를 출력하기\n\n5. 데이터셋을 train_set과 validation_set으로 나누기\n\n이제 mask가 존재하는 모든 데이터에 대하여 데이터셋을 numpy array화 해서 저장하도록 하자.\n다음과 같은 규칙으로 데이터셋을 만들기로 한다.\n\nx : resizing한 원본 데이터\ny : resizing한 마스크 데이터\n\nx_train, y_train, x_test, y_test를 만들도록 한다.\n\n\n이미지 데이터셋을 numpy array화 하는 방법은 다음과 같다.\n1. 일반 empty 배열을 만든다.\n2. 각 이미지를 numpy array화 시킨다. (예를들어 cv2.imread나 cv2.resize를 사용하는 등)\n3. 해당 이미지를 배열에 append한다.\n4. np.array(배열 이름)이 곧 데이터셋의 numpy array이다.\n\n그런데... 이렇게 해줬더니 메모리 초과되어버린다.\n데이터 용량이 크다보니 한 번에 로드하면 메모리가 버티지 못하는 것이다.\n\n그렇기 때문에 train 데이터 전체를 numpy 파일 하나로 묶어서 처리하기보다는\ntrain 데이터 하나당 numpy 파일 하나로 만들어서 처리하는 것이 더 합리적이다.\n\n[참고사항]\nskimage.io.imread보다\nskimage.io.MultiImage가 더 빠르다. (훨씬 훨씬)\n'''\ni = 0\n\nfor img_id in tqdm(data_train['image_id']):\n    #img = io.imread('/kaggle/input/prostate-cancer-grade-assessment/train_images/'+ img_id +'.tiff')\n    #resized = cv2.resize(img, dsize=(256, 256), interpolation=cv2.INTER_CUBIC)\n    img = io.MultiImage('/kaggle/input/prostate-cancer-grade-assessment/train_images/'+ img_id +'.tiff')\n    resized = cv2.resize(img[-1], (256,256), interpolation=cv2.INTER_CUBIC)\n    \n    #mask = io.imread('/kaggle/input/prostate-cancer-grade-assessment/train_label_masks/'+ img_id +'_mask.tiff')\n    #resized_mask = cv2.resize(mask, dsize=(256, 256), interpolation=cv2.INTER_CUBIC)\n    \n    \n    np.save('./train_img/' + str(i) + '.npy', resized)\n    #np.save('./train_mask/' + str(i) + '.npy', resized_mask)\n    \n    i = i+1\nprint(\"done!\")\n    \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\n같은 방법으로 mask데이터도 저장해보자.\n'''\n\ni = 0\n\nfor img_id in tqdm(data_train['image_id']):\n    mask = io.MultiImage('/kaggle/input/prostate-cancer-grade-assessment/train_label_masks/'+ img_id +'_mask.tiff')\n    resized_mask = cv2.resize(mask[-1], dsize=(256, 256), interpolation=cv2.INTER_CUBIC)\n    \n    \n    np.save('./train_mask/' + str(i) + '.npy', resized_mask)\n    \n    i = i+1\nprint(\"done!\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"i = 0\n\nfor img_id in tqdm(data_val['image_id']):\n    img = io.MultiImage('/kaggle/input/prostate-cancer-grade-assessment/train_images/'+ img_id +'.tiff')\n    resized= cv2.resize(img[-1], dsize=(256, 256), interpolation=cv2.INTER_CUBIC)\n    \n    \n    np.save('./val_img/' + str(i) + '.npy', resized)\n    \n    i = i+1\nprint(\"done!\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"i = 0\n\nfor img_id in tqdm(data_val['image_id']):\n    mask = io.MultiImage('/kaggle/input/prostate-cancer-grade-assessment/train_label_masks/'+ img_id +'_mask.tiff')\n    resized_mask = cv2.resize(mask[-1], dsize=(256, 256), interpolation=cv2.INTER_CUBIC)\n    \n    \n    np.save('./val_mask/' + str(i) + '.npy', resized_mask)\n    \n    i = i+1\nprint(\"done!\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"i = 0\n\nfor img_id in tqdm(data_test['image_id']):\n    img = io.MultiImage('/kaggle/input/prostate-cancer-grade-assessment/train_images/'+ img_id +'.tiff')\n    resized= cv2.resize(img[-1], dsize=(256, 256), interpolation=cv2.INTER_CUBIC)\n    \n    \n    np.save('./test_img/' + str(i) + '.npy', resized)\n    \n    i = i+1\nprint(\"done!\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"i = 0\n\nfor img_id in tqdm(data_test['image_id']):\n    mask = io.MultiImage('/kaggle/input/prostate-cancer-grade-assessment/train_label_masks/'+ img_id +'_mask.tiff')\n    resized_mask = cv2.resize(mask[-1], dsize=(256, 256), interpolation=cv2.INTER_CUBIC)\n    \n    \n    np.save('./test_mask/' + str(i) + '.npy', resized_mask)\n    \n    i = i+1\nprint(\"done!\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nhoh = np.load('./train_img/799.npy')\n\nfig, axs = plt.subplots(1,5, figsize = (200,200))\n\naxs[0].imshow(hoh)\n#hoh = cv2.imread('./train_mask/799.npy')\n\n#print(hoh)\n'''\nos.listdir('./')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mask = ''\nresized_mask = ''\nimg = ''\nresized = ''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nnumpy 형태로 저장한 데이터를 넣을 수 있게\ndatagenerator을 디자인해보자.\n\n참고자료 : https://sunshower76.github.io/frameworks/2020/02/09/Keras-Batch%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B01-(Seuquence&fit_generator)/\n'''\n\nclass DataGenerator(Sequence):\n    def __init__(self, list_IDs, imgs_dir, masks_dir, batch_size = 10, img_size = 256, n_channels=3, n_classes=1, shuffle=True):\n        self.list_IDs = list_IDs\n        #인덱스는 __get_item__ 함수에서 쓰이므로 만들어놔야 한다.\n        #np.arange(3)은 array([0,1,2])이다. 즉, 아래 코드는 array용 index를 만들어주는 것.\n        self.indexes = np.arange(len(self.list_IDs))\n        self.imgs_dir = imgs_dir\n        self.masks_dir = masks_dir\n        self.batch_size = batch_size\n        self.img_size = img_size\n        self.n_channels = n_channels\n        self.n_classes = n_classes\n        self.shuffle = shuffle\n        self.on_epoch_end()\n    def __len__(self):\n        return int(np.floor(len(self.list_IDs) / self.batch_size))\n    def __getitem__(self, index):\n        #batch용 index들을 만들어준다.\n        indexes = self.indexes[index * self.batch_size:(index + 1) * self.batch_size]\n        batch_ids = [self.list_IDs[k] for k in indexes]\n        \n        imgs = list()\n        masks = list()\n        \n        for id_name in batch_ids:\n            img, mask = self.__data_generation(id_name)\n            imgs.append(img)\n            masks.append(mask)\n            \n        imgs = np.array(imgs)\n        masks = np.array(masks)\n        \n        return imgs, masks\n        \n    def on_epoch_end(self):\n        self.indexes = np.arange(len(self.list_IDs))\n        if self.shuffle == True:\n            np.random.shuffle(self.indexes)\n    def __data_generation(self, id_name):\n        img_path = os.path.join(self.imgs_dir, id_name)\n        mask_path = os.path.join(self.masks_dir, id_name)\n        \n        img = np.load(img_path)\n        mask = np.load(mask_path)\n        \n        '''\n        img = img / 255.0\n        mask = mask / 255.0\n        \n        '''\n        \n        return img, mask","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import glob\n#x_train_list = sorted(glob.glob(os.path.join('./train_img', '*.npy')))\n#y_train_list = sorted(glob.glob(os.path.join('./train_mask', '*.npy')))\n'''\ntrain_img 폴더에 포함된 npy파일과\ntrain_mask에 포함된 npy파일 이름은 모두 같다.\n'''\ntrain_id = sorted(os.listdir('./train_img'))\nval_id = sorted(os.listdir('./val_img'))\nprint(train_id[3])\nprint(len(train_id))\nprint(len(val_id))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_gen = DataGenerator(list_IDs=train_id, imgs_dir = './train_img', masks_dir = './train_mask', batch_size = 10, img_size=256)\nval_gen = DataGenerator(list_IDs=val_id, imgs_dir = './val_img', masks_dir = './val_mask', batch_size = 10, img_size=256)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\n모델을 작성하도록 해보자.\n'''\n\ninputs = Input(shape=(256,256,3))\n\nnet = Conv2D(32, kernel_size=3, activation = 'relu', padding='same')(inputs)\nnet = MaxPooling2D(pool_size=2, padding='same')(net)\n\nnet = Conv2D(64, kernel_size=3, activation = 'relu', padding='same')(net)\nnet = MaxPooling2D(pool_size=2, padding='same')(net)\n\nnet = Conv2D(128, kernel_size=3, activation = 'relu', padding='same')(net)\nnet = MaxPooling2D(pool_size=2, padding='same')(net)\n\nnet = Dense(128, activation='relu')(net)\n\nnet = UpSampling2D(size=2)(net)\nnet = Conv2D(128, kernel_size=3, activation='relu', padding='same')(net)\n\nnet = UpSampling2D(size=2)(net)\nnet = Conv2D(64, kernel_size=3, activation='relu', padding='same')(net)\n\nnet = UpSampling2D(size=2)(net)\noutputs = Conv2D(3, kernel_size=3, activation='softmax', padding='same')(net)\n\n\nmodel = Model(inputs=inputs, outputs=outputs)\nmodel.compile(optimizer = 'adam', loss='binary_crossentropy', metrics=['acc', 'mse'])\n\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit_generator(train_gen, validation_data = val_gen, epochs=2, verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_list = sorted(os.listdir('./test_img'))\n\nprint(len(test_list))\nprint(test_list[45])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_idx = 8\nx1_test = np.load('./test_img/' + test_list[test_idx])\ny1_test = np.load('./test_mask/' + test_list[test_idx])\ny_pred = model.predict(x1_test.reshape(1,256,256,3))\n\n\ny_pred = np.clip(y_pred.reshape((256,256,3)), 0, 5)\n\n\n\nprint(x1_test.shape, y1_test.shape, y_pred.shape)\n\n\n#y_pred = cv2.cvtColor(y_pred, cv2.COLOR_BGR2RGB)\n#y_pred = y_pred * 10\n\ncmap = matplotlib.colors.ListedColormap(['black', 'gray', 'green', 'yellow', 'orange', 'red'])\n\nplt.figure(figsize=(15, 10))\nplt.subplot(1, 3, 1)\nplt.title('input')\nplt.imshow(x1_test)\nplt.subplot(1, 3, 2)\nplt.title('output')\nplt.imshow(np.asarray(y_pred)[:,:,0], cmap = cmap, interpolation='nearest', vmin=0, vmax=5)\n#plt.imshow(y_pred)\nplt.subplot(1, 3, 3)\nplt.title('groundtruth')\nplt.imshow(np.asarray(y1_test)[:,:,0], cmap = cmap, interpolation='nearest', vmin=0, vmax=5)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(y_pred)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(y1_test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}