{"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":"![](https://storage.googleapis.com/kaggle-competitions/kaggle/36073/logos/header.png?t=2022-04-12-20-53-30)","metadata":{"execution":{"iopub.status.busy":"2022-04-21T18:39:54.474251Z","iopub.execute_input":"2022-04-21T18:39:54.474986Z","iopub.status.idle":"2022-04-21T18:39:55.157888Z","shell.execute_reply.started":"2022-04-21T18:39:54.474943Z","shell.execute_reply":"2022-04-21T18:39:55.157081Z"}}},{"cell_type":"markdown","source":"# The task is to denoise “shabby” pages, reversing the effects imposed on them by Augraphy","metadata":{}},{"cell_type":"markdown","source":"### Importing some basic libraries required to play with the images","metadata":{}},{"cell_type":"code","source":"import os\nimport cv2\nimport glob\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-09-09T03:48:18.629746Z","iopub.execute_input":"2022-09-09T03:48:18.630002Z","iopub.status.idle":"2022-09-09T03:48:18.963529Z","shell.execute_reply.started":"2022-09-09T03:48:18.629919Z","shell.execute_reply":"2022-09-09T03:48:18.962865Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BASE_DIR = \"/kaggle/input/denoising-shabby-pages\"\nglob.glob(BASE_DIR+'/*')\n\ncleaned_img_paths = sorted(glob.glob(BASE_DIR+\"/train/train/train_cleaned/*.png\"))\ntrain_shabby_paths = sorted(glob.glob(BASE_DIR+\"/train/train/train_shabby/*.png\"))\n\nlen(cleaned_img_paths),len(train_shabby_paths)","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:18.965098Z","iopub.execute_input":"2022-09-09T03:48:18.965345Z","iopub.status.idle":"2022-09-09T03:48:19.123162Z","shell.execute_reply.started":"2022-09-09T03:48:18.965313Z","shell.execute_reply":"2022-09-09T03:48:19.122457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Display some of the shabby images given for training","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(20, 5))\nprint(\"Input samples:\")\nfor i,pth in enumerate(train_shabby_paths[0:20]):\n    im = cv2.imread(pth)\n    plt.subplot(2, 10, i+1)\n    plt.imshow(im, cmap='gray')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:19.124269Z","iopub.execute_input":"2022-09-09T03:48:19.124614Z","iopub.status.idle":"2022-09-09T03:48:21.046276Z","shell.execute_reply.started":"2022-09-09T03:48:19.124577Z","shell.execute_reply":"2022-09-09T03:48:21.045679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(20, 5))\nprint(\"Target samples:\")\nfor i,pth in enumerate(cleaned_img_paths[0:20]):\n    im = cv2.imread(pth)\n    plt.subplot(2, 10, i+1)\n    plt.imshow(im, cmap='gray')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:21.047148Z","iopub.execute_input":"2022-09-09T03:48:21.047361Z","iopub.status.idle":"2022-09-09T03:48:23.006944Z","shell.execute_reply.started":"2022-09-09T03:48:21.047330Z","shell.execute_reply":"2022-09-09T03:48:23.005231Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train = []\nfor i,pth in enumerate(train_shabby_paths):\n    im = cv2.imread(pth,0)\n    X_train.append(im)\nX_train = np.array(X_train)","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:23.009049Z","iopub.execute_input":"2022-09-09T03:48:23.009843Z","iopub.status.idle":"2022-09-09T03:48:30.468806Z","shell.execute_reply.started":"2022-09-09T03:48:23.009807Z","shell.execute_reply":"2022-09-09T03:48:30.468002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_train = []\nfor i,pth in enumerate(cleaned_img_paths):\n    im = cv2.imread(pth,0)\n    y_train.append(im)\ny_train = np.array(y_train)","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:30.470092Z","iopub.execute_input":"2022-09-09T03:48:30.470351Z","iopub.status.idle":"2022-09-09T03:48:35.573394Z","shell.execute_reply.started":"2022-09-09T03:48:30.470315Z","shell.execute_reply":"2022-09-09T03:48:35.572597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train.shape, y_train.shape","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:35.574756Z","iopub.execute_input":"2022-09-09T03:48:35.575021Z","iopub.status.idle":"2022-09-09T03:48:35.582425Z","shell.execute_reply.started":"2022-09-09T03:48:35.574980Z","shell.execute_reply":"2022-09-09T03:48:35.581514Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We have 700 shabby pages and corresponding cleaned images with the size of 400x400","metadata":{}},{"cell_type":"markdown","source":"Various approaches are available to denoise shabby images.\n\nFeel free to experiment and find best suitable algo/model","metadata":{}},{"cell_type":"code","source":"import random\nimport numpy as np \nimport matplotlib.pyplot as plt \nimport os, time, pickle, json \nfrom glob import glob \nfrom PIL import Image\nimport cv2 \nfrom typing import List, Tuple, Dict\nfrom statistics import mean \nfrom tqdm import tqdm \n\nimport torch \nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torchvision import transforms \nfrom torchvision.utils import save_image\nfrom torch.utils.data import DataLoader ","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:35.584302Z","iopub.execute_input":"2022-09-09T03:48:35.584586Z","iopub.status.idle":"2022-09-09T03:48:37.377829Z","shell.execute_reply.started":"2022-09-09T03:48:35.584535Z","shell.execute_reply":"2022-09-09T03:48:37.377053Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MEAN = (0.5, 0.5, 0.5,)\nSTD = (0.5, 0.5, 0.5,)\nRESIZE = 256\n\n\nclass Transform():\n    def __init__(self, resize=RESIZE, mean=MEAN, std=STD):\n        self.data_transform = transforms.Compose([\n            transforms.Resize((resize, resize)), \n            transforms.ToTensor(),\n            transforms.Normalize(mean, std)\n        ])\n        \n    def __call__(self, img: Image.Image):\n        return self.data_transform(img)\n\n\nclass Dataset(object):\n    def __init__(self, files: List[str], is_valid=False):\n        self.files = files \n        self.trasformer = Transform()\n        self.is_valid = is_valid\n    \n    def __getitem__(self, idx: int) -> Tuple[torch.Tensor, torch.Tensor]:\n        filename = os.path.basename(self.files[idx])\n        \n        src = cv2.imread(self.files[idx])\n        dst = cv2.imread(f\"{BASE_DIR}/train/train/train_cleaned/{filename}\")\n\n        # flip mode\n#         mode = 3 if self.is_valid else random.randint(0, 3)\n        \n#         if mode == 3:\n#             input_tensor = self.trasformer(Image.fromarray(src))\n#             output_tensor = self.trasformer(Image.fromarray(dst))\n#         else:\n#             input_img = cv2.flip(src, mode - 1)\n#             output_img = cv2.flip(dst, mode - 1)\n            \n        input_tensor = self.trasformer(Image.fromarray(src))\n        output_tensor = self.trasformer(Image.fromarray(dst))\n\n        return input_tensor, output_tensor \n    \n    def __len__(self):\n        return len(self.files)\n\n\ndef show_img_sample(img: torch.Tensor, img1: torch.Tensor):\n    fig, axes = plt.subplots(1, 2, figsize=(14, 7))\n    ax = axes.ravel()\n    ax[0].imshow(img.permute(1, 2, 0))\n    ax[0].set_xticks([])\n    ax[0].set_yticks([])\n    ax[0].set_title(\"input image\", c=\"g\")\n    ax[1].imshow(img1.permute(1, 2, 0))\n    ax[1].set_xticks([])\n    ax[1].set_yticks([])\n    ax[1].set_title(\"label image\", c=\"g\")\n    plt.subplots_adjust(wspace=0, hspace=0)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:37.379256Z","iopub.execute_input":"2022-09-09T03:48:37.379553Z","iopub.status.idle":"2022-09-09T03:48:37.393062Z","shell.execute_reply.started":"2022-09-09T03:48:37.379516Z","shell.execute_reply":"2022-09-09T03:48:37.391290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_ds = Dataset(train_shabby_paths)\nval_ds = Dataset(train_shabby_paths, True)","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:37.394697Z","iopub.execute_input":"2022-09-09T03:48:37.395112Z","iopub.status.idle":"2022-09-09T03:48:37.405649Z","shell.execute_reply.started":"2022-09-09T03:48:37.395076Z","shell.execute_reply":"2022-09-09T03:48:37.404923Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_img_sample(val_ds.__getitem__(1)[0], val_ds.__getitem__(1)[1])","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:37.406993Z","iopub.execute_input":"2022-09-09T03:48:37.407408Z","iopub.status.idle":"2022-09-09T03:48:37.748937Z","shell.execute_reply.started":"2022-09-09T03:48:37.407316Z","shell.execute_reply":"2022-09-09T03:48:37.747238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BATCH_SIZE = 1\ndevice = \"cuda:0\" if torch.cuda.is_available() else \"cpu\"\ntorch.manual_seed(0)\nnp.random.seed(0)\n\ntrain_dl = DataLoader(train_ds, batch_size=BATCH_SIZE, shuffle=True, drop_last=True)\nval_dl = DataLoader(val_ds, batch_size=BATCH_SIZE, shuffle=False, drop_last=False)","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:37.750148Z","iopub.execute_input":"2022-09-09T03:48:37.750884Z","iopub.status.idle":"2022-09-09T03:48:37.815049Z","shell.execute_reply.started":"2022-09-09T03:48:37.750848Z","shell.execute_reply":"2022-09-09T03:48:37.814201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def normal_init(m, mean, std):\n    if isinstance(m, nn.ConvTranspose2d) or isinstance(m, nn.Conv2d):\n        m.weight.data.normal_(mean, std)\n        m.bias.data.zero_()\n        \nclass Generator(nn.Module):\n    # initializers\n    def __init__(self, d=64):\n        super().__init__()\n        # Unet encoder\n        self.conv1 = nn.Conv2d(3, d, 4, 2, 1)\n        self.conv2 = nn.Conv2d(d, d * 2, 4, 2, 1)\n        self.conv2_bn = nn.BatchNorm2d(d * 2)\n        self.conv3 = nn.Conv2d(d * 2, d * 4, 4, 2, 1)\n        self.conv3_bn = nn.BatchNorm2d(d * 4)\n        self.conv4 = nn.Conv2d(d * 4, d * 8, 4, 2, 1)\n        self.conv4_bn = nn.BatchNorm2d(d * 8)\n        self.conv5 = nn.Conv2d(d * 8, d * 8, 4, 2, 1)\n        self.conv5_bn = nn.BatchNorm2d(d * 8)\n        self.conv6 = nn.Conv2d(d * 8, d * 8, 4, 2, 1)\n        self.conv6_bn = nn.BatchNorm2d(d * 8)\n        self.conv7 = nn.Conv2d(d * 8, d * 8, 4, 2, 1)\n        self.conv7_bn = nn.BatchNorm2d(d * 8)\n        self.conv8 = nn.Conv2d(d * 8, d * 8, 4, 2, 1)\n        # self.conv8_bn = nn.BatchNorm2d(d * 8)\n\n        # Unet decoder\n        self.deconv1 = nn.ConvTranspose2d(d * 8, d * 8, 4, 2, 1)\n        self.deconv1_bn = nn.BatchNorm2d(d * 8)\n        self.deconv2 = nn.ConvTranspose2d(d * 8 * 2, d * 8, 4, 2, 1)\n        self.deconv2_bn = nn.BatchNorm2d(d * 8)\n        self.deconv3 = nn.ConvTranspose2d(d * 8 * 2, d * 8, 4, 2, 1)\n        self.deconv3_bn = nn.BatchNorm2d(d * 8)\n        self.deconv4 = nn.ConvTranspose2d(d * 8 * 2, d * 8, 4, 2, 1)\n        self.deconv4_bn = nn.BatchNorm2d(d * 8)\n        self.deconv5 = nn.ConvTranspose2d(d * 8 * 2, d * 4, 4, 2, 1)\n        self.deconv5_bn = nn.BatchNorm2d(d * 4)\n        self.deconv6 = nn.ConvTranspose2d(d * 4 * 2, d * 2, 4, 2, 1)\n        self.deconv6_bn = nn.BatchNorm2d(d * 2)\n        self.deconv7 = nn.ConvTranspose2d(d * 2 * 2, d, 4, 2, 1)\n        self.deconv7_bn = nn.BatchNorm2d(d)\n        self.deconv8 = nn.ConvTranspose2d(d * 2, 3, 4, 2, 1)\n\n    # weight_init\n    def weight_init(self, mean, std):\n        for m in self._modules:\n            normal_init(self._modules[m], mean, std)\n\n    # forward method\n    def forward(self, input):\n        e1 = self.conv1(input)\n        e2 = self.conv2_bn(self.conv2(F.leaky_relu(e1, 0.2)))\n        e3 = self.conv3_bn(self.conv3(F.leaky_relu(e2, 0.2)))\n        e4 = self.conv4_bn(self.conv4(F.leaky_relu(e3, 0.2)))\n        e5 = self.conv5_bn(self.conv5(F.leaky_relu(e4, 0.2)))\n        e6 = self.conv6_bn(self.conv6(F.leaky_relu(e5, 0.2)))\n        e7 = self.conv7_bn(self.conv7(F.leaky_relu(e6, 0.2)))\n        e8 = self.conv8(F.leaky_relu(e7, 0.2))\n        # e8 = self.conv8_bn(self.conv8(F.leaky_relu(e7, 0.2)))\n        d1 = F.dropout(self.deconv1_bn(self.deconv1(F.relu(e8))), 0.5, training=True)\n        d1 = torch.cat([d1, e7], 1)\n        d2 = F.dropout(self.deconv2_bn(self.deconv2(F.relu(d1))), 0.5, training=True)\n        d2 = torch.cat([d2, e6], 1)\n        d3 = F.dropout(self.deconv3_bn(self.deconv3(F.relu(d2))), 0.5, training=True)\n        d3 = torch.cat([d3, e5], 1)\n        d4 = self.deconv4_bn(self.deconv4(F.relu(d3)))\n        # d4 = F.dropout(self.deconv4_bn(self.deconv4(F.relu(d3))), 0.5)\n        d4 = torch.cat([d4, e4], 1)\n        d5 = self.deconv5_bn(self.deconv5(F.relu(d4)))\n        d5 = torch.cat([d5, e3], 1)\n        d6 = self.deconv6_bn(self.deconv6(F.relu(d5)))\n        d6 = torch.cat([d6, e2], 1)\n        d7 = self.deconv7_bn(self.deconv7(F.relu(d6)))\n        d7 = torch.cat([d7, e1], 1)\n        d8 = self.deconv8(F.relu(d7))\n        o = F.tanh(d8)\n\n        return o","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:37.816384Z","iopub.execute_input":"2022-09-09T03:48:37.818056Z","iopub.status.idle":"2022-09-09T03:48:37.841044Z","shell.execute_reply.started":"2022-09-09T03:48:37.817985Z","shell.execute_reply":"2022-09-09T03:48:37.840210Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Discriminator(nn.Module):\n    # initializers\n    def __init__(self, d=64):\n        super().__init__()\n        self.conv1 = nn.Conv2d(6, d, 4, 2, 1)\n        self.conv2 = nn.Conv2d(d, d * 2, 4, 2, 1)\n        self.conv2_bn = nn.BatchNorm2d(d * 2)\n        self.conv3 = nn.Conv2d(d * 2, d * 4, 4, 2, 1)\n        self.conv3_bn = nn.BatchNorm2d(d * 4)\n        self.conv4 = nn.Conv2d(d * 4, d * 8, 4, 1, 1)\n        self.conv4_bn = nn.BatchNorm2d(d * 8)\n        self.conv5 = nn.Conv2d(d * 8, 1, 4, 1, 1)\n\n    # weight_init\n    def weight_init(self, mean, std):\n        for m in self._modules:\n            normal_init(self._modules[m], mean, std)\n\n    # forward method\n    def forward(self, input, label):\n        x = torch.cat([input, label], 1)\n        x = F.leaky_relu(self.conv1(x), 0.2)\n        x = F.leaky_relu(self.conv2_bn(self.conv2(x)), 0.2)\n        x = F.leaky_relu(self.conv3_bn(self.conv3(x)), 0.2)\n        x = F.leaky_relu(self.conv4_bn(self.conv4(x)), 0.2)\n        x = F.sigmoid(self.conv5(x))\n\n        return x","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:37.845015Z","iopub.execute_input":"2022-09-09T03:48:37.845659Z","iopub.status.idle":"2022-09-09T03:48:37.856687Z","shell.execute_reply.started":"2022-09-09T03:48:37.845628Z","shell.execute_reply":"2022-09-09T03:48:37.855859Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_fn(train_dl, G, D, criterion_bce, criterion_mae, optimizer_g, optimizer_d):\n    G.train()\n    D.train()\n    LAMBDA = 100.0\n    total_loss_g, total_loss_d = [], []\n    for i, (input_img, real_img) in enumerate(tqdm(train_dl)):\n        input_img = input_img.to(device)\n        real_img = real_img.to(device)\n        \n        real_label = torch.ones(input_img.size()[0], 1, 30, 30).to(device)\n        fake_label = torch.zeros(input_img.size()[0], 1, 30, 30).to(device)\n        # Generator \n        fake_img = G(input_img)\n        fake_img_ = fake_img.detach() # commonly using \n        out_fake = D(fake_img, input_img)\n        \n        loss_g_bce = criterion_bce(out_fake, real_label) # binaryCrossEntropy\n        loss_g_mae = criterion_mae(fake_img, real_img) # MSELoss\n\n        loss_g = loss_g_bce + LAMBDA * loss_g_mae \n        total_loss_g.append(loss_g.item())\n        \n        optimizer_g.zero_grad()\n        optimizer_d.zero_grad()\n        loss_g.backward(retain_graph=True)\n        optimizer_g.step()\n        # Discriminator\n        out_real = D(real_img, input_img)\n        loss_d_real = criterion_bce(out_real, real_label)\n        out_fake = D(fake_img_, input_img)\n        loss_d_fake = criterion_bce(out_fake, fake_label)\n        loss_d = loss_d_real + loss_d_fake \n        total_loss_d.append(loss_d.item())\n        \n        optimizer_g.zero_grad()\n        optimizer_d.zero_grad()\n        loss_d.backward()\n        optimizer_d.step()\n    return mean(total_loss_g), mean(total_loss_d), fake_img.detach().cpu() \n\ndef de_norm(img):\n    img_ = img.mul(torch.FloatTensor(STD).view(3, 1, 1))\n    img_ = img_.add(torch.FloatTensor(MEAN).view(3, 1, 1)).detach().numpy()\n    img_ = np.transpose(img_, (1, 2, 0))\n    return img_\n\ndef saving_img(fake_img, e):\n    os.makedirs(\"generated\", exist_ok=True)\n    for i in range(BATCH_SIZE):\n        output_img = (255 * de_norm(fake_img[i])).astype(np.uint8)\n        output_img = cv2.resize(output_img, (400, 400))\n        cv2.imwrite(f'generated/fake{str(e)}.png', output_img)\n    #     save_image(fake_img, f\"generated/fake{str(e)}.png\", range=(-1.0, 1.0), normalize=True)\n    \ndef saving_logs(result):\n    with open(\"train.pkl\", \"wb\") as f:\n        pickle.dump([result], f)\n        \ndef saving_model(D, G, e):\n    os.makedirs(\"weight\", exist_ok=True)\n    torch.save(G.state_dict(), f\"weight/G{str(e+1)}.pth\")\n    torch.save(D.state_dict(), f\"weight/D{str(e+1)}.pth\")\n        \ndef show_losses(g, d):\n    fig, axes = plt.subplots(1, 2, figsize=(14,6))\n    ax = axes.ravel()\n    ax[0].plot(np.arange(len(g)).tolist(), g)\n    ax[0].set_title(\"Generator Loss\")\n    ax[1].plot(np.arange(len(d)).tolist(), d)\n    ax[1].set_title(\"Discriminator Loss\")\n    plt.show()\n\n\ndef train_loop(train_dl, G, D, num_epoch, lr=0.0002, betas=(0.5, 0.999)):\n    G.to(device)\n    D.to(device)\n    optimizer_g = torch.optim.Adam(G.parameters(), lr=lr, betas=betas)\n    optimizer_d = torch.optim.Adam(D.parameters(), lr=lr, betas=betas)\n    criterion_mae = nn.L1Loss()\n    criterion_bce = nn.BCEWithLogitsLoss()\n    total_loss_d, total_loss_g = [], []\n    result = {}\n    \n    for e in range(num_epoch):\n        loss_g, loss_d, fake_img = train_fn(train_dl, G, D, criterion_bce, criterion_mae, optimizer_g, optimizer_d)\n        total_loss_d.append(loss_d)\n        total_loss_g.append(loss_g)\n        saving_img(fake_img, e+1)\n        \n        if e%10 == 0:\n            saving_model(D, G, e)\n    try:\n        result[\"G\"] = total_loss_d \n        result[\"D\"] = total_loss_g \n        saving_logs(result)\n        show_losses(total_loss_g, total_loss_d)\n    finally:\n        return G, D \n    \n    saving_model(D, G, num_epoch)\n    print(\"successfully save model\")","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:37.857963Z","iopub.execute_input":"2022-09-09T03:48:37.858274Z","iopub.status.idle":"2022-09-09T03:48:37.882010Z","shell.execute_reply.started":"2022-09-09T03:48:37.858240Z","shell.execute_reply":"2022-09-09T03:48:37.881319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"G = Generator()\nD = Discriminator()\nG.weight_init(mean=0.0, std=0.02)\nD.weight_init(mean=0.0, std=0.02)\n\nEPOCH = 200 \ntrained_G, trained_D = train_loop(train_dl, G, D, EPOCH)","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:48:37.883068Z","iopub.execute_input":"2022-09-09T03:48:37.883458Z","iopub.status.idle":"2022-09-09T03:49:27.527154Z","shell.execute_reply.started":"2022-09-09T03:48:37.883417Z","shell.execute_reply":"2022-09-09T03:49:27.525926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_model(name):\n    G = Generator()\n    G.load_state_dict(torch.load(f\"weight/G{name}.pth\", map_location={\"cuda:0\": \"cpu\"}))\n    G.eval()\n    return G.to(device)\n\ndef train_show_img(name, G):\n#     G = load_model(name)\n    root = \"generated\"\n    fig, axes = plt.subplots(1, int(name), figsize=(36, 36))\n    ax = axes.ravel()\n    for i in range(int(name)):\n        filename = os.path.join(root, f\"fake{str(i+1)}.png\")\n        ax[i].imshow(Image.open(filename))\n        ax[i].set_xticks([])\n        ax[i].set_yticks([])\n\ndef evaluate(val_dl, name, G):\n    with torch.no_grad():\n        fig, axes = plt.subplots(6, 8, figsize=(36, 36))\n        ax = axes.ravel()\n#         G = load_model(name)\n        for input_img, real_img in tqdm(val_dl):\n            input_img = input_img.to(device)\n            real_img = real_img.to(device)\n            \n            fake_img = G(input_img)\n            batch_size = input_img.size()[0]\n            batch_size_2 = batch_size * 2 \n            \n            for i in range(batch_size):\n                ax[i].imshow(input_img[i].permute(1, 2, 0).cpu())\n                ax[i+batch_size].imshow(de_norm(real_img[i].cpu()))\n                ax[i+batch_size_2].imshow(de_norm(fake_img[i].cpu()))\n                ax[i].set_xticks([])\n                ax[i].set_yticks([])\n                ax[i+batch_size].set_xticks([])\n                ax[i+batch_size].set_yticks([])\n                ax[i+batch_size_2].set_xticks([])\n                ax[i+batch_size_2].set_yticks([])\n                if i == 0:\n                    ax[i].set_ylabel(\"Input Image\", c=\"g\")\n                    ax[i+batch_size].set_ylabel(\"Real Image\", c=\"g\")\n                    ax[i+batch_size_2].set_ylabel(\"Generated Image\", c=\"r\")\n            plt.subplots_adjust(wspace=0, hspace=0)\n            break   ","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:49:27.528396Z","iopub.status.idle":"2022-09-09T03:49:27.528838Z","shell.execute_reply.started":"2022-09-09T03:49:27.528601Z","shell.execute_reply":"2022-09-09T03:49:27.528626Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_show_img(5, trained_G)","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:49:27.530488Z","iopub.status.idle":"2022-09-09T03:49:27.531530Z","shell.execute_reply.started":"2022-09-09T03:49:27.531297Z","shell.execute_reply":"2022-09-09T03:49:27.531322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"evaluate(val_dl, 5, trained_G)","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:49:27.532774Z","iopub.status.idle":"2022-09-09T03:49:27.533187Z","shell.execute_reply.started":"2022-09-09T03:49:27.532964Z","shell.execute_reply":"2022-09-09T03:49:27.532986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Result preparation:","metadata":{}},{"cell_type":"markdown","source":"### Once the solution is ready, make the submission with the following steps:","metadata":{}},{"cell_type":"code","source":"TEST_DIR = BASE_DIR+\"/test/test/\"\nOUTPUT_DIR = \"/kaggle/working/results\"\n\ntry:\n    os.mkdir(OUTPUT_DIR)\nexcept Exception:\n    pass\nfinal_img_paths = sorted(glob(TEST_DIR+\"*.png\"))\nlen(final_img_paths)","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:49:27.535179Z","iopub.status.idle":"2022-09-09T03:49:27.536115Z","shell.execute_reply.started":"2022-09-09T03:49:27.535879Z","shell.execute_reply":"2022-09-09T03:49:27.535902Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### We have to predict/recreate 300 cleaned images from the given test set to make submissions","metadata":{}},{"cell_type":"code","source":"transformer = Transform()\nfor i,full_pth in enumerate(final_img_paths):\n    name = i+1\n    pth = full_pth.split('/')[-1]\n    img = cv2.imread(TEST_DIR+pth.strip())\n    with torch.no_grad():\n        img = transformer(Image.fromarray(img))\n        img = img.unsqueeze(0).to(device)\n        res_img = G(img)\n        output_img = (255 * de_norm(res_img[0].cpu())).astype(np.uint8)\n        output_img = cv2.resize(output_img, (400, 400))\n        \n        smoothed = cv2.GaussianBlur(output_img, (9, 9), 10)\n        unsharped = cv2.addWeighted(output_img, 1.5, smoothed, -0.5, 0)\n        gray = cv2.cvtColor(unsharped, cv2.COLOR_BGR2GRAY)\n        cv2.imwrite(f'{OUTPUT_DIR}/{i}.png', gray)","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:49:27.537190Z","iopub.status.idle":"2022-09-09T03:49:27.538869Z","shell.execute_reply.started":"2022-09-09T03:49:27.538628Z","shell.execute_reply":"2022-09-09T03:49:27.538653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Visualize the test set:","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(20, 5))\nfor i,pth in enumerate(final_img_paths[0:20]):\n    im = cv2.imread(pth, 0)\n    plt.subplot(2, 10, i+1)\n    plt.imshow(im, cmap='gray')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:49:27.540080Z","iopub.status.idle":"2022-09-09T03:49:27.540830Z","shell.execute_reply.started":"2022-09-09T03:49:27.540544Z","shell.execute_reply":"2022-09-09T03:49:27.540572Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Visualize some of the results:","metadata":{}},{"cell_type":"code","source":"results_img_paths = glob(f'{OUTPUT_DIR}/*.png')\nplt.figure(figsize=(20, 5))\n\nfor i,pth in enumerate(results_img_paths[0:20]):\n    im = cv2.imread(pth, 0)\n    plt.subplot(2, 10, i+1)\n    plt.imshow(im, cmap='gray')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:49:27.542273Z","iopub.status.idle":"2022-09-09T03:49:27.543037Z","shell.execute_reply.started":"2022-09-09T03:49:27.542744Z","shell.execute_reply":"2022-09-09T03:49:27.542772Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Make a submission:","metadata":{}},{"cell_type":"markdown","source":"To create submission.csv file, run the following code block...","metadata":{}},{"cell_type":"code","source":"# Make_submission.py:\nimport random\nimport os\nimport cv2\n\n################################################################################\n# CHANGE THIS\n################################################################################\ncleaned_images_dir = OUTPUT_DIR\n\n################################################################################\n# DON'T CHANGE ANYTHING BELOW HERE\n################################################################################\ndef select_pixels(img):\n    y,x = img.shape\n\n    pixels = list()\n\n    for i in range(10000):\n        pixel = (random.randrange(y), random.randrange(x))\n\n        if pixel not in pixels:\n            pixels.append(pixel)\n\n    return pixels\n\nrandom.seed(0)\ncleaned_images = sorted(os.listdir(cleaned_images_dir))\n\nwith open(\"submission.csv\", \"w\") as submission_file:\n    submission_file.write(\"id,predicted\\n\")\n\n    filenum = 1\n    for image in cleaned_images:\n\n        img = cv2.imread(\"{}/{}\".format(cleaned_images_dir, image), cv2.IMREAD_GRAYSCALE)\n        pixels = select_pixels(img)\n\n        for pixel in pixels:\n            y,x = pixel\n            submission_file.write(\"{}_{}_{},{}\\n\".format(filenum, y, x, img[y][x]/255.0))\n\n        filenum += 1","metadata":{"execution":{"iopub.status.busy":"2022-09-09T03:49:27.544277Z","iopub.status.idle":"2022-09-09T03:49:27.544917Z","shell.execute_reply.started":"2022-09-09T03:49:27.544681Z","shell.execute_reply":"2022-09-09T03:49:27.544706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# The world belongs to those who READ! Let's make shabby pages readable, those are not to be thrown in the trash! :D\n# Thanks!","metadata":{}},{"cell_type":"markdown","source":"> ","metadata":{}}]}