Comprensión de imágenes

Los modelos de Gemini pueden procesar imágenes, lo que permite muchos casos de uso de desarrolladores pioneros que, en el pasado, habrían requerido modelos específicos de dominio. Algunas de las capacidades de visión de Gemini incluyen las siguientes:

  • Agrega leyendas y responde preguntas sobre imágenes
  • Transcribe y razona sobre archivos PDF, incluidos hasta 2 millones de tokens
  • Detecta objetos en una imagen y muestra las coordenadas del cuadro delimitador
  • Segmenta objetos dentro de una imagen

Gemini se diseñó para ser multimodal desde cero y seguimos ampliando los límites de lo posible. En esta guía, se muestra cómo usar la API de Gemini para generar respuestas de texto basadas en entradas de imágenes y realizar tareas comunes de comprensión de imágenes.

Antes de comenzar

Antes de llamar a la API de Gemini, asegúrate de tener instalado el SDK que elijas y de que una clave de API de Gemini esté configurada y lista para usar.

Entrada de imagen

Puedes proporcionar imágenes como entrada a Gemini de las siguientes maneras:

  • Sube un archivo de imagen con la API de File antes de realizar una solicitud a generateContent. Usa este método para archivos de más de 20 MB o cuando quieras volver a usar el archivo en varias solicitudes.
  • Pasa datos de imagen intercalados con la solicitud a generateContent. Usa este método para archivos más pequeños (<20 MB de tamaño de solicitud total) o imágenes recuperadas directamente desde URLs.

Sube un archivo de imagen

Puedes usar la API de Files para subir un archivo de imagen. Usa siempre la API de Files cuando el tamaño total de la solicitud (incluido el archivo, la instrucción de texto, las instrucciones del sistema, etcétera) sea superior a 20 MB o si deseas usar la misma imagen en varias instrucciones.

El siguiente código sube un archivo de imagen y, luego, lo usa en una llamada a generateContent.

Python

from google import genai

client = genai.Client(api_key="GOOGLE_API_KEY")

myfile = client.files.upload(file="path/to/sample.jpg")

response = client.models.generate_content(
    model="gemini-2.0-flash",
    contents=[myfile, "Caption this image."])

print(response.text)

JavaScript

import {
  GoogleGenAI,
  createUserContent,
  createPartFromUri,
} from "@google/genai";

const ai = new GoogleGenAI({ apiKey: "GOOGLE_API_KEY" });

async function main() {
  const myfile = await ai.files.upload({
    file: "path/to/sample.jpg",
    config: { mimeType: "image/jpeg" },
  });

  const response = await ai.models.generateContent({
    model: "gemini-2.0-flash",
    contents: createUserContent([
      createPartFromUri(myfile.uri, myfile.mimeType),
      "Caption this image.",
    ]),
  });
  console.log(response.text);
}

await main();

Go

file, err := client.UploadFileFromPath(ctx, "path/to/sample.jpg", nil)
if err != nil {
    log.Fatal(err)
}
defer client.DeleteFile(ctx, file.Name)

model := client.GenerativeModel("gemini-2.0-flash")
resp, err := model.GenerateContent(ctx,
    genai.FileData{URI: file.URI},
    genai.Text("Caption this image."))
if err != nil {
    log.Fatal(err)
}

printResponse(resp)

REST

IMAGE_PATH="path/to/sample.jpg"
MIME_TYPE=$(file -b --mime-type "${IMAGE_PATH}")
NUM_BYTES=$(wc -c < "${IMAGE_PATH}")
DISPLAY_NAME=IMAGE

tmp_header_file=upload-header.tmp

# Initial resumable request defining metadata.
# The upload url is in the response headers dump them to a file.
curl "https://generativelanguage.googleapis.com/upload/v1beta/files?key=${GOOGLE_API_KEY}" \
  -D upload-header.tmp \
  -H "X-Goog-Upload-Protocol: resumable" \
  -H "X-Goog-Upload-Command: start" \
  -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \
  -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \
  -H "Content-Type: application/json" \
  -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null

upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r")
rm "${tmp_header_file}"

# Upload the actual bytes.
curl "${upload_url}" \
  -H "Content-Length: ${NUM_BYTES}" \
  -H "X-Goog-Upload-Offset: 0" \
  -H "X-Goog-Upload-Command: upload, finalize" \
  --data-binary "@${IMAGE_PATH}" 2> /dev/null > file_info.json

file_uri=$(jq ".file.uri" file_info.json)
echo file_uri=$file_uri

# Now generate content using that file
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GOOGLE_API_KEY" \
    -H 'Content-Type: application/json' \
    -X POST \
    -d '{
      "contents": [{
        "parts":[
          {"file_data":{"mime_type": "${MIME_TYPE}", "file_uri": '$file_uri'}},
          {"text": "Caption this image."}]
        }]
      }' 2> /dev/null > response.json

cat response.json
echo

jq ".candidates[].content.parts[].text" response.json

Para obtener más información sobre cómo trabajar con archivos multimedia, consulta la API de Files.

Pasa datos de imágenes intercalados

En lugar de subir un archivo de imagen, puedes pasar datos de imagen intercalados en la solicitud a generateContent. Esto es adecuado para imágenes más pequeñas (menos de 20 MB de tamaño de solicitud total) o imágenes recuperadas directamente desde URLs.

Puedes proporcionar datos de imagen como cadenas codificadas en base64 o leyendo archivos locales directamente (según el SDK).

Archivo de imagen local:

Python

  from google.genai import types

  with open('path/to/small-sample.jpg', 'rb') as f:
      img_bytes = f.read()

  response = client.models.generate_content(
    model='gemini-2.0-flash',
    contents=[
      types.Part.from_bytes(
        data=img_bytes,
        mime_type='image/jpeg',
      ),
      'Caption this image.'
    ]
  )

  print(response.text)

JavaScript

import { GoogleGenAI } from "@google/genai";
import * as fs from "node:fs";

const ai = new GoogleGenAI({ apiKey: "GOOGLE_API_KEY" });
const base64ImageFile = fs.readFileSync("path/to/small-sample.jpg", {
  encoding: "base64",
});

const contents = [
  {
    inlineData: {
      mimeType: "image/jpeg",
      data: base64ImageFile,
    },
  },
  { text: "Caption this image." },
];

const response = await ai.models.generateContent({
  model: "gemini-2.0-flash",
  contents: contents,
});
console.log(response.text);

Go

model := client.GenerativeModel("gemini-2.0-flash")

bytes, err := os.ReadFile("path/to/small-sample.jpg")
if err != nil {
  log.Fatal(err)
}

prompt := []genai.Part{
  genai.Blob{MIMEType: "image/jpeg", Data: bytes},
  genai.Text("Caption this image."),
}

resp, err := model.GenerateContent(ctx, prompt...)
if err != nil {
  log.Fatal(err)
}

for _, c := range resp.Candidates {
  if c.Content != nil {
    fmt.Println(*c.Content)
  }
}

REST

IMG_PATH=/path/to/your/image1.jpg

if [[ "$(base64 --version 2>&1)" = *"FreeBSD"* ]]; then
  B64FLAGS="--input"
else
  B64FLAGS="-w0"
fi

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GOOGLE_API_KEY" \
    -H 'Content-Type: application/json' \
    -X POST \
    -d '{
      "contents": [{
        "parts":[
            {
              "inline_data": {
                "mime_type":"image/jpeg",
                "data": "'\$(base64 \$B64FLAGS \$IMG_PATH)'"
              }
            },
            {"text": "Caption this image."},
        ]
      }]
    }' 2> /dev/null

Imagen de la URL:

Python

from google import genai
from google.genai import types

import requests

image_path = "https://goo.gle/instrument-img"
image = requests.get(image_path)

client = genai.Client(api_key="GOOGLE_API_KEY")
response = client.models.generate_content(
    model="gemini-2.0-flash-exp",
    contents=["What is this image?",
              types.Part.from_bytes(data=image.content, mime_type="image/jpeg")])

print(response.text)

JavaScript

import { GoogleGenAI } from "@google/genai";

async function main() {
  const ai = new GoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY });

  const imageUrl = "https://goo.gle/instrument-img";

  const response = await fetch(imageUrl);
  const imageArrayBuffer = await response.arrayBuffer();
  const base64ImageData = Buffer.from(imageArrayBuffer).toString('base64');

  const result = await ai.models.generateContent({
    model: "gemini-2.0-flash",
    contents: [
    {
      inlineData: {
        mimeType: 'image/jpeg',
        data: base64ImageData,
      },
    },
    { text: "Caption this image." }
  ],
  });
  console.log(result.text);
}

main();

Go

func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, option.WithAPIKey(os.Getenv("GOOGLE_API_KEY")))
if err != nil {
  log.Fatal(err)
}
defer client.Close()

model := client.GenerativeModel("gemini-2.0-flash")

// Download the image.
imageResp, err := http.Get("https://goo.gle/instrument-img")
if err != nil {
  panic(err)
}
defer imageResp.Body.Close()

imageBytes, err := io.ReadAll(imageResp.Body)
if err != nil {
  panic(err)
}

// Create the request.
req := []genai.Part{
  genai.ImageData("jpeg", imageBytes),

  genai.Text("Caption this image."),
}

// Generate content.
resp, err := model.GenerateContent(ctx, req...)
if err != nil {
  panic(err)
}

// Handle the response of generated text.
for _, c := range resp.Candidates {
  if c.Content != nil {
    fmt.Println(*c.Content)
  }
}

}

REST

IMG_URL="https://goo.gle/instrument-img"

MIME_TYPE=$(curl -sIL "$IMG_URL" | grep -i '^content-type:' | awk -F ': ' '{print $2}' | sed 's/\r$//' | head -n 1)
if [[ -z "$MIME_TYPE" || ! "$MIME_TYPE" == image/* ]]; then
  MIME_TYPE="image/jpeg"
fi

if [[ "$(base64 --version 2>&1)" = *"FreeBSD"* ]]; then
  B64FLAGS="--input"
else
  B64FLAGS="-w0"
fi

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GOOGLE_API_KEY" \
    -H 'Content-Type: application/json' \
    -X POST \
    -d '{
      "contents": [{
        "parts":[
            {
              "inline_data": {
                "mime_type":"'"$MIME_TYPE"'",
                "data": "'$(curl -sL "$IMG_URL" | base64 $B64FLAGS)'"
              }
            },
            {"text": "Caption this image."}
        ]
      }]
    }' 2> /dev/null

Ten en cuenta lo siguiente sobre los datos de imágenes intercalados:

  • El tamaño máximo total de la solicitud es de 20 MB, lo que incluye las instrucciones de texto, del sistema y todos los archivos proporcionados intercalados. Si el tamaño de tu archivo hará que el tamaño total de la solicitud supere los 20 MB, usa la API de Files para subir un archivo de imagen que se usará en la solicitud.
  • Si usas un ejemplo de imagen varias veces, es más eficiente subir un archivo de imagen con la API de File.

Cómo generar indicaciones con varias imágenes

Para proporcionar varias imágenes en una sola instrucción, incluye varios objetos Part de imagen en el array contents. Pueden ser una combinación de datos intercalados (archivos locales o URLs) y referencias a la API de archivos.

Python

from google import genai
from google.genai import types

client = genai.Client(api_key="GOOGLE_API_KEY")

# Upload the first image
image1_path = "path/to/image1.jpg"
uploaded_file = client.files.upload(file=image1_path)

# Prepare the second image as inline data
image2_path = "path/to/image2.png"
with open(image2_path, 'rb') as f:
    img2_bytes = f.read()

# Create the prompt with text and multiple images
response = client.models.generate_content(
    model="gemini-2.0-flash",
    contents=[
        "What is different between these two images?",
        uploaded_file,  # Use the uploaded file reference
        types.Part.from_bytes(
            data=img2_bytes,
            mime_type='image/png'
        )
    ]
)

print(response.text)

JavaScript

import {
  GoogleGenAI,
  createUserContent,
  createPartFromUri,
} from "@google/genai";
import * as fs from "node:fs";

const ai = new GoogleGenAI({ apiKey: "GOOGLE_API_KEY" });

async function main() {
  // Upload the first image
  const image1_path = "path/to/image1.jpg";
  const uploadedFile = await ai.files.upload({
    file: image1_path,
    config: { mimeType: "image/jpeg" },
  });

  // Prepare the second image as inline data
  const image2_path = "path/to/image2.png";
  const base64Image2File = fs.readFileSync(image2_path, {
    encoding: "base64",
  });

  // Create the prompt with text and multiple images
  const response = await ai.models.generateContent({
    model: "gemini-2.0-flash",
    contents: createUserContent([
      "What is different between these two images?",
      createPartFromUri(uploadedFile.uri, uploadedFile.mimeType),
      {
        inlineData: {
          mimeType: "image/png",
          data: base64Image2File,
        },
      },
    ]),
  });
  console.log(response.text);
}

await main();

Go

+    // Upload the first image
image1Path := "path/to/image1.jpg"
uploadedFile, err := client.UploadFileFromPath(ctx, image1Path, nil)
if err != nil {
    log.Fatal(err)
}
defer client.DeleteFile(ctx, uploadedFile.Name)

// Prepare the second image as inline data
image2Path := "path/to/image2.png"
img2Bytes, err := os.ReadFile(image2Path)
if err != nil {
  log.Fatal(err)
}

// Create the prompt with text and multiple images
model := client.GenerativeModel("gemini-2.0-flash")
prompt := []genai.Part{
  genai.Text("What is different between these two images?"),
  genai.FileData{URI: uploadedFile.URI},
  genai.Blob{MIMEType: "image/png", Data: img2Bytes},
}

resp, err := model.GenerateContent(ctx, prompt...)
if err != nil {
  log.Fatal(err)
}

printResponse(resp)

REST

# Upload the first image
IMAGE1_PATH="path/to/image1.jpg"
MIME1_TYPE=$(file -b --mime-type "${IMAGE1_PATH}")
NUM1_BYTES=$(wc -c < "${IMAGE1_PATH}")
DISPLAY_NAME1=IMAGE1

tmp_header_file1=upload-header1.tmp

curl "https://generativelanguage.googleapis.com/upload/v1beta/files?key=${GOOGLE_API_KEY}" \
  -D upload-header1.tmp \
  -H "X-Goog-Upload-Protocol: resumable" \
  -H "X-Goog-Upload-Command: start" \
  -H "X-Goog-Upload-Header-Content-Length: ${NUM1_BYTES}" \
  -H "X-Goog-Upload-Header-Content-Type: ${MIME1_TYPE}" \
  -H "Content-Type: application/json" \
  -d "{'file': {'display_name': '${DISPLAY_NAME1}'}}" 2> /dev/null

upload_url1=$(grep -i "x-goog-upload-url: " "${tmp_header_file1}" | cut -d" " -f2 | tr -d "\r")
rm "${tmp_header_file1}"

curl "${upload_url1}" \
  -H "Content-Length: ${NUM1_BYTES}" \
  -H "X-Goog-Upload-Offset: 0" \
  -H "X-Goog-Upload-Command: upload, finalize" \
  --data-binary "@${IMAGE1_PATH}" 2> /dev/null > file_info1.json

file1_uri=$(jq ".file.uri" file_info1.json)
echo file1_uri=$file1_uri

# Prepare the second image (inline)
IMAGE2_PATH="path/to/image2.png"
MIME2_TYPE=$(file -b --mime-type "${IMAGE2_PATH}")

if [[ "$(base64 --version 2>&1)" = *"FreeBSD"* ]]; then
  B64FLAGS="--input"
else
  B64FLAGS="-w0"
fi
IMAGE2_BASE64=$(base64 $B64FLAGS $IMAGE2_PATH)

# Now generate content using both images
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GOOGLE_API_KEY" \
    -H 'Content-Type: application/json' \
    -X POST \
    -d '{
      "contents": [{
        "parts":[
          {"text": "What is different between these two images?"},
          {"file_data":{"mime_type": "'"${MIME1_TYPE}"'", "file_uri": '$file1_uri'}},
          {
            "inline_data": {
              "mime_type":"'"${MIME2_TYPE}"'",
              "data": "'"$IMAGE2_BASE64"'"
            }
          }
        ]
      }]
    }' 2> /dev/null > response.json

cat response.json
echo

jq ".candidates[].content.parts[].text" response.json

Obtén un cuadro de límite para un objeto

Los modelos de Gemini se entrenan para identificar objetos en una imagen y proporcionar sus coordenadas de cuadro delimitador. Las coordenadas se muestran en relación con las dimensiones de la imagen, ajustadas a [0, 1000]. Debes desescalarlas según el tamaño de la imagen original.

Python

prompt = "Detect the all of the prominent items in the image. The box_2d should be [ymin, xmin, ymax, xmax] normalized to 0-1000."

JavaScript

const prompt = "Detect the all of the prominent items in the image. The box_2d should be [ymin, xmin, ymax, xmax] normalized to 0-1000.";

Go

prompt := []genai.Part{
    genai.FileData{URI: sampleImage.URI},
    genai.Text("Detect the all of the prominent items in the image. The box_2d should be [ymin, xmin, ymax, xmax] normalized to 0-1000."),
}

REST

PROMPT="Detect the all of the prominent items in the image. The box_2d should be [ymin, xmin, ymax, xmax] normalized to 0-1000."

Puedes usar cuadros de límite para la detección y localización de objetos en imágenes y videos. Si identificas y delimitas con precisión los objetos con cuadros de límites, puedes desbloquear una amplia variedad de aplicaciones y mejorar la inteligencia de tus proyectos.

Ventajas clave

  • Fácil: Integra funciones de detección de objetos en tus aplicaciones con facilidad, independientemente de tu experiencia en visión artificial.
  • Personalizable: Produce cuadros de límite según instrucciones personalizadas (p.ej., "Quiero ver los cuadros de límite de todos los objetos verdes en esta imagen"), sin tener que entrenar un modelo personalizado.

Detalles técnicos

  • Entrada: Tu instrucción y las imágenes o los fotogramas de video asociados.
  • Resultado: Rectángulos de límite en formato [y_min, x_min, y_max, x_max]. La esquina superior izquierda es el origen. Los ejes x y y se orientan horizontal y verticalmente, respectivamente. Los valores de las coordenadas se normalizan de 0 a 1,000 para cada imagen.
  • Visualización: Los usuarios de AI Studio verán los cuadros de límite trazados dentro de la IU.

Para desarrolladores de Python, prueba el notebook de comprensión espacial 2D o el notebook experimental de puntero 3D.

Cómo normalizar coordenadas

El modelo muestra las coordenadas del cuadro delimitador en el formato [y_min, x_min, y_max, x_max]. Para convertir estas coordenadas normalizadas en las coordenadas de píxeles de tu imagen original, sigue estos pasos:

  1. Divide cada coordenada de salida por 1,000.
  2. Multiplica las coordenadas x por el ancho de la imagen original.
  3. Multiplica las coordenadas y por la altura de la imagen original.

Para explorar ejemplos más detallados de cómo generar coordenadas de cuadros de límite y visualizarlas en imágenes, consulta el ejemplo de libro de recetas de detección de objetos.

Segmentación de imágenes

A partir de los modelos Gemini 2.5, los modelos Gemini se entrenan para no solo detectar elementos, sino también segmentarlos y proporcionar una máscara de sus contornos.

El modelo predice una lista JSON, en la que cada elemento representa una máscara de segmentación. Cada elemento tiene un cuadro de límite ("box_2d") en el formato [y0, x0, y1, x1] con coordenadas normalizadas entre 0 y 1000, una etiqueta ("label") que identifica el objeto y, por último, la máscara de segmentación dentro del cuadro de límite, como un archivo PNG con codificación base64 que es un mapa de probabilidad con valores entre 0 y 255. Se debe cambiar el tamaño de la máscara para que coincida con las dimensiones del cuadro delimitador y, luego, se debe binarizar en el umbral de confianza (127 para el punto medio).

Python

prompt = """
  Give the segmentation masks for the wooden and glass items.
  Output a JSON list of segmentation masks where each entry contains the 2D
  bounding box in the key "box_2d", the segmentation mask in key "mask", and
  the text label in the key "label". Use descriptive labels.
"""

JavaScript

const prompt = `
  Give the segmentation masks for the wooden and glass items.
  Output a JSON list of segmentation masks where each entry contains the 2D
  bounding box in the key "box_2d", the segmentation mask in key "mask", and
  the text label in the key "label". Use descriptive labels.
`;    

Go

prompt := []genai.Part{
    genai.FileData{URI: sampleImage.URI},
    genai.Text(`
      Give the segmentation masks for the wooden and glass items.
      Output a JSON list of segmentation masks where each entry contains the 2D
      bounding box in the key "box_2d", the segmentation mask in key "mask", and
      the text label in the key "label". Use descriptive labels.
    `),
}

REST

PROMPT='''
  Give the segmentation masks for the wooden and glass items.
  Output a JSON list of segmentation masks where each entry contains the 2D
  bounding box in the key "box_2d", the segmentation mask in key "mask", and
  the text label in the key "label". Use descriptive labels.
'''
Una mesa con cupcakes, en la que se destacan los objetos de madera y vidrio
Máscara de los objetos de madera y vidrio que se encuentran en la imagen

Consulta el ejemplo de segmentación en la guía del libro de recetas para ver un ejemplo más detallado.

Formatos de imagen compatibles

Gemini admite los siguientes tipos de MIME de formato de imagen:

  • PNG - image/png
  • JPEG - image/jpeg
  • WEBP: image/webp
  • HEIC: image/heic
  • HEIF: image/heif

Detalles técnicos sobre las imágenes

  • Límite de archivos: Gemini 2.5 Pro, 2.0 Flash, 1.5 Pro y 1.5 Flash admiten un máximo de 3,600 archivos de imagen por solicitud.
  • Cálculo de tokens:
    • Gemini 1.5 Flash y Gemini 1.5 Pro: 258 tokens si ambas dimensiones son <= 384 píxeles. Las imágenes más grandes se organizan en mosaicos (mosaico mínimo de 256 px, máximo de 768 px, tamaño modificado a 768 x 768), y cada mosaico cuesta 258 tokens.
    • Gemini 2.0 Flash: 258 tokens si ambas dimensiones son <= 384 píxeles. Las imágenes más grandes se dividen en mosaicos de 768 x 768 píxeles, cada uno de los cuales cuesta 258 tokens.
  • Prácticas recomendadas:
    • Asegúrate de que las imágenes se hayan rotado correctamente.
    • Usa imágenes claras y no borrosas.
    • Cuando uses una sola imagen con texto, coloca la instrucción de texto después de la parte de la imagen en el array contents.

¿Qué sigue?

En esta guía, se muestra cómo subir archivos de imagen y generar resultados de texto a partir de entradas de imagen. Para obtener más información, consulta los siguientes recursos:

  • Instrucciones del sistema: Las instrucciones del sistema te permiten dirigir el comportamiento del modelo según tus necesidades y casos de uso específicos.
  • Interpretación de videos: Aprende a trabajar con entradas de video.
  • API de Files: Obtén más información para subir y administrar archivos para usarlos con Gemini.
  • Estrategias de indicaciones de archivos: La API de Gemini admite indicaciones con datos de texto, imagen, audio y video, también conocidos como indicaciones multimodales.
  • Orientación de seguridad: A veces, los modelos de IA generativa producen resultados inesperados, como resultados imprecisos, sesgados o ofensivos. El procesamiento posterior y la evaluación humana son esenciales para limitar el riesgo de daños que pueden causar estos resultados.