{"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":"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\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../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# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-04-12T13:37:27.636659Z","iopub.execute_input":"2023-04-12T13:37:27.637366Z","iopub.status.idle":"2023-04-12T13:37:27.643045Z","shell.execute_reply.started":"2023-04-12T13:37:27.637327Z","shell.execute_reply":"2023-04-12T13:37:27.641772Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport numpy as np\nimport glob\nimport PIL.Image as Image\nimport torch.utils.data as data\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nfrom tqdm import tqdm\nfrom ipywidgets import interact, fixed\nfrom torch.nn import DataParallel\nimport os\nimport time\n# os.environ['CUDA_VISIBLE_DEVICE']='0,1'\n# device_ids = [0,1]\n\nstart_time = time.time()\n\nPREFIX = '/kaggle/input/vesuvius-challenge-ink-detection/train/1/'\nBUFFER = 30  # Buffer size in x and y direction\nZ_START = 10 # First slice in the z direction to use\nZ_DIM = 48   # Number of slices in the z direction\nTRAINING_STEPS = 30000\nLEARNING_RATE = 0.03\nBATCH_SIZE = 32\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nimg = Image.open(PREFIX+\"ir.png\")\nplt.imshow(img, cmap=\"gray\")","metadata":{"execution":{"iopub.status.busy":"2023-04-12T13:43:44.601614Z","iopub.execute_input":"2023-04-12T13:43:44.602229Z","iopub.status.idle":"2023-04-12T13:43:50.403332Z","shell.execute_reply.started":"2023-04-12T13:43:44.602179Z","shell.execute_reply":"2023-04-12T13:43:50.402256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"hy, hx = img.size\n# hx = 8181\n# hy = 6330\n# Z_DIM = 10","metadata":{"execution":{"iopub.status.busy":"2023-04-12T13:48:51.096117Z","iopub.execute_input":"2023-04-12T13:48:51.097309Z","iopub.status.idle":"2023-04-12T13:48:51.102099Z","shell.execute_reply.started":"2023-04-12T13:48:51.097262Z","shell.execute_reply":"2023-04-12T13:48:51.101042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mask = np.array(Image.open(PREFIX+\"mask.png\").convert('1'))[0:hx, 0:hy]\nlabel = torch.from_numpy(np.array(Image.open(PREFIX+\"inklabels.png\"))[0:hx, 0:hy]).gt(0).float().to(DEVICE)\nfig, (ax1, ax2) = plt.subplots(1, 2)\nax1.set_title(\"mask.png\")\nax1.imshow(mask, cmap='gray')\nax2.set_title(\"inklabels.png\")\nax2.imshow(label.cpu(), cmap='gray')\nplt.show()\nprint(DEVICE)","metadata":{"execution":{"iopub.status.busy":"2023-04-12T13:03:23.261859Z","iopub.execute_input":"2023-04-12T13:03:23.262834Z","iopub.status.idle":"2023-04-12T13:03:28.949206Z","shell.execute_reply.started":"2023-04-12T13:03:23.262797Z","shell.execute_reply":"2023-04-12T13:03:28.948152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Load the 3d x-ray scan, one slice at a time\n# images = [np.array(Image.open(filename), dtype=np.float32)[:,0:3165]/65535.0 for filename in tqdm(sorted(glob.glob(PREFIX+\"surface_volume/*.tif\")))]\n# image_stack = torch.stack([torch.from_numpy(image).to(DEVICE) for image in images], dim=0)\n\n# fig, axes = plt.subplots(1, len(images), figsize=(15, 3))\n# for image, ax in zip(images, axes):\n#   ax.imshow(np.array(Image.fromarray(image).resize((image.shape[1]//20, image.shape[0]//20)), dtype=np.float32), cmap='gray')\n#   ax.set_xticks([]); ax.set_yticks([])\n# fig.tight_layout()\n# plt.show()\nimage_stack = (torch.from_numpy(np.array(Image.open(sorted(glob.glob(PREFIX+\"surface_volume/*.tif\"))[0]), dtype=np.float32)[0:hx, 0:hy] ).to(DEVICE)).reshape(1,hx, hy)\nfor i in tqdm(range(Z_DIM)):\n    if i>0:\n        img = (np.array(Image.open(sorted(glob.glob(PREFIX+\"surface_volume/*.tif\"))[i]), dtype=np.float32)[0:hx, 0:hy]).reshape(1,hx, hy)\n        image_stack = torch.vstack((image_stack, torch.from_numpy(img).to(DEVICE)))\n        torch.cuda.empty_cache()\n","metadata":{"execution":{"iopub.status.busy":"2023-04-12T13:03:34.398064Z","iopub.execute_input":"2023-04-12T13:03:34.398631Z","iopub.status.idle":"2023-04-12T13:03:48.050795Z","shell.execute_reply.started":"2023-04-12T13:03:34.398587Z","shell.execute_reply":"2023-04-12T13:03:48.049873Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_stack.shape","metadata":{"execution":{"iopub.status.busy":"2023-04-12T12:04:18.464376Z","iopub.execute_input":"2023-04-12T12:04:18.465488Z","iopub.status.idle":"2023-04-12T12:04:18.473733Z","shell.execute_reply.started":"2023-04-12T12:04:18.465434Z","shell.execute_reply":"2023-04-12T12:04:18.472529Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rect = (1100, 3500, 700, 950)\nfig, ax = plt.subplots()\nax.imshow(label.cpu())\npatch = patches.Rectangle((rect[0], rect[1]), rect[2], rect[3], linewidth=2, edgecolor='r', facecolor='none')\nax.add_patch(patch)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-12T13:03:52.647054Z","iopub.execute_input":"2023-04-12T13:03:52.647413Z","iopub.status.idle":"2023-04-12T13:03:54.550947Z","shell.execute_reply.started":"2023-04-12T13:03:52.647381Z","shell.execute_reply":"2023-04-12T13:03:54.550017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class SubvolumeDataset(data.Dataset):\n    def __init__(self, image_stack, label, pixels):\n        self.image_stack = image_stack\n        self.label = label\n        self.pixels = pixels\n    def __len__(self):\n        return len(self.pixels)\n    def __getitem__(self, index):\n        y, x = self.pixels[index]\n\n        subvolume = self.image_stack[:, y-BUFFER:y+BUFFER+1, x-BUFFER:x+BUFFER+1].view(1, Z_DIM, BUFFER*2+1, BUFFER*2+1)\n        inklabel = self.label[y, x].view(1)\n        return subvolume, inklabel\n\nmodel = nn.Sequential(\n    nn.Conv3d(1, 16, 3, 1, 1), nn.MaxPool3d(2, 2),\n    nn.Conv3d(16, 32, 3, 1, 1), nn.MaxPool3d(2, 2),\n    nn.Conv3d(32, 64, 3, 1, 1), nn.MaxPool3d(2, 2),\n    nn.Flatten(start_dim=1),\n    nn.LazyLinear(128), nn.ReLU(),\n    nn.LazyLinear(1), nn.Sigmoid()\n)\n# dummy_input = torch.randn(65,30,30)\n# model(dummy_input)\n# model = torch.nn.DataParallel(model, device_ids=device_ids)\nmodel.to(DEVICE)","metadata":{"execution":{"iopub.status.busy":"2023-04-12T13:03:57.983953Z","iopub.execute_input":"2023-04-12T13:03:57.985093Z","iopub.status.idle":"2023-04-12T13:03:58.013998Z","shell.execute_reply.started":"2023-04-12T13:03:57.985047Z","shell.execute_reply":"2023-04-12T13:03:58.012941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Generating pixel lists...\")\n# Split our dataset into train and val. The pixels inside the rect are the \n# val set, and the pixels outside the rect are the train set.\n# Adapted from https://www.kaggle.com/code/jamesdavey/100x-faster-pixel-coordinate-generator-1s-runtime\n# Create a Boolean array of the same shape as the bitmask, initially all True\nnot_border = np.zeros(mask.shape, dtype=bool)\nnot_border[BUFFER:mask.shape[0]-BUFFER, BUFFER:mask.shape[1]-BUFFER] = True\narr_mask = np.array(mask) * not_border\ninside_rect = np.zeros(mask.shape, dtype=bool) * arr_mask\n# Sets all indexes with inside_rect array to True\ninside_rect[rect[1]:rect[1]+rect[3]+1, rect[0]:rect[0]+rect[2]+1] = True\n# Set the pixels within the inside_rect to False\noutside_rect = np.ones(mask.shape, dtype=bool) * arr_mask\noutside_rect[rect[1]:rect[1]+rect[3]+1, rect[0]:rect[0]+rect[2]+1] = False\npixels_inside_rect = np.argwhere(inside_rect)\npixels_outside_rect = np.argwhere(outside_rect)\n\nprint(\"Training...\")\ntrain_dataset = SubvolumeDataset(image_stack, label, pixels_outside_rect)\ntrain_loader = data.DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)\ncriterion = nn.BCELoss()\noptimizer = optim.SGD(model.parameters(), lr=LEARNING_RATE)\nscheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr=LEARNING_RATE, total_steps=TRAINING_STEPS)\n\n","metadata":{"execution":{"iopub.status.busy":"2023-04-12T13:16:00.706286Z","iopub.execute_input":"2023-04-12T13:16:00.706875Z","iopub.status.idle":"2023-04-12T13:16:01.494260Z","shell.execute_reply.started":"2023-04-12T13:16:00.706839Z","shell.execute_reply":"2023-04-12T13:16:01.493049Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(pixels_outside_rect[:,0])","metadata":{"execution":{"iopub.status.busy":"2023-04-12T13:04:09.259947Z","iopub.execute_input":"2023-04-12T13:04:09.260554Z","iopub.status.idle":"2023-04-12T13:04:09.267446Z","shell.execute_reply.started":"2023-04-12T13:04:09.260513Z","shell.execute_reply":"2023-04-12T13:04:09.266294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.train()\n\n# running_loss = 0.0\nfor i, (subvolumes, inklabels) in tqdm(enumerate(train_loader), total=889697):\n#     if i >= 30000:\n#         break\n    optimizer.zero_grad()\n    outputs = model(subvolumes.to(DEVICE))\n    loss = criterion(outputs, inklabels.to(DEVICE))\n    loss.backward()\n    optimizer.step()\n    scheduler.step()\n#     running_loss += loss.item()\n#     if i % 3000 == 3000-1:\n#         print(\"Loss:\", running_loss / 3000)\n#         running_loss = 0.0","metadata":{"execution":{"iopub.status.busy":"2023-04-12T13:16:43.070920Z","iopub.execute_input":"2023-04-12T13:16:43.071306Z","iopub.status.idle":"2023-04-12T13:25:04.342352Z","shell.execute_reply.started":"2023-04-12T13:16:43.071273Z","shell.execute_reply":"2023-04-12T13:25:04.341159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model","metadata":{"execution":{"iopub.status.busy":"2023-04-12T13:11:53.296878Z","iopub.execute_input":"2023-04-12T13:11:53.297838Z","iopub.status.idle":"2023-04-12T13:11:53.304920Z","shell.execute_reply.started":"2023-04-12T13:11:53.297784Z","shell.execute_reply":"2023-04-12T13:11:53.303834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(pixels_outside_rect[:,0])","metadata":{"execution":{"iopub.status.busy":"2023-04-12T12:05:32.768404Z","iopub.execute_input":"2023-04-12T12:05:32.769005Z","iopub.status.idle":"2023-04-12T12:05:32.780128Z","shell.execute_reply.started":"2023-04-12T12:05:32.768951Z","shell.execute_reply":"2023-04-12T12:05:32.778916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# for i, (subvolumes, inklabels) in tqdm(enumerate(train_loader), total=890000):\n#     if i >= 890000:\n#         break","metadata":{"execution":{"iopub.status.busy":"2023-04-12T12:05:49.531379Z","iopub.execute_input":"2023-04-12T12:05:49.532454Z","iopub.status.idle":"2023-04-12T12:18:02.143348Z","shell.execute_reply.started":"2023-04-12T12:05:49.532402Z","shell.execute_reply":"2023-04-12T12:18:02.142104Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# subvolumes.size()","metadata":{"execution":{"iopub.status.busy":"2023-04-12T12:20:23.153940Z","iopub.execute_input":"2023-04-12T12:20:23.154429Z","iopub.status.idle":"2023-04-12T12:20:23.161746Z","shell.execute_reply.started":"2023-04-12T12:20:23.154393Z","shell.execute_reply":"2023-04-12T12:20:23.160682Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# inklabels.size()","metadata":{"execution":{"iopub.status.busy":"2023-04-12T12:20:32.042808Z","iopub.execute_input":"2023-04-12T12:20:32.043183Z","iopub.status.idle":"2023-04-12T12:20:32.049670Z","shell.execute_reply.started":"2023-04-12T12:20:32.043149Z","shell.execute_reply":"2023-04-12T12:20:32.048680Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"eval_dataset = SubvolumeDataset(image_stack, label, pixels_inside_rect)\neval_loader = data.DataLoader(eval_dataset, batch_size=BATCH_SIZE, shuffle=False)\noutput = torch.zeros_like(label).float()\nmodel.eval()\nwith torch.no_grad():\n    for i, (subvolumes, _) in enumerate(tqdm(eval_loader)):\n        for j, value in enumerate(model(subvolumes.to(DEVICE))):\n            output[tuple(pixels_inside_rect[i*BATCH_SIZE+j])] = value\n\nfig, (ax1, ax2) = plt.subplots(1, 2)\nax1.imshow(output.cpu(), cmap='gray')\nax2.imshow(label.cpu(), cmap='gray')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-12T13:28:48.404249Z","iopub.execute_input":"2023-04-12T13:28:48.405177Z","iopub.status.idle":"2023-04-12T13:30:15.612093Z","shell.execute_reply.started":"2023-04-12T13:28:48.405127Z","shell.execute_reply":"2023-04-12T13:30:15.610948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"THRESHOLD = 0.4\nfig, (ax1, ax2) = plt.subplots(1, 2)\nax1.imshow(output.gt(THRESHOLD).cpu(), cmap='gray')\nax2.imshow(label.cpu(), cmap='gray')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-12T13:30:37.562746Z","iopub.execute_input":"2023-04-12T13:30:37.563138Z","iopub.status.idle":"2023-04-12T13:30:40.254938Z","shell.execute_reply.started":"2023-04-12T13:30:37.563103Z","shell.execute_reply":"2023-04-12T13:30:40.253917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"end_time = time.time()\nall_time = end_time - start_","metadata":{},"execution_count":null,"outputs":[]}]}