Files
2026-07-13 13:30:30 +08:00

683 lines
24 KiB
Plaintext

{
"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": [
"# Virtual Try-On: 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/virtual_try_on.ipynb\">\n",
" <img width=\"32px\" src=\"https://www.gstatic.com/pantheon/images/bigquery/welcome_page/colab-logo.svg\" alt=\"Google Colaboratory logo\"><br> Open in Colab\n",
" </a>\n",
" </td>\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://console.cloud.google.com/agent-platform/colab/import/https:%2F%2Fraw.githubusercontent.com%2FGoogleCloudPlatform%2Fgenerative-ai%2Fmain%2Fvision%2Fgetting-started%2Fvirtual_try_on.ipynb\">\n",
" <img width=\"32px\" src=\"https://lh3.googleusercontent.com/JmcxdQi-qOpctIvWKgPtrzZdJJK-J3sWE1RsfjZNwshCFgE_9fULcNpuXYTilIR2hjwN\" alt=\"Google Cloud Colab Enterprise logo\"><br> Open in Colab Enterprise\n",
" </a>\n",
" </td>\n",
" <td style=\"text-align: center\">\n",
" <a href=\"https://console.cloud.google.com/agent-platform/workbench/instances?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/generative-ai/main/vision/getting-started/virtual_try_on.ipynb\">\n",
" <img width=\"32px\" src=\"https://storage.googleapis.com/github-repo/workbench-icon.svg\" alt=\"Workbench logo\"><br> Open in 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/virtual_try_on.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",
"<p>\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/virtual_try_on.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/virtual_try_on.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/virtual_try_on.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/virtual_try_on.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/virtual_try_on.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",
"</p>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "EXljS1-Ib0ue"
},
"source": [
"| Authors |\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",
"### Virtual Try-On\n",
"\n",
"[Virtual Try-On](https://cloud.google.com/vertex-ai/generative-ai/docs/image/generate-virtual-try-on-images) uses Google's cutting-edge image generation models to create high-quality images of people virtually trying on clothes. By providing an image of a model and a clothing item, you can generate a new image of the model wearing that product.\n",
"\n",
"In this tutorial, you will learn how to use the Google Gen AI SDK for Python to interact with the Virtual Try-On model to:\n",
"- Try-on multiple clothing items from locally stored images\n",
"- Try-on a clothing item in Cloud Storage with an Imagen generated person\n",
"\n",
"Learn more about [quotas](https://cloud.google.com/vertex-ai/generative-ai/docs/models/imagen/virtual-try-on-preview-08-04) and [pricing](https://cloud.google.com/vertex-ai/generative-ai/pricing#imagen-models) for Virtual Try-On in the product documentation."
]
},
{
"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": null,
"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": "Sh5eUOaLsJ46"
},
"source": [
"### Import libraries"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ybBXSukZkgjg"
},
"source": [
"### Set Google Cloud project information\n",
"\n",
"To get started using Agent Platform, you must have an existing Google Cloud project and [enable the Agent Platform API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com).\n",
"\n",
"Learn more about [setting up a project](https://docs.cloud.google.com/resource-manager/docs/creating-managing-projects) and a [development environment](https://cloud.google.com/docs/authentication/set-up-adc-local-dev-environment)."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"id": "q7YvbXXdtzDT"
},
"outputs": [],
"source": [
"import os\n",
"import typing\n",
"import urllib.request\n",
"\n",
"import IPython.display\n",
"import matplotlib.image as img\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\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",
" GenerateImagesConfig,\n",
" Image,\n",
" ProductImage,\n",
" RecontextImageConfig,\n",
" RecontextImageSource,\n",
")\n",
"\n",
"# fmt: off\n",
"PROJECT_ID = \"[your-project-id]\" # @param {type: \"string\", placeholder: \"[your-project-id]\", isTemplate: true}\n",
"# fmt: on\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(enterprise=True, project=PROJECT_ID, location=LOCATION)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ic4fVqs8skdA"
},
"source": [
"### Define helper functions to display media"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"id": "hk8bfm7Xsvg8"
},
"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": "qnEcP0UUsy-_"
},
"source": [
"### Load the image models"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"id": "w_TfEzggs2fp"
},
"outputs": [],
"source": [
"virtual_try_on = \"virtual-try-on-001\"\n",
"image_generation = \"imagen-4.0-generate-001\""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "fU32286ooc8Q"
},
"source": [
"## Virtual Try-On with local files\n",
"\n",
"In this section, you'll download images of a person and clothing items to try them on from local files.\n",
"\n",
"Supported Clothing:\n",
" - **Tops:** shirts, hoodies, sweaters, tank tops, blouses\n",
" - **Bottoms:** pants, leggings, shorts, skirts\n",
" - **Other:** shoes, full body items\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "faTZezkUs7KP"
},
"source": [
"### Download an image of a person\n",
"\n",
"First, download an image of a person. The following example uses an image from Cloud Storage. If you prefer to use a different image, you can either change the URL in the `wget` command or, if you have a local file, update the `person_image` variable in the subsequent step."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "19kR3OR7Fwgv"
},
"outputs": [],
"source": [
"!wget https://storage.googleapis.com/cloud-samples-data/generative-ai/image/man-in-field.png"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "p04U4s73tRe2"
},
"source": [
"If you'd like to use a different local image, modify the file name in `person_image`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Spzul-ObF00N"
},
"outputs": [],
"source": [
"person_image = \"man-in-field.png\" # @param {type: 'string'}\n",
"\n",
"display_local_image([person_image])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "SRgtZr0YteN2"
},
"source": [
"### Download clothing images\n",
"\n",
"Next, download the clothing images. The examples below are stored in Cloud Storage, but you can use your own by modifying the URLs or by specifying the paths to local images in the next step."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "b5HxMgDpMQta"
},
"outputs": [],
"source": [
"!wget https://storage.googleapis.com/cloud-samples-data/generative-ai/image/sweater.jpg\n",
"\n",
"!wget https://storage.googleapis.com/cloud-samples-data/generative-ai/image/trousers.jpg"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "mm-jYPq5t7yN"
},
"source": [
"If you'd like to use a different top, modify the file name in `top_image`. The same goes for the file name in `bottom_image`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "IY0LHYHfMjkK"
},
"outputs": [],
"source": [
"top_image = \"sweater.jpg\" # @param {type: 'string'}\n",
"bottom_image = \"trousers.jpg\" # @param {type: 'string'}\n",
"\n",
"display_local_image([top_image, bottom_image])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "mTgQo5Hauk92"
},
"source": [
"### Send the request\n",
"\n",
"With the Virtual Try-On model, you can only specify one clothing item to try on at a time. Since this example has two clothing items, you'll need to make two separate requests. In each call, you can specify the following parameters in addition to the `person_image` and `product_images`:\n",
" - **Number of images:** 1 - 4\n",
"\n",
"You'll save the output image locally so that it can be referenced in the next step."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "RHnSHJl-t8ud"
},
"outputs": [],
"source": [
"response = client.models.recontext_image(\n",
" model=virtual_try_on,\n",
" source=RecontextImageSource(\n",
" person_image=Image.from_file(location=person_image),\n",
" product_images=[\n",
" ProductImage(product_image=Image.from_file(location=top_image))\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",
"response.generated_images[0].image.save(\"try-on.jpeg\")\n",
"display_image(response.generated_images[0].image)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cP_gkDUVx-3Z"
},
"source": [
"When generating images you can also set the `safety_filter_level` parameter accordingly:\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": "JKtLpyrZ3wA5"
},
"outputs": [],
"source": [
"response = client.models.recontext_image(\n",
" model=virtual_try_on,\n",
" source=RecontextImageSource(\n",
" person_image=Image.from_file(location=\"try-on.jpeg\"),\n",
" product_images=[\n",
" ProductImage(product_image=Image.from_file(location=bottom_image))\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",
"display_image(response.generated_images[0].image)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "TmLGH9LAd371"
},
"source": [
"### Try-on multiple items at once\n",
"\n",
"By combining multiple clothing items into one photo, you can have the model try-on multiple clothing items in one request. You'll start by downloading and displaying a new model image and outfit image for this example. Like before, you can use your own images by modifying the URLs."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "na3_ELDnefNI"
},
"outputs": [],
"source": [
"!wget https://storage.googleapis.com/cloud-samples-data/generative-ai/image/woman.jpeg\n",
"\n",
"!wget https://storage.googleapis.com/cloud-samples-data/generative-ai/image/outfit.png\n",
"\n",
"person_image = \"woman.jpeg\" # @param {type: 'string'}\n",
"outfit_image = \"outfit.png\" # @param {type: 'string'}\n",
"\n",
"display_local_image([person_image, outfit_image])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "xMKIaRsWgxSw"
},
"source": [
"Now, you'll send the request."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "bhJhmUraWngz"
},
"outputs": [],
"source": [
"response = client.models.recontext_image(\n",
" model=virtual_try_on,\n",
" source=RecontextImageSource(\n",
" person_image=Image.from_file(location=person_image),\n",
" product_images=[\n",
" ProductImage(product_image=Image.from_file(location=outfit_image))\n",
" ],\n",
" ),\n",
" config=RecontextImageConfig(\n",
" output_mime_type=\"image/png\",\n",
" number_of_images=1,\n",
" safety_filter_level=\"BLOCK_LOW_AND_ABOVE\",\n",
" ),\n",
")\n",
"display_image(response.generated_images[0].image)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "mBLJtICO8iMQ"
},
"source": [
"## Virtual Try-On with files in Cloud Storage\n",
"\n",
"In this section, you'll use images of a clothing item stored in Cloud Storage and a person generated with Imagen for virtual try-on."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "08ZEbEDgyyCB"
},
"source": [
"### Generate an image of a person\n",
"\n",
"In this example, you'll generate a person to try on the clothing item with Imagen. Run the step below and change the prompt if you see fit."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "I9caIrZ7Dek1"
},
"outputs": [],
"source": [
"prompt = \"\"\"\n",
"A high-resolution, full-body, head-on photograph of a woman standing in a photography studio wearing jeans and a white t-shirt. The backdrop is clean and neutral.\n",
"\"\"\"\n",
"\n",
"image = client.models.generate_images(\n",
" model=image_generation,\n",
" prompt=prompt,\n",
" config=GenerateImagesConfig(\n",
" output_mime_type=\"image/jpeg\",\n",
" number_of_images=1,\n",
" image_size=\"2K\",\n",
" safety_filter_level=\"BLOCK_MEDIUM_AND_ABOVE\",\n",
" ),\n",
")\n",
"display_image(image.generated_images[0].image)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "l2p7TJtXzhpM"
},
"source": [
"### View clothing image\n",
"\n",
"Here, you'll view the clothing image that is stored in Cloud Storage. If you'd like, you can modify the URL below to use a different image in Cloud Storage."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "qj70GAQjfCPC"
},
"outputs": [],
"source": [
"clothing_image = PIL_Image.open(\n",
" urllib.request.urlopen(\n",
" \"https://storage.googleapis.com/cloud-samples-data/generative-ai/image/dress.jpg\"\n",
" )\n",
")\n",
"\n",
"# Display the image\n",
"fig, axis = plt.subplots(1, 2, figsize=(12, 6))\n",
"axis[0].imshow(clothing_image)\n",
"for ax in axis:\n",
" ax.axis(\"off\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "P-yAQ2rt_pll"
},
"source": [
"### Send the request\n",
"\n",
"By default, a digital watermark, or [SynthID](https://deepmind.google/technologies/synthid/), is added to images. If you would like to explicitly set the watermark to True, you can do so with the `add_watermark` parameter."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "c9N8l0oo_cWs"
},
"outputs": [],
"source": [
"response = client.models.recontext_image(\n",
" model=virtual_try_on,\n",
" source=RecontextImageSource(\n",
" person_image=image.generated_images[0].image,\n",
" product_images=[\n",
" ProductImage(\n",
" product_image=Image(\n",
" gcs_uri=\"gs://cloud-samples-data/generative-ai/image/dress.jpg\"\n",
" )\n",
" )\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",
"display_image(response.generated_images[0].image)"
]
}
],
"metadata": {
"colab": {
"name": "virtual_try_on.ipynb",
"toc_visible": true
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
}
},
"nbformat": 4,
"nbformat_minor": 0
}