{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"The tif images are all very large and cannot be fed directly into the neural network model for training. So I plan to cut the images into small patches for training. There is also a lot of white background in the images that should be removed.\n\n(tif图像都很大，无法直接输入神经网络模型进行训练。所以把图片切割成小patch进行训练。图片中还有很多白色背景应该剔除。)\n\n**Upvote if it help ( 请给我一票如果有用)**","metadata":{}},{"cell_type":"markdown","source":"### IMPORT (导入)","metadata":{}},{"cell_type":"code","source":"import sys\nimport os\nimport cv2\nimport pandas as pd\nimport numpy as np\nimport openslide\nfrom skimage.filters import threshold_otsu\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2022-07-11T15:09:19.812792Z","iopub.execute_input":"2022-07-11T15:09:19.813642Z","iopub.status.idle":"2022-07-11T15:09:19.824217Z","shell.execute_reply.started":"2022-07-11T15:09:19.813584Z","shell.execute_reply":"2022-07-11T15:09:19.822681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## HELPER (一些函数)","metadata":{}},{"cell_type":"code","source":"def get_img_path(img_id, test=False):\n    if test:\n        return f'../input/mayo-clinic-strip-ai/test/{img_id}.tif'\n    return f'../input/mayo-clinic-strip-ai/train/{img_id}.tif'\n\n# 进行前景背景分离 Separate foreground backgrounds\ndef ostu(img):\n    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n    thre = threshold_otsu(gray)\n    ret1, th =  cv2.threshold(gray,thre,255,cv2.THRESH_BINARY_INV)\n    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))\n    th = cv2.morphologyEx(th.astype(np.uint8), cv2.MORPH_CLOSE, kernel)\n    th[th>0] = 1\n    th[gray==0] = 0\n    return th\n\n# 利用reshape把图片分为size大小的patch\n# split img to patch by np.reshape\ndef gray2patch(img, size=256):\n    h, w = img.shape\n    nh, nw = h - h%size, w - w%size\n    img = img[:nh, :nw]\n    h,w= img.shape\n    d_h=int(h/size)\n    d_w=int(w/size)\n    img = img.reshape((d_h, h//d_h, d_w, w//d_w))\n    return img.transpose([0,2,1,3])\ndef img2patch(img, patch_size=256):\n    img_r = gray2patch(img[:,:,0])\n    img_g = gray2patch(img[:,:,1])\n    img_b = gray2patch(img[:,:,2])\n    return np.stack((img_r, img_g, img_b), axis=-1)\n\n# 检验二值化msk中前景(=1)像素点的数量是否满足阈值\n# Check if the number of foreground (=1) pixel points \n# in msk satisfies the threshold\ndef check_msk(msk, threshold=0.6):\n    if msk.sum()/(msk.size) > threshold:\n        return True\n    return False","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-07-11T15:27:48.399073Z","iopub.execute_input":"2022-07-11T15:27:48.399565Z","iopub.status.idle":"2022-07-11T15:27:48.414926Z","shell.execute_reply.started":"2022-07-11T15:27:48.399517Z","shell.execute_reply":"2022-07-11T15:27:48.413498Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = pd.read_csv('../input/mayo-clinic-strip-ai/train.csv')","metadata":{"execution":{"iopub.status.busy":"2022-07-11T15:09:32.546671Z","iopub.execute_input":"2022-07-11T15:09:32.547618Z","iopub.status.idle":"2022-07-11T15:09:32.566831Z","shell.execute_reply.started":"2022-07-11T15:09:32.547546Z","shell.execute_reply":"2022-07-11T15:09:32.565389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Show an example (展示一个例子)\n\nsplit img to patch by np.reshape(把图片用reshape切割为patch)","metadata":{"execution":{"iopub.status.busy":"2022-07-11T13:25:08.235286Z","iopub.execute_input":"2022-07-11T13:25:08.235698Z","iopub.status.idle":"2022-07-11T13:25:08.259697Z","shell.execute_reply.started":"2022-07-11T13:25:08.235665Z","shell.execute_reply":"2022-07-11T13:25:08.257889Z"}}},{"cell_type":"code","source":"img_id = df_train.image_id[4]","metadata":{"execution":{"iopub.status.busy":"2022-07-11T15:27:59.848255Z","iopub.execute_input":"2022-07-11T15:27:59.848678Z","iopub.status.idle":"2022-07-11T15:27:59.854372Z","shell.execute_reply.started":"2022-07-11T15:27:59.848646Z","shell.execute_reply":"2022-07-11T15:27:59.853302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with openslide.OpenSlide(get_img_path(img_id)) as wsi:\n    img_RGB = np.transpose(np.array(wsi.read_region((0, 0), 0,\n                       wsi.level_dimensions[0]).convert('RGB')),\n                       axes=[1, 0, 2])\nth = ostu(img_RGB)\nplt.imshow(th, cmap='gray')","metadata":{"execution":{"iopub.status.busy":"2022-07-11T15:11:22.805739Z","iopub.execute_input":"2022-07-11T15:11:22.806208Z","iopub.status.idle":"2022-07-11T15:11:44.434005Z","shell.execute_reply.started":"2022-07-11T15:11:22.806168Z","shell.execute_reply":"2022-07-11T15:11:44.432422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"msk_patches = gray2patch(th)\nplt.imshow(msk_patches[35,25,...], cmap='gray')","metadata":{"execution":{"iopub.status.busy":"2022-07-11T15:16:45.678326Z","iopub.execute_input":"2022-07-11T15:16:45.681278Z","iopub.status.idle":"2022-07-11T15:16:46.275523Z","shell.execute_reply.started":"2022-07-11T15:16:45.681189Z","shell.execute_reply":"2022-07-11T15:16:46.274059Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_patches = img2patch(img_RGB)\nplt.imshow(img_patches[35,25,...])","metadata":{"execution":{"iopub.status.busy":"2022-07-11T15:11:44.651647Z","iopub.execute_input":"2022-07-11T15:11:44.652076Z","iopub.status.idle":"2022-07-11T15:11:45.168741Z","shell.execute_reply.started":"2022-07-11T15:11:44.652039Z","shell.execute_reply":"2022-07-11T15:11:45.167371Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.makedirs('train', exist_ok=True)\nh, w, _, _, _ = img_patches.shape\n# 如果切割的遮罩满足一定阈值，就保留该图片\n# If an image corresponds to a mask that meets a certain threshold, image is saved.\ncount = 0\nfor i in range(h):\n    for j in range(w):\n        if check_msk(msk_patches[i, j, ...], threshold=0.6):\n            np.save(f'./train/{img_id}_{count}.npy', img_patches[i, j, ...])\n            count += 1\nprint(f'Image {img_id} convert to {count} patch.')","metadata":{"execution":{"iopub.status.busy":"2022-07-11T15:28:03.530969Z","iopub.execute_input":"2022-07-11T15:28:03.531949Z","iopub.status.idle":"2022-07-11T15:28:06.165363Z","shell.execute_reply.started":"2022-07-11T15:28:03.531908Z","shell.execute_reply":"2022-07-11T15:28:06.163983Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"patch = np.load('./train/026c97_0_0.npy')\nplt.imshow(patch)","metadata":{"execution":{"iopub.status.busy":"2022-07-11T15:28:43.340183Z","iopub.execute_input":"2022-07-11T15:28:43.340627Z","iopub.status.idle":"2022-07-11T15:28:43.573202Z","shell.execute_reply.started":"2022-07-11T15:28:43.340593Z","shell.execute_reply":"2022-07-11T15:28:43.571476Z"},"trusted":true},"execution_count":null,"outputs":[]}]}