{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "uxCkB_DXTHzf"
      },
      "outputs": [],
      "source": [
        "# Copyright 2025 Google LLC\n",
        "#\n",
        "# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "#     https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Hny4I-ODTIS6"
      },
      "source": [
        "# Imagen Product Recontextualization: Image Generation\n",
        "\n",
        "\n",
        "<table align=\"left\">\n",
        "  <td style=\"text-align: center\">\n",
        "    <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/generative-ai/blob/main/vision/getting-started/imagen_product_recontext.ipynb\">\n",
        "      <img src=\"https://www.gstatic.com/pantheon/images/bigquery/welcome_page/colab-logo.svg\" alt=\"Google Colaboratory logo\"><br> Run in Colab\n",
        "    </a>\n",
        "  </td>\n",
        "  <td style=\"text-align: center\">\n",
        "    <a href=\"https://console.cloud.google.com/vertex-ai/colab/import/https:%2F%2Fraw.githubusercontent.com%2FGoogleCloudPlatform%2Fgenerative-ai%2Fmain%2Fvision%2Fgetting-started%2Fimagen_product_recontext.ipynb\">\n",
        "      <img width=\"32px\" src=\"https://lh3.googleusercontent.com/JmcxdQi-qOpctIvWKgPtrzZdJJK-J3sWE1RsfjZNwshCFgE_9fULcNpuXYTilIR2hjwN\" alt=\"Google Cloud Colab Enterprise logo\"><br> Run in Colab Enterprise\n",
        "    </a>\n",
        "  </td>\n",
        "  <td style=\"text-align: center\">\n",
        "    <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/generative-ai/main/vision/getting-started/imagen_product_recontext.ipynb\">\n",
        "      <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\"><br> Open in Vertex AI Workbench\n",
        "    </a>\n",
        "  </td>    \n",
        "  <td style=\"text-align: center\">\n",
        "    <a href=\"https://github.com/GoogleCloudPlatform/generative-ai/blob/main/vision/getting-started/imagen_product_recontext.ipynb\">\n",
        "      <img width=\"32px\" src=\"https://raw.githubusercontent.com/primer/octicons/refs/heads/main/icons/mark-github-24.svg\" alt=\"GitHub logo\"><br> View on GitHub\n",
        "    </a>\n",
        "  </td>\n",
        "</table>\n",
        "\n",
        "<div style=\"clear: both;\"></div>\n",
        "\n",
        "<b>Share to:</b>\n",
        "\n",
        "<a href=\"https://www.linkedin.com/sharing/share-offsite/?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/vision/getting-started/imagen_product_recontext.ipynb\" target=\"_blank\">\n",
        "  <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/8/81/LinkedIn_icon.svg\" alt=\"LinkedIn logo\">\n",
        "</a>\n",
        "\n",
        "<a href=\"https://bsky.app/intent/compose?text=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/vision/getting-started/imagen_product_recontext.ipynb\" target=\"_blank\">\n",
        "  <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/7/7a/Bluesky_Logo.svg\" alt=\"Bluesky logo\">\n",
        "</a>\n",
        "\n",
        "<a href=\"https://twitter.com/intent/tweet?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/vision/getting-started/imagen_product_recontext.ipynb\" target=\"_blank\">\n",
        "  <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/5/5a/X_icon_2.svg\" alt=\"X logo\">\n",
        "</a>\n",
        "\n",
        "<a href=\"https://reddit.com/submit?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/vision/getting-started/imagen_product_recontext.ipynb\" target=\"_blank\">\n",
        "  <img width=\"20px\" src=\"https://redditinc.com/hubfs/Reddit%20Inc/Brand/Reddit_Logo.png\" alt=\"Reddit logo\">\n",
        "</a>\n",
        "\n",
        "<a href=\"https://www.facebook.com/sharer/sharer.php?u=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/vision/getting-started/imagen_product_recontext.ipynb\" target=\"_blank\">\n",
        "  <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/5/51/Facebook_f_logo_%282019%29.svg\" alt=\"Facebook logo\">\n",
        "</a>            \n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "EXljS1-Ib0ue"
      },
      "source": [
        "| Author |\n",
        "| --- |\n",
        "| [Jorj Ismailyan](https://github.com/jismailyan-google) |\n",
        "| [Katie Nguyen](https://github.com/katiemn) |"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-nLS57E2TO5y"
      },
      "source": [
        "## Overview\n",
        "\n",
        "With Product Recontextualization, you can use Google's cutting-edge Imagen model to generate high-quality images of your products in new scenes and backgrounds.\n",
        "\n",
        "In this tutorial, you'll learn how to use the Google Gen AI SDK for Python to:\n",
        "  - Recontextualize multiple product items from locally stored images\n",
        "  - Recontextualize a product item stored in Cloud Storage\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "mvKl-BtQTRiQ"
      },
      "source": [
        "## Get started"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "B-UOCMvJdmlq"
      },
      "source": [
        "### Install Google Gen AI SDK for Python"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "u5lOntr-doIT"
      },
      "outputs": [],
      "source": [
        "%pip install --upgrade --quiet google-genai"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "opUxT_k5TdgP"
      },
      "source": [
        "### Authenticate your notebook environment (Colab only)\n",
        "\n",
        "If you are running this notebook on Google Colab, run the following cell to authenticate your environment."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {
        "id": "vbNgv4q1T2Mi"
      },
      "outputs": [],
      "source": [
        "import sys\n",
        "\n",
        "if \"google.colab\" in sys.modules:\n",
        "    from google.colab import auth\n",
        "\n",
        "    auth.authenticate_user()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Lx4XDaC5-ZbL"
      },
      "source": [
        "### Import libraries"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "id": "Xaf2lPmI-c34"
      },
      "outputs": [],
      "source": [
        "import typing\n",
        "import urllib.request\n",
        "\n",
        "import IPython.display\n",
        "from PIL import Image as PIL_Image\n",
        "from PIL import ImageOps as PIL_ImageOps\n",
        "from google import genai\n",
        "from google.genai.types import (\n",
        "    Image,\n",
        "    ProductImage,\n",
        "    RecontextImageConfig,\n",
        "    RecontextImageSource,\n",
        ")\n",
        "import matplotlib.image as img\n",
        "import matplotlib.pyplot as plt\n",
        "import numpy as np"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ybBXSukZkgjg"
      },
      "source": [
        "### Set Google Cloud project information and create client\n",
        "\n",
        "To get started using Vertex AI, you must have an existing Google Cloud project and [enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com).\n",
        "\n",
        "Learn more about [setting up a project and a development environment](https://cloud.google.com/vertex-ai/docs/start/cloud-environment)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "id": "q7YvbXXdtzDT"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "\n",
        "PROJECT_ID = \"[your-project-id]\"  # @param {type: \"string\", placeholder: \"[your-project-id]\", isTemplate: true}\n",
        "if not PROJECT_ID or PROJECT_ID == \"[your-project-id]\":\n",
        "    PROJECT_ID = str(os.environ.get(\"GOOGLE_CLOUD_PROJECT\"))\n",
        "\n",
        "LOCATION = os.environ.get(\"GOOGLE_CLOUD_REGION\", \"us-central1\")\n",
        "\n",
        "client = genai.Client(vertexai=True, project=PROJECT_ID, location=LOCATION)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "RHzZeiPg--Ik"
      },
      "source": [
        "### Define helper functions to display media"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "id": "OOCJRU7X_A7G"
      },
      "outputs": [],
      "source": [
        "def display_image(\n",
        "    image,\n",
        "    max_width: int = 700,\n",
        "    max_height: int = 400,\n",
        ") -> None:\n",
        "    pil_image = typing.cast(PIL_Image.Image, image._pil_image)\n",
        "    if pil_image.mode != \"RGB\":\n",
        "        # RGB is supported by all Jupyter environments (e.g. RGBA is not yet)\n",
        "        pil_image = pil_image.convert(\"RGB\")\n",
        "    image_width, image_height = pil_image.size\n",
        "    if max_width < image_width or max_height < image_height:\n",
        "        # Resize to display a smaller notebook image\n",
        "        pil_image = PIL_ImageOps.contain(pil_image, (max_width, max_height))\n",
        "    IPython.display.display(pil_image)\n",
        "\n",
        "\n",
        "def display_local_image(\n",
        "    images: list[str],\n",
        ") -> None:\n",
        "    fig, axes = plt.subplots(1, len(images), figsize=(12, 6))\n",
        "    if len(images) == 1:\n",
        "        axes = np.array([axes])\n",
        "    for i, ax in enumerate(axes):\n",
        "        image = img.imread(images[i])\n",
        "        ax.imshow(image)\n",
        "        ax.axis(\"off\")\n",
        "    plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vOEaog0c_Dlj"
      },
      "source": [
        "### Load the image model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "id": "x1qGfKi-_GIq"
      },
      "outputs": [],
      "source": [
        "product_recontext = \"imagen-product-recontext-preview-06-30\""
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "fU32286ooc8Q"
      },
      "source": [
        "## Product Recontextualization with local files\n",
        "\n",
        "In this section, you'll download product images and then use them to generate new images with different backgrounds and settings.\n",
        "\n",
        "Supported Product Categories:\n",
        "  - **Business & Industrial**\n",
        "  - **Clothing**\n",
        "  - **Furniture**\n",
        "  - **Garden & Yard**\n",
        "  - **Health & Beauty**\n",
        "  - **Jewelry**\n",
        "  - **Shoes**\n",
        "  - **Sporting goods**\n",
        "  - **Toys & Games**"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "XuReHuUTKHI5"
      },
      "source": [
        "### Download product images\n",
        "\n",
        "If you want to use your own images, you can either change the URLs in the `wget` commands or, if you're using local files, update the`first_product` and `second_product` variables in the next step."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "I9caIrZ7Dek1"
      },
      "outputs": [],
      "source": [
        "!wget https://storage.googleapis.com/cloud-samples-data/generative-ai/image/perfume.jpg\n",
        "\n",
        "!wget https://storage.googleapis.com/cloud-samples-data/generative-ai/image/armchair.png"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qyKuaJoJV8R2"
      },
      "source": [
        "If you'd like to use different local images, modify the file names below."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "4jRPrSLmNm76"
      },
      "outputs": [],
      "source": [
        "first_product = \"perfume.jpg\"  # @param {type: 'string'}\n",
        "second_product = \"armchair.png\"  # @param {type: 'string'}\n",
        "\n",
        "display_local_image([first_product, second_product])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "x1203T6syOvP"
      },
      "source": [
        "### Send the request\n",
        "\n",
        "In each call, you can specify the following parameters in addition to `product_images`:\n",
        " - **Prompt:** Describe the setting you'd like the product to appear in.\n",
        " - **Enhance Prompt:** This model offers the option to enhance your provided prompt, which is enabled by default. If you'd like to disable this feature, set `enhance_prompt` to False.\n",
        " - **Number of images:** 1 - 4"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "AHaPiAlkyOvQ"
      },
      "outputs": [],
      "source": [
        "prompt = \"on a makeup vanity surrounded by a flower vase and string of pearls\"  # @param {type: 'string'}\n",
        "\n",
        "response = client.models.recontext_image(\n",
        "    model=product_recontext,\n",
        "    source=RecontextImageSource(\n",
        "        prompt=prompt,\n",
        "        product_images=[\n",
        "            ProductImage(product_image=Image.from_file(location=first_product))\n",
        "        ],\n",
        "    ),\n",
        "    config=RecontextImageConfig(\n",
        "        enhance_prompt=True,\n",
        "        output_mime_type=\"image/jpeg\",\n",
        "        number_of_images=1,\n",
        "        safety_filter_level=\"BLOCK_LOW_AND_ABOVE\",\n",
        "    ),\n",
        ")\n",
        "\n",
        "display_image(response.generated_images[0].image)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "P-yAQ2rt_pll"
      },
      "source": [
        "You can also recontextualize products without setting a `prompt` in the request. The model will generate an appropriate background based on the product image.\n",
        "\n",
        "\n",
        "When generating images you can also set the `safety_filter_level` accordingly:\n",
        "\n",
        "- `safety_filter_level`\n",
        "  - `BLOCK_LOW_AND_ABOVE`\n",
        "  - `BLOCK_MEDIUM_AND_ABOVE`\n",
        "  - `BLOCK_ONLY_HIGH`\n",
        "  - `BLOCK_NONE`"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "c9N8l0oo_cWs"
      },
      "outputs": [],
      "source": [
        "response = client.models.recontext_image(\n",
        "    model=product_recontext,\n",
        "    source=RecontextImageSource(\n",
        "        product_images=[\n",
        "            ProductImage(product_image=Image.from_file(location=second_product))\n",
        "        ],\n",
        "    ),\n",
        "    config=RecontextImageConfig(\n",
        "        output_mime_type=\"image/jpeg\",\n",
        "        number_of_images=1,\n",
        "        safety_filter_level=\"BLOCK_LOW_AND_ABOVE\",\n",
        "    ),\n",
        ")\n",
        "\n",
        "display_image(response.generated_images[0].image)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GhLTWiarWP3s"
      },
      "source": [
        "## Product Recontextualization with files in Cloud Storage\n",
        "\n",
        "In this section, you'll use an image of sneakers from Cloud Storage to generate a new product image."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "YnM_XzieWTHI"
      },
      "source": [
        "### View sneaker image\n",
        "\n",
        "The following cell displays the product image from Cloud Storage. You can change the URL to use a different image."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "e6CM25NcWVy-"
      },
      "outputs": [],
      "source": [
        "product_image = PIL_Image.open(\n",
        "    urllib.request.urlopen(\n",
        "        \"https://storage.googleapis.com/cloud-samples-data/generative-ai/image/shoes.jpg\"\n",
        "    )\n",
        ")\n",
        "\n",
        "# Display the image\n",
        "fig, axis = plt.subplots(1, 2, figsize=(12, 6))\n",
        "axis[0].imshow(product_image)\n",
        "for ax in axis:\n",
        "    ax.axis(\"off\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0qemrhZAWYm9"
      },
      "source": [
        "### Send the request\n",
        "\n",
        "A digital watermark ([SynthID](https://deepmind.google/technologies/synthid/)) is added to the images by default. You can specifically enable this by setting the `add_watermark` parameter to `True`. You can also [verify a watermarked image](https://cloud.google.com/vertex-ai/generative-ai/docs/image/verify-watermark) in Vertex AI Studio."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Gs5dial6sTRG"
      },
      "outputs": [],
      "source": [
        "# fmt: off\n",
        "prompt = \"on a running track\"  # @param {type: 'string'}\n",
        "gcs_uri = \"gs://cloud-samples-data/generative-ai/image/shoes.jpg\"  # @param {type: 'string'}\n",
        "# fmt: on\n",
        "\n",
        "\n",
        "response = client.models.recontext_image(\n",
        "    model=product_recontext,\n",
        "    source=RecontextImageSource(\n",
        "        prompt=prompt,\n",
        "        product_images=[ProductImage(product_image=Image(gcs_uri=gcs_uri))],\n",
        "    ),\n",
        "    config=RecontextImageConfig(\n",
        "        output_mime_type=\"image/jpeg\",\n",
        "        enhance_prompt=True,\n",
        "        number_of_images=1,\n",
        "        safety_filter_level=\"BLOCK_LOW_AND_ABOVE\",\n",
        "    ),\n",
        ")\n",
        "\n",
        "display_image(response.generated_images[0].image)"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "name": "imagen_product_recontext.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
