{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Marrying Grounding DINO with Stable Diffusion for Image Editing\n",
    "\n",
    "\n",
    "[![GitHub](https://badges.aleen42.com/src/github.svg)](https://github.com/IDEA-Research/GroundingDINO)\n",
    "[![arXiv](https://img.shields.io/badge/arXiv-2303.05499-b31b1b.svg)](https://arxiv.org/abs/2303.05499) \n",
    "[![YouTube](https://badges.aleen42.com/src/youtube.svg)](https://youtu.be/wxWDt5UiwY8)\n",
    "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/roboflow-ai/notebooks/blob/main/notebooks/zero-shot-object-detection-with-grounding-dino.ipynb)\n",
    "[![YouTube](https://badges.aleen42.com/src/youtube.svg)](https://youtu.be/cMa77r3YrDk)\n",
    "[![HuggingFace space](https://img.shields.io/badge/🤗-HuggingFace%20Space-cyan.svg)](https://huggingface.co/spaces/ShilongLiu/Grounding_DINO_demo)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![gdsd](https://huggingface.co/ShilongLiu/GroundingDINO/resolve/main/gdsd_example.png)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Install diffusers "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...\n",
      "To disable this warning, you can either:\n",
      "\t- Avoid using `tokenizers` before the fork if possible\n",
      "\t- Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)\n",
      "Requirement already satisfied: diffusers in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (0.14.0)\n",
      "Requirement already satisfied: transformers in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (4.27.4)\n",
      "Requirement already satisfied: accelerate in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (0.18.0)\n",
      "Requirement already satisfied: scipy in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (1.7.3)\n",
      "Requirement already satisfied: safetensors in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (0.3.0)\n",
      "Requirement already satisfied: requests in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from diffusers) (2.28.1)\n",
      "Requirement already satisfied: Pillow in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from diffusers) (9.2.0)\n",
      "Requirement already satisfied: regex!=2019.12.17 in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from diffusers) (2022.7.25)\n",
      "Requirement already satisfied: numpy in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from diffusers) (1.21.6)\n",
      "Requirement already satisfied: filelock in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from diffusers) (3.9.0)\n",
      "Requirement already satisfied: huggingface-hub>=0.10.0 in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from diffusers) (0.13.3)\n",
      "Requirement already satisfied: importlib-metadata in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from diffusers) (4.12.0)\n",
      "Requirement already satisfied: tqdm>=4.27 in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from transformers) (4.64.0)\n",
      "Requirement already satisfied: tokenizers!=0.11.3,<0.14,>=0.11.1 in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from transformers) (0.13.3)\n",
      "Requirement already satisfied: packaging>=20.0 in /home/liushilong/.local/lib/python3.7/site-packages (from transformers) (21.0)\n",
      "Requirement already satisfied: pyyaml>=5.1 in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from transformers) (6.0)\n",
      "Requirement already satisfied: torch>=1.4.0 in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from accelerate) (1.12.1+cu113)\n",
      "Requirement already satisfied: psutil in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from accelerate) (5.9.4)\n",
      "Requirement already satisfied: typing-extensions>=3.7.4.3 in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from huggingface-hub>=0.10.0->diffusers) (4.3.0)\n",
      "Requirement already satisfied: pyparsing>=2.0.2 in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from packaging>=20.0->transformers) (3.0.9)\n",
      "Requirement already satisfied: zipp>=0.5 in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from importlib-metadata->diffusers) (3.8.1)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from requests->diffusers) (3.3)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from requests->diffusers) (2022.6.15)\n",
      "Requirement already satisfied: charset-normalizer<3,>=2 in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from requests->diffusers) (2.1.0)\n",
      "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /home/liushilong/anaconda3/envs/ideadet2/lib/python3.7/site-packages (from requests->diffusers) (1.26.11)\n"
     ]
    }
   ],
   "source": [
    "! pip install diffusers transformers accelerate scipy safetensors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"2\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import argparse\n",
    "from functools import partial\n",
    "import cv2\n",
    "import requests\n",
    "\n",
    "from io import BytesIO\n",
    "from PIL import Image\n",
    "import numpy as np\n",
    "from pathlib import Path\n",
    "\n",
    "\n",
    "import warnings\n",
    "warnings.filterwarnings(\"ignore\")\n",
    "\n",
    "\n",
    "import torch\n",
    "from torchvision.ops import box_convert\n",
    "\n",
    "from groundingdino.models import build_model\n",
    "from groundingdino.util.slconfig import SLConfig\n",
    "from groundingdino.util.utils import clean_state_dict\n",
    "from groundingdino.util.inference import annotate, load_image, predict\n",
    "import groundingdino.datasets.transforms as T\n",
    "\n",
    "from huggingface_hub import hf_hub_download\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Load grounding dino models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def load_model_hf(repo_id, filename, ckpt_config_filename, device='cpu'):\n",
    "    cache_config_file = hf_hub_download(repo_id=repo_id, filename=ckpt_config_filename)\n",
    "\n",
    "    args = SLConfig.fromfile(cache_config_file) \n",
    "    model = build_model(args)\n",
    "    args.device = device\n",
    "\n",
    "    cache_file = hf_hub_download(repo_id=repo_id, filename=filename)\n",
    "    checkpoint = torch.load(cache_file, map_location='cpu')\n",
    "    log = model.load_state_dict(clean_state_dict(checkpoint['model']), strict=False)\n",
    "    print(\"Model loaded from {} \\n => {}\".format(cache_file, log))\n",
    "    _ = model.eval()\n",
    "    return model    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Use this command for evaluate the Grounding DINO model\n",
    "# Or you can download the model by yourself\n",
    "ckpt_repo_id = \"ShilongLiu/GroundingDINO\"\n",
    "ckpt_filenmae = \"groundingdino_swint_ogc.pth\"\n",
    "ckpt_config_filename = \"GroundingDINO_SwinT_OGC.cfg.py\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "final text_encoder_type: bert-base-uncased\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Some weights of the model checkpoint at bert-base-uncased were not used when initializing BertModel: ['cls.predictions.transform.LayerNorm.bias', 'cls.predictions.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.seq_relationship.weight', 'cls.predictions.transform.dense.bias', 'cls.predictions.transform.dense.weight', 'cls.seq_relationship.bias']\n",
      "- This IS expected if you are initializing BertModel from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n",
      "- This IS NOT expected if you are initializing BertModel from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model loaded from /home/liushilong/.cache/huggingface/hub/models--ShilongLiu--GroundingDINO/snapshots/4d4409dc29f29629f4ebb808a68ea67be53886b6/groundingdino_swint_ogc.pth \n",
      " => _IncompatibleKeys(missing_keys=[], unexpected_keys=['label_enc.weight'])\n"
     ]
    }
   ],
   "source": [
    "model = load_model_hf(ckpt_repo_id, ckpt_filenmae, ckpt_config_filename)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Load stable diffusion inpainting models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Fetching 13 files: 100%|██████████| 13/13 [00:00<00:00, 44656.80it/s]\n"
     ]
    }
   ],
   "source": [
    "from diffusers import StableDiffusionInpaintPipeline\n",
    "\n",
    "pipe = StableDiffusionInpaintPipeline.from_pretrained(\n",
    "    \"stabilityai/stable-diffusion-2-inpainting\",\n",
    "    torch_dtype=torch.float16,\n",
    ")\n",
    "\n",
    "pipe = pipe.to(\"cuda\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Load demo image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "image_url = 'https://huggingface.co/ShilongLiu/GroundingDINO/resolve/main/cats.png'\n",
    "local_image_path = 'cats.png'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Image downloaded from url: https://huggingface.co/ShilongLiu/GroundingDINO/resolve/main/cats.png and saved to: cats.png.\n"
     ]
    }
   ],
   "source": [
    "import io\n",
    "\n",
    "\n",
    "def download_image(url, image_file_path):\n",
    "    r = requests.get(url, timeout=4.0)\n",
    "    if r.status_code != requests.codes.ok:\n",
    "        assert False, 'Status code error: {}.'.format(r.status_code)\n",
    "\n",
    "    with Image.open(io.BytesIO(r.content)) as im:\n",
    "        im.save(image_file_path)\n",
    "\n",
    "    print('Image downloaded from url: {} and saved to: {}.'.format(url, image_file_path))\n",
    "\n",
    "download_image(image_url, local_image_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Run Grounding DINO"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 131,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import supervision as sv\n",
    "\n",
    "\n",
    "TEXT_PROMPT = \"the black cat .\"\n",
    "BOX_TRESHOLD = 0.45\n",
    "TEXT_TRESHOLD = 0.25\n",
    "\n",
    "image_source, image = load_image(local_image_path)\n",
    "\n",
    "boxes, logits, phrases = predict(\n",
    "    model=model, \n",
    "    image=image, \n",
    "    caption=TEXT_PROMPT, \n",
    "    box_threshold=BOX_TRESHOLD, \n",
    "    text_threshold=TEXT_TRESHOLD\n",
    ")\n",
    "\n",
    "annotated_frame = annotate(image_source=image_source, boxes=boxes, logits=logits, phrases=phrases)\n",
    "annotated_frame = annotated_frame[...,::-1] # BGR to RGB\n",
    "\n",
    "# image_source: np.ndarray\n",
    "# annotated_frame: np.ndarray"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 132,
   "metadata": {},
   "outputs": [],
   "source": [
    "def generate_masks_with_grounding(image_source, boxes):\n",
    "    h, w, _ = image_source.shape\n",
    "    boxes_unnorm = boxes * torch.Tensor([w, h, w, h])\n",
    "    boxes_xyxy = box_convert(boxes=boxes_unnorm, in_fmt=\"cxcywh\", out_fmt=\"xyxy\").numpy()\n",
    "    mask = np.zeros_like(image_source)\n",
    "    for box in boxes_xyxy:\n",
    "        x0, y0, x1, y1 = box\n",
    "        mask[int(y0):int(y1), int(x0):int(x1), :] = 255\n",
    "    return mask"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {},
   "outputs": [],
   "source": [
    "image_mask = generate_masks_with_grounding(image_source, boxes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 508812 characters]",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=854x479>"
      ]
     },
     "execution_count": 134,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Image.fromarray(image_source)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 509836 characters]",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=854x479>"
      ]
     },
     "execution_count": 135,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Image.fromarray(annotated_frame)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1YAAAHfCAIAAADcHt4FAAAH1UlEQVR4nO3WwQnAIAAEQU3/PZseQlBwZyq417FjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFxknh4At1lrnZ5AwpwOHPjuOT0AAIDdJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAIAcCQgAkCMBAQByJCAAQI4EBADIkYAAADkSEAAgRwICAORIQACAHAkIAJAjAQEAciQgAECOBAQAyJGAAAA5EhAAIEcCAgDkSEAAgBwJCACQIwEBAHIkIABAjgQEAMiRgAAAORIQACBHAgIA5EhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD41QsduwXQaxIvPgAAAABJRU5ErkJggg==",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=854x479>"
      ]
     },
     "execution_count": 136,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Image.fromarray(image_mask)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "metadata": {},
   "outputs": [],
   "source": [
    "# image_source"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Image Inpainting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "image_source = Image.fromarray(image_source)\n",
    "annotated_frame = Image.fromarray(annotated_frame)\n",
    "image_mask = Image.fromarray(image_mask)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "image_source_for_inpaint = image_source.resize((512, 512))\n",
    "image_mask_for_inpaint = image_mask.resize((512, 512))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 50/50 [00:02<00:00, 22.20it/s]\n"
     ]
    }
   ],
   "source": [
    "prompt = \"a cute dinosaur\"\n",
    "#image and mask_image should be PIL images.\n",
    "#The mask structure is white for inpainting and black for keeping as is\n",
    "image_inpainting = pipe(prompt=prompt, image=image_source_for_inpaint, mask_image=image_mask_for_inpaint).images[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "image_inpainting = image_inpainting.resize((image_source.size[0], image_source.size[1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 596248 characters]",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=854x479>"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "image_inpainting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.12"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
