{"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":"!pip install celluloid -q\n!pip install segmentation_models_pytorch","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-05-16T04:41:31.070785Z","iopub.execute_input":"2023-05-16T04:41:31.071371Z","iopub.status.idle":"2023-05-16T04:42:00.397838Z","shell.execute_reply.started":"2023-05-16T04:41:31.071314Z","shell.execute_reply":"2023-05-16T04:42:00.396505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch as tc\nimport numpy as np\n\nfrom tqdm.auto import tqdm\n\nimport torch\nimport torch.nn as nn\nimport matplotlib.pyplot as plt\nimport cv2\nfrom typing import List\nfrom celluloid import Camera\n\nimport segmentation_models_pytorch as smp\nfrom IPython.display import HTML, display","metadata":{"execution":{"iopub.status.busy":"2023-05-16T04:42:00.401870Z","iopub.execute_input":"2023-05-16T04:42:00.402210Z","iopub.status.idle":"2023-05-16T04:42:05.523517Z","shell.execute_reply.started":"2023-05-16T04:42:00.402177Z","shell.execute_reply":"2023-05-16T04:42:05.522122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## config","metadata":{}},{"cell_type":"code","source":"class CFG:\n    # ============== comp exp name =============\n    comp_name = 'vesuvius'\n\n    comp_dir_path = '/kaggle/input/'\n    comp_folder_name = 'vesuvius-challenge-ink-detection'\n    comp_dataset_path = f'{comp_dir_path}{comp_folder_name}/'\n    \n    exp_name = 'vesuvius_2d_slide_exp002'\n\n    # ============== pred target =============\n    target_size = 1\n    TTA=True\n    \n    # ============== model cfg =============\n    model_name = 'Unet'\n    backbone = 'se_resnext50_32x4d'\n\n    in_chans = 6 # 65\n    # ============== training cfg =============\n    size = 224\n    tile_size = 224","metadata":{"execution":{"iopub.status.busy":"2023-05-16T04:42:05.525401Z","iopub.execute_input":"2023-05-16T04:42:05.525813Z","iopub.status.idle":"2023-05-16T04:42:05.534960Z","shell.execute_reply.started":"2023-05-16T04:42:05.525769Z","shell.execute_reply":"2023-05-16T04:42:05.533768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# helper","metadata":{}},{"cell_type":"code","source":"def animate_volume(volume: List[np.ndarray], rect: dict = None):\n    plt.rcParams[\"figure.dpi\"] = 350\n    plt.style.use(\"dark_background\")\n    num_slices = len(volume)\n    fig = plt.figure()\n    camera = Camera(fig)\n    for i in range(num_slices):\n        if rect is not None:\n            plt.imshow(volume[i][rect[\"y\"] : rect[\"y\"] + rect[\"height\"], rect[\"x\"] : rect[\"x\"] + rect[\"width\"]], cmap=\"gray\")\n        else:\n            plt.imshow(volume[i], cmap=\"gray\")\n        plt.text(x=0.1, y=-0.1, s=f\"slice {i+1}/{num_slices}\", horizontalalignment=\"center\")\n        plt.axis(\"off\")\n        camera.snap()\n    animation = camera.animate()\n    plt.close(fig)\n    fix_video_adjust = \"<style> video {margin: 0px; padding: 0px; width:100%; height:auto;} </style>\"\n    display(HTML(fix_video_adjust + animation.to_html5_video()))","metadata":{"execution":{"iopub.status.busy":"2023-05-16T04:42:05.538682Z","iopub.execute_input":"2023-05-16T04:42:05.539367Z","iopub.status.idle":"2023-05-16T04:42:05.558280Z","shell.execute_reply.started":"2023-05-16T04:42:05.539325Z","shell.execute_reply":"2023-05-16T04:42:05.557116Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# model","metadata":{}},{"cell_type":"code","source":"class CustomModel(nn.Module):\n    def __init__(self, cfg, weight=None):\n        super().__init__()\n        self.cfg = cfg\n\n        self.encoder = smp.Unet(\n            encoder_name=cfg.backbone, \n            encoder_weights=weight,\n            in_channels=cfg.in_chans,\n            classes=cfg.target_size,\n            activation=None,\n        )\n\n    def forward(self, image):\n        output = self.encoder(image)\n        output = output.squeeze(-1)\n        return output\n\ndef build_model(cfg, weight=\"imagenet\"):\n    print('model_name', cfg.model_name)\n    print('backbone', cfg.backbone)\n\n    model = CustomModel(cfg, weight)\n    return model","metadata":{"execution":{"iopub.status.busy":"2023-05-16T04:42:05.573412Z","iopub.execute_input":"2023-05-16T04:42:05.574030Z","iopub.status.idle":"2023-05-16T04:42:05.585293Z","shell.execute_reply.started":"2023-05-16T04:42:05.573989Z","shell.execute_reply":"2023-05-16T04:42:05.584197Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = build_model(CFG, weight=None)\n\nmodel_path = f'/kaggle/input/vesuvius-models-public/{CFG.exp_name}/vesuvius-models/Unet_fold1_best.pth'\nstate = torch.load(model_path)['model']\nmodel.load_state_dict(state)\nmodel.eval().cuda()\nprint(\"ok\")","metadata":{"execution":{"iopub.status.busy":"2023-05-16T04:42:05.587158Z","iopub.execute_input":"2023-05-16T04:42:05.587561Z","iopub.status.idle":"2023-05-16T04:42:19.202426Z","shell.execute_reply.started":"2023-05-16T04:42:05.587500Z","shell.execute_reply":"2023-05-16T04:42:19.201131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# main\nUse gradient descent to get images that match the label.","metadata":{}},{"cell_type":"code","source":"def run(label:np.ndarray,x=5000,y=2000,iteration=6000):\n    BCELoss = smp.losses.SoftBCEWithLogitsLoss()\n\n    label=tc.from_numpy(label[x:x+CFG.size,y:y+CFG.size][None,None]).cuda()!=0\n    label=label.to(tc.float32)\n\n    images=tc.randn(1,CFG.in_chans,CFG.size,CFG.size,requires_grad=True,device=\"cuda:0\")\n    optimizer=tc.optim.AdamW([images],lr=5e-2)\n\n    time_=tqdm(total=iteration)\n    for i in range(iteration):\n        output=model.forward(images)\n        loss:tc.Tensor=BCELoss(output,label)\n        #loss+=((images[...,1:,:]-images[...,:-1,:])**2).mean()/2\n        #loss+=((images[...,:,1:]-images[...,:,:-1])**2).mean()/2\n        loss.backward(inputs=[images])\n        optimizer.step()\n        optimizer.zero_grad()\n        time_.set_description(f\"{loss:.7f}\")\n        time_.update()\n    return images.detach().cpu().numpy()[0],label.cpu().numpy()[0,0]","metadata":{"execution":{"iopub.status.busy":"2023-05-16T04:42:19.204071Z","iopub.execute_input":"2023-05-16T04:42:19.204751Z","iopub.status.idle":"2023-05-16T04:42:19.216656Z","shell.execute_reply.started":"2023-05-16T04:42:19.204706Z","shell.execute_reply":"2023-05-16T04:42:19.215457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label=cv2.imread(CFG.comp_dataset_path + f\"train/2/inklabels.png\", 0)\nimages,label=run(label,5000,2000)","metadata":{"execution":{"iopub.status.busy":"2023-05-16T04:42:19.218627Z","iopub.execute_input":"2023-05-16T04:42:19.219124Z","iopub.status.idle":"2023-05-16T04:46:54.562481Z","shell.execute_reply.started":"2023-05-16T04:42:19.219073Z","shell.execute_reply":"2023-05-16T04:46:54.561338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# label","metadata":{}},{"cell_type":"code","source":"plt.imshow(label)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-05-16T04:46:54.566446Z","iopub.execute_input":"2023-05-16T04:46:54.567553Z","iopub.status.idle":"2023-05-16T04:46:54.815452Z","shell.execute_reply.started":"2023-05-16T04:46:54.567510Z","shell.execute_reply":"2023-05-16T04:46:54.814489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Features required by the model","metadata":{}},{"cell_type":"code","source":"animate_volume(images)","metadata":{"execution":{"iopub.status.busy":"2023-05-16T04:46:54.817405Z","iopub.execute_input":"2023-05-16T04:46:54.818155Z","iopub.status.idle":"2023-05-16T04:46:57.275608Z","shell.execute_reply.started":"2023-05-16T04:46:54.818113Z","shell.execute_reply":"2023-05-16T04:46:57.274340Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images=np.stack(images)\nimage=images.mean(0)\nlabel=label.astype(bool)\n\nkde = np.histogram(image[label], bins=200, density=True)\nkde_x, kde_y = kde[1], kde[0]\nplt.plot(kde_x[:-1], kde_y, label='ink')\nkde = np.histogram(image[~label], bins=200, density=True)\nkde_x, kde_y = kde[1], kde[0]\nplt.plot(kde_x[:-1], kde_y, label='not_ink')\n\n\nplt.xlabel('Value')\nplt.ylabel('Probability Density')\nplt.title('Distribution of Data')\nplt.legend(loc='best')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-05-16T04:55:23.988045Z","iopub.execute_input":"2023-05-16T04:55:23.988706Z","iopub.status.idle":"2023-05-16T04:55:24.018743Z","shell.execute_reply.started":"2023-05-16T04:55:23.988663Z","shell.execute_reply":"2023-05-16T04:55:24.016771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Original image","metadata":{}},{"cell_type":"code","source":"images=[]\nfor i in tqdm(range(32,32+6)):\n    image = cv2.imread(CFG.comp_dataset_path + f\"train/2/surface_volume/{i:02}.tif\",0)\n    images.append(image[5000:5000+CFG.size,2000:2000+CFG.size])\nanimate_volume(images)","metadata":{"execution":{"iopub.status.busy":"2023-05-16T04:54:53.788963Z","iopub.execute_input":"2023-05-16T04:54:53.789960Z","iopub.status.idle":"2023-05-16T04:55:20.215177Z","shell.execute_reply.started":"2023-05-16T04:54:53.789902Z","shell.execute_reply":"2023-05-16T04:55:20.213954Z"},"trusted":true},"execution_count":null,"outputs":[]}]}