{"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":"import numpy as np \nimport matplotlib.pyplot as plt\n\nimport json\nimport os\nimport random\n\nimport torch\nimport torch.nn as nn\n\nimport torchvision.models as models\nimport torchvision.transforms as transforms\n\n\n%matplotlib inline","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-05-29T08:31:26.256569Z","iopub.execute_input":"2022-05-29T08:31:26.256924Z","iopub.status.idle":"2022-05-29T08:31:26.266111Z","shell.execute_reply.started":"2022-05-29T08:31:26.256885Z","shell.execute_reply":"2022-05-29T08:31:26.264988Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.manual_seed(3001)\nimport random\n# random.seed(3001)","metadata":{"execution":{"iopub.status.busy":"2022-05-29T08:31:26.337256Z","iopub.execute_input":"2022-05-29T08:31:26.338549Z","iopub.status.idle":"2022-05-29T08:31:26.342861Z","shell.execute_reply.started":"2022-05-29T08:31:26.338492Z","shell.execute_reply":"2022-05-29T08:31:26.342181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2022-05-29T08:31:26.689901Z","iopub.execute_input":"2022-05-29T08:31:26.690194Z","iopub.status.idle":"2022-05-29T08:31:26.695287Z","shell.execute_reply.started":"2022-05-29T08:31:26.690163Z","shell.execute_reply":"2022-05-29T08:31:26.694413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Load pretrained VGG16 model for transfer learning:","metadata":{}},{"cell_type":"code","source":"# model = models.vgg16(pretrained=False)","metadata":{"execution":{"iopub.status.busy":"2022-05-29T08:31:26.697136Z","iopub.execute_input":"2022-05-29T08:31:26.697531Z","iopub.status.idle":"2022-05-29T08:31:26.705368Z","shell.execute_reply.started":"2022-05-29T08:31:26.697486Z","shell.execute_reply":"2022-05-29T08:31:26.704553Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Freeze all feature extraction layers:","metadata":{}},{"cell_type":"code","source":"# for param in model.features.parameters():\n#     param.requires_grad = False","metadata":{"execution":{"iopub.status.busy":"2022-05-29T08:31:26.706452Z","iopub.execute_input":"2022-05-29T08:31:26.707129Z","iopub.status.idle":"2022-05-29T08:31:26.716696Z","shell.execute_reply.started":"2022-05-29T08:31:26.707089Z","shell.execute_reply":"2022-05-29T08:31:26.716002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Replace the output layer with a single node:","metadata":{}},{"cell_type":"code","source":"# num_ftrs = model.classifier[6].in_features\n# model.classifier[6] = nn.Linear(num_ftrs, 1)","metadata":{"execution":{"iopub.status.busy":"2022-05-29T08:31:26.718492Z","iopub.execute_input":"2022-05-29T08:31:26.718719Z","iopub.status.idle":"2022-05-29T08:31:26.728663Z","shell.execute_reply.started":"2022-05-29T08:31:26.718692Z","shell.execute_reply":"2022-05-29T08:31:26.727923Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Train the model:","metadata":{}},{"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2022-05-29T08:31:26.730470Z","iopub.execute_input":"2022-05-29T08:31:26.730886Z","iopub.status.idle":"2022-05-29T08:31:26.740596Z","shell.execute_reply.started":"2022-05-29T08:31:26.730841Z","shell.execute_reply":"2022-05-29T08:31:26.739860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_model(checkpoint_path: str, device):\n    model = models.vgg16(pretrained=False)\n    \n    # Freeze all feature extraction layers:\n    for param in model.features.parameters():\n        param.requires_grad = False\n    \n    # Replace the output layer with a single node:\n    num_ftrs = model.classifier[6].in_features\n    model.classifier[6] = nn.Linear(num_ftrs, 1)\n    \n    # Move model to gpu if avaliable:\n    model.to(device=device, dtype = torch.float32)\n    \n    # Apply checkpoint\n    if os.path.isdir(checkpoint_path):\n        checkpoint = torch.load(os.path.join(checkpoint_path, 'model.pt'), map_location=device)\n        model.load_state_dict(checkpoint['model'])\n    #     optimizer.load_state_dict(checkpoint['optimizer'])\n        model.eval()\n        print(\"Model retrieved succesfully.\")\n        return model\n    else:\n        print(\"Model could not be found\")\n        return None","metadata":{"execution":{"iopub.status.busy":"2022-05-29T08:31:26.750214Z","iopub.execute_input":"2022-05-29T08:31:26.750950Z","iopub.status.idle":"2022-05-29T08:31:26.758875Z","shell.execute_reply.started":"2022-05-29T08:31:26.750915Z","shell.execute_reply":"2022-05-29T08:31:26.758049Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# move model to gpu if avaliable:\n# model.to(device=device, dtype = torch.float32)\n\n# if os.path.isdir('../input/image-rotation-prediction-training'):\n#     checkpoint = torch.load('../input/image-rotation-prediction-training/model.pt', map_location=device)\n#     model.load_state_dict(checkpoint['model'])\n# #     optimizer.load_state_dict(checkpoint['optimizer'])\n#     model.eval()\n#     print(\"Model retrieved succesfully.\")\n# else:\n#     print(\"Model could not be found\")\n# model = load_model('../input/image-rotation-prediction-training', device)\nmodel = load_model('../input/imagerotationexternaltrainingcheckpoint', device)","metadata":{"execution":{"iopub.status.busy":"2022-05-29T08:31:26.814328Z","iopub.execute_input":"2022-05-29T08:31:26.815007Z","iopub.status.idle":"2022-05-29T08:31:30.103400Z","shell.execute_reply.started":"2022-05-29T08:31:26.814963Z","shell.execute_reply":"2022-05-29T08:31:30.102515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import PIL\n\ndef rotate_upright(img: PIL.Image, model, device):\n    img_tensor = transforms.ToTensor()(img).unsqueeze_(0)\n    img_tensor = img_tensor.to(device=device, dtype = torch.float32)\n\n    rotation_prediction = model(img_tensor).squeeze()\n    \n    corrected_image = img.rotate(-rotation_prediction)\n    return corrected_image, rotation_prediction","metadata":{"execution":{"iopub.status.busy":"2022-05-29T08:31:30.105081Z","iopub.execute_input":"2022-05-29T08:31:30.105417Z","iopub.status.idle":"2022-05-29T08:31:30.111568Z","shell.execute_reply.started":"2022-05-29T08:31:30.105381Z","shell.execute_reply":"2022-05-29T08:31:30.110701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torchvision.transforms.functional as TF\n\nclass RotateUprightTransform:\n    \n    def __init__(self):\n        self.device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n        self.model = load_model('../input/imagerotationexternaltrainingcheckpoint', self.device)\n    \n    def load_model(checkpoint_path: str, device):\n        model = models.vgg16(pretrained=False)\n\n        # Freeze all feature extraction layers:\n        for param in model.features.parameters():\n            param.requires_grad = False\n\n        # Replace the output layer with a single node:\n        num_ftrs = model.classifier[6].in_features\n        model.classifier[6] = nn.Linear(num_ftrs, 1)\n\n        # Move model to gpu if avaliable:\n        model.to(device=device, dtype = torch.float32)\n\n        # Apply checkpoint\n        if os.path.isdir(checkpoint_path):\n            checkpoint = torch.load(os.path.join(checkpoint_path, 'model.pt'), map_location=device)\n            model.load_state_dict(checkpoint['model'])\n        #     optimizer.load_state_dict(checkpoint['optimizer'])\n            model.eval()\n            print(\"Model retrieved succesfully.\")\n            return model\n        else:\n            print(\"Model could not be found\")\n            return None\n    \n    def __call__(self, img: PIL.Image, return_angle=False):\n        img_tensor = transforms.ToTensor()(img).unsqueeze_(0)\n        img_tensor = img_tensor.to(device=self.device, dtype = torch.float32)\n\n        rotation_prediction = self.model(img_tensor).squeeze().item()\n\n        corrected_image = TF.rotate(img, rotation_prediction)#img.rotate(-rotation_prediction)\n        if return_angle:\n            return corrected_image, rotation_prediction\n        return corrected_image","metadata":{"execution":{"iopub.status.busy":"2022-05-29T08:31:30.112795Z","iopub.execute_input":"2022-05-29T08:31:30.113123Z","iopub.status.idle":"2022-05-29T08:31:30.125968Z","shell.execute_reply.started":"2022-05-29T08:31:30.113089Z","shell.execute_reply":"2022-05-29T08:31:30.125199Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import PIL\n\ndef rotate_and_crop(image: PIL.Image, angle_deg: int):\n    w_i,h_i = image.size\n    \n    rotated_expanded_image_with_padding = image.rotate(-angle_deg, expand=True)\n    w_p,h_p = rotated_expanded_image_with_padding.size\n    \n    import math\n    angle_rad = np.deg2rad(abs(angle_deg))\n    rem_deg_rad = np.deg2rad(90-(abs(angle_deg) % 90))\n    \n    w_to_remove = int(math.cos(rem_deg_rad)*h_i)\n    h_to_remove = int(math.sin(angle_rad)*w_i)\n    return rotated_expanded_image_with_padding.crop((w_to_remove,h_to_remove,w_p-w_to_remove,h_p-h_to_remove))\n\ndef randomly_rotate_image(image: PIL.Image):\n    def do_nothing(image: PIL.Image):\n        return image, 0\n\n    def rotate_with_max_degrees(image: PIL.Image, max_degrees: int = 10):\n        rotation_deg = random.randrange(-abs(max_degrees), abs(max_degrees) + 1)\n        return (rotate_and_crop(image, rotation_deg), rotation_deg)\n\n    def rotate_about_90_degrees_left(image: PIL.Image):\n        rotated_90_degrees_left = image.rotate(90, expand=True)\n        rotated_image, further_degrees = rotate_with_max_degrees(rotated_90_degrees_left, 5)\n        return (rotated_image, -90 + further_degrees)\n\n    def rotate_about_90_degrees_right(image: PIL.Image):\n        rotated_90_degrees_right = image.rotate(-90, expand=True)\n        rotated_image, further_degrees = rotate_with_max_degrees(rotated_90_degrees_right, 5)\n        return (rotated_image, 90 + further_degrees)\n\n    random_image_rotation_fun = np.random.choice(\n        [\n            do_nothing,\n            rotate_with_max_degrees,\n            rotate_about_90_degrees_left,\n            rotate_about_90_degrees_right\n        ],\n        p=[\n            0.6,\n            0.2,\n            0.1,\n            0.1\n        ]\n    )\n\n    return random_image_rotation_fun(image)","metadata":{"execution":{"iopub.status.busy":"2022-05-29T08:31:30.127634Z","iopub.execute_input":"2022-05-29T08:31:30.128008Z","iopub.status.idle":"2022-05-29T08:31:30.144813Z","shell.execute_reply.started":"2022-05-29T08:31:30.127979Z","shell.execute_reply":"2022-05-29T08:31:30.143898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import PIL\ninput_path = r'../input/hotel-id-to-combat-human-trafficking-2022-fgvc9'\ntrain_image_path = os.path.join(input_path, r\"train_images\")\n\nrandom_hotel_images_path = os.path.join(train_image_path, random.choice(os.listdir(train_image_path)))\n# random_hotel_image_path = '../input/hotel-id-to-combat-human-trafficking-2022-fgvc9/train_images/11260/000039269.jpg'\nrandom_hotel_image_path = os.path.join(random_hotel_images_path, random.choice(os.listdir(random_hotel_images_path)))\nprint(\"Random hotel folder: {}\".format(random_hotel_image_path))\nrandom_hotel_image = PIL.Image.open(random_hotel_image_path)\nprint(\"Original image dimensions: {}\".format(random_hotel_image.size))\nangle_deg = 8\n\nrotated_random_hotel_image = rotate_and_crop(random_hotel_image, angle_deg) # Temporary, for testing purposes\n\nrotate_upright_transform = RotateUprightTransform()\ncorrected_image, hotel_pred = rotate_upright_transform(rotated_random_hotel_image, True)#rotate_upright(rotated_random_hotel_image, model, device)\nprint(\"Prediction: {}\".format(hotel_pred))\n\nimport matplotlib.pyplot as plt\nf, axarr = plt.subplots(1,3)\naxarr[0].imshow(random_hotel_image)\naxarr[1].imshow(rotated_random_hotel_image)\naxarr[2].imshow(corrected_image)","metadata":{"execution":{"iopub.status.busy":"2022-05-29T08:31:30.146091Z","iopub.execute_input":"2022-05-29T08:31:30.146345Z","iopub.status.idle":"2022-05-29T08:31:37.233498Z","shell.execute_reply.started":"2022-05-29T08:31:30.146315Z","shell.execute_reply":"2022-05-29T08:31:37.232756Z"},"trusted":true},"execution_count":null,"outputs":[]}]}