I modelli Gemini sono stati sviluppati da zero appositamente per essere multimodali e sono dotati di funzionalità di comprensione delle immagini efficaci e integrate. In questo modo, puoi eseguire attività come sottotitoli codificati delle immagini, classificazione, domande e risposte visive, rilevamento e segmentazione di oggetti senza addestrare modelli di ML specializzati.
Questa guida illustra gli input di immagini e le attività comuni di interpretazione delle immagini. Per altre modalità, consulta le guide relative ai video e all'audio.
Trasmissione di immagini a Gemini
Puoi fornire immagini come input a Gemini utilizzando due metodi:
- Trasmissione dei dati delle immagini in linea: ideale per file di dimensioni ridotte (dimensioni totali della richiesta inferiori a 20 MB, inclusi i prompt).
- Caricamento di immagini utilizzando l'API File: consigliato per file di grandi dimensioni o per riutilizzare le immagini in più richieste.
Trasferimento dei dati delle immagini in linea
Puoi passare i dati delle immagini in linea nella richiesta a generateContent
. Puoi fornire i dati delle immagini come stringhe codificate Base64 o leggendo direttamente i file locali (a seconda della lingua).
L'esempio seguente mostra come leggere un'immagine da un file locale e passarla all'API generateContent
per l'elaborazione.
Python
from google.genai import types
with open('path/to/small-sample.jpg', 'rb') as f:
image_bytes = f.read()
response = client.models.generate_content(
model='gemini-2.0-flash',
contents=[
types.Part.from_bytes(
data=image_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);
Vai
bytes, _ := os.ReadFile("path/to/small-sample.jpg")
parts := []*genai.Part{
genai.NewPartFromBytes(bytes, "image/jpeg"),
genai.NewPartFromText("Caption this image."),
}
contents := []*genai.Content{
genai.NewContentFromParts(parts, genai.RoleUser),
}
result, _ := client.Models.GenerateContent(
ctx,
"gemini-2.0-flash",
contents,
nil,
)
fmt.Println(result.Text())
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
Puoi anche recuperare un'immagine da un URL, convertirla in byte e passarla a
generateContent
come mostrato negli esempi seguenti.
Python
from google import genai
from google.genai import types
import requests
image_path = "https://goo.gle/instrument-img"
image_bytes = requests.get(image_path).content
image = types.Part.from_bytes(
data=image_bytes, mime_type="image/jpeg"
)
client = genai.Client(api_key="GOOGLE_API_KEY")
response = client.models.generate_content(
model="gemini-2.0-flash-exp",
contents=["What is this image?", image],
)
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();
Vai
package main
import (
"context"
"fmt"
"os"
"io"
"net/http"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
client, _ := genai.NewClient(ctx, &genai.ClientConfig{
APIKey: os.Getenv("GOOGLE_API_KEY"),
Backend: genai.BackendGeminiAPI,
})
// Download the image.
imageResp, _ := http.Get("https://goo.gle/instrument-img")
imageBytes, _ := io.ReadAll(imageResp.Body)
parts := []*genai.Part{
genai.NewPartFromBytes(imageBytes, "image/jpeg"),
genai.NewPartFromText("Caption this image."),
}
contents := []*genai.Content{
genai.NewContentFromParts(parts, genai.RoleUser),
}
result, _ := client.Models.GenerateContent(
ctx,
"gemini-2.0-flash",
contents,
nil,
)
fmt.Println(result.Text())
}
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
# Check for macOS
if [[ "$(uname)" == "Darwin" ]]; then
IMAGE_B64=$(curl -sL "$IMG_URL" | base64 -b 0)
elif [[ "$(base64 --version 2>&1)" = *"FreeBSD"* ]]; then
IMAGE_B64=$(curl -sL "$IMG_URL" | base64)
else
IMAGE_B64=$(curl -sL "$IMG_URL" | base64 -w0)
fi
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"contents": [{
"parts":[
{
"inline_data": {
"mime_type":"'"$MIME_TYPE"'",
"data": "'"$IMAGE_B64"'"
}
},
{"text": "Caption this image."}
]
}]
}' 2> /dev/null
Caricamento di immagini tramite l'API File
Per file di grandi dimensioni o per poter utilizzare ripetutamente lo stesso file immagine, utilizza l'API Files. Il seguente codice carica un file immagine e lo utilizza in una chiamata a generateContent
. Per ulteriori informazioni ed esempi, consulta la guida all'API Files.
Python
from google import genai
client = genai.Client(api_key="GOOGLE_API_KEY")
my_file = client.files.upload(file="path/to/sample.jpg")
response = client.models.generate_content(
model="gemini-2.0-flash",
contents=[my_file, "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();
Vai
package main
import (
"context"
"fmt"
"os"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
client, _ := genai.NewClient(ctx, &genai.ClientConfig{
APIKey: os.Getenv("GOOGLE_API_KEY"),
Backend: genai.BackendGeminiAPI,
})
uploadedFile, _ := client.Files.UploadFromPath(ctx, "path/to/sample.jpg", nil)
parts := []*genai.Part{
genai.NewPartFromText("Caption this image."),
genai.NewPartFromURI(uploadedFile.URI, uploadedFile.MIMEType),
}
contents := []*genai.Content{
genai.NewContentFromParts(parts, genai.RoleUser),
}
result, _ := client.Models.GenerateContent(
ctx,
"gemini-2.0-flash",
contents,
nil,
)
fmt.Println(result.Text())
}
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 -r ".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
Prompt con più immagini
Puoi fornire più immagini in un singolo prompt includendo più oggetti Part
di immagini nell'array contents
. Possono essere una combinazione di dati in linea
(file locali o URL) e riferimenti all'API File.
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();
Vai
// Upload the first image
image1Path := "path/to/image1.jpg"
uploadedFile, _ := client.Files.UploadFromPath(ctx, image1Path, nil)
// Prepare the second image as inline data
image2Path := "path/to/image2.jpeg"
imgBytes, _ := os.ReadFile(image2Path)
parts := []*genai.Part{
genai.NewPartFromText("What is different between these two images?"),
genai.NewPartFromBytes(imgBytes, "image/jpeg"),
genai.NewPartFromURI(uploadedFile.URI, uploadedFile.MIMEType),
}
contents := []*genai.Content{
genai.NewContentFromParts(parts, genai.RoleUser),
}
result, _ := client.Models.GenerateContent(
ctx,
"gemini-2.0-flash",
contents,
nil,
)
fmt.Println(result.Text())
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
Rilevamento di oggetti
A partire da Gemini 2.0, i modelli vengono addestrati ulteriormente per rilevare gli oggetti in un'immagine e ottenere le coordinate del riquadro di delimitazione. Le coordinate, relative alle dimensioni dell'immagine, vengono ridimensionate in [0, 1000]. Devi ridimensionare queste coordinate in base alle dimensioni dell'immagine originale.
Python
from google import genai
from google.genai import types
from PIL import Image
import json
client = genai.Client(api_key="GOOGLE_API_KEY")
prompt = "Detect the all of the prominent items in the image. The box_2d should be [ymin, xmin, ymax, xmax] normalized to 0-1000."
image = Image.open("/path/to/image.png")
config = types.GenerateContentConfig(response_mime_type="application/json")
response = client.models.generate_content(model="gemini-2.0-flash",
contents=[image, prompt],
config=config)
width, height = image.size
bounding_boxes = json.loads(response.text)
converted_bounding_boxes = []
for bounding_box in bounding_boxes:
abs_y1 = int(bounding_box["box_2d"][0]/1000 * height)
abs_x1 = int(bounding_box["box_2d"][1]/1000 * width)
abs_y2 = int(bounding_box["box_2d"][2]/1000 * height)
abs_x2 = int(bounding_box["box_2d"][3]/1000 * width)
converted_bounding_boxes.append([abs_x1, abs_y1, abs_x2, abs_y2])
print("Image size: ", width, height)
print("Bounding boxes:", converted_bounding_boxes)
Per altri esempi, consulta i seguenti cookbook:
Segmentazione dell'immagine
A partire da Gemini 2.5, i modelli non solo rilevano gli articoli, ma li segmentano anche e forniscono le relative maschere di contorno.
Il modello prevede un elenco JSON, in cui ogni elemento rappresenta una maschera di segmentazione.
Ogni elemento ha una scatola delimitante ("box_2d
") nel formato [y0, x0, y1, x1]
con coordinate normalizzate tra 0 e 1000, un'etichetta ("label
") che identifica l'oggetto e infine la maschera di segmentazione all'interno della scatola delimitante, come immagine png codificata in base64 che è una mappa di probabilità con valori compresi tra 0 e 255.
La maschera deve essere ridimensionata in modo da corrispondere alle dimensioni della casella delimitante, quindi deve essere sbiancata in base alla soglia di confidenza (127 per il punto intermedio).
Python
from google import genai
from PIL import Image
import io
import os
import requests
from io import BytesIO
import dataclasses
import numpy as np
import base64
# Mask data type
@dataclasses.dataclass(frozen=True)
class SegmentationMask:
# bounding box pixel coordinates (not normalized)
y0: int # in [0..height - 1]
x0: int # in [0..width - 1]
y1: int # in [0..height - 1]
x1: int # in [0..width - 1]
mask: np.array # [img_height, img_width] with values 0..255
label: str
# Parsing JSON output
def parse_json(json_output: str):
# Parsing out the markdown fencing
lines = json_output.splitlines()
for i, line in enumerate(lines):
if line == "```json":
json_output = "\n".join(lines[i+1:]) # Remove everything before "```json"
json_output = json_output.split("```")[0] # Remove everything after the closing "```"
break # Exit the loop once "```json" is found
return json_output
# Generates a list of segmentation masks from the model output
def parse_segmentation_masks(
predicted_str: str, *, img_height: int, img_width: int
) -> list[SegmentationMask]:
items = json.loads(parse_json(predicted_str))
masks = []
for item in items:
raw_box = item["box_2d"]
abs_y0 = int(item["box_2d"][0] / 1000 * img_height)
abs_x0 = int(item["box_2d"][1] / 1000 * img_width)
abs_y1 = int(item["box_2d"][2] / 1000 * img_height)
abs_x1 = int(item["box_2d"][3] / 1000 * img_width)
if abs_y0 >= abs_y1 or abs_x0 >= abs_x1:
print("Invalid bounding box", item["box_2d"])
continue
label = item["label"]
png_str = item["mask"]
if not png_str.startswith("data:image/png;base64,"):
print("Invalid mask")
continue
png_str = png_str.removeprefix("data:image/png;base64,")
png_str = base64.b64decode(png_str)
mask = Image.open(io.BytesIO(png_str))
bbox_height = abs_y1 - abs_y0
bbox_width = abs_x1 - abs_x0
if bbox_height < 1 or bbox_width < 1:
print("Invalid bounding box")
continue
mask = mask.resize((bbox_width, bbox_height), resample=Image.Resampling.BILINEAR)
np_mask = np.zeros((img_height, img_width), dtype=np.uint8)
np_mask[abs_y0:abs_y1, abs_x0:abs_x1] = mask
masks.append(SegmentationMask(abs_y0, abs_x0, abs_y1, abs_x1, np_mask, label))
return masks
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.
"""
model = "gemini-2.5-pro-preview-06-05"
image ="path/to/image.png"
# Load and resize image
im = Image.open(BytesIO(open(image, "rb").read()))
im.thumbnail([1024,1024], Image.Resampling.LANCZOS)
# Run model to find segmentation masks
response = client.models.generate_content(
model=model,
contents=[prompt, im],
config = types.GenerateContentConfig(
temperature=0.5,
)
)
# Check output
print(response.text)
# Get segmentation masks
print(parse_segmentation_masks(response.text, img_height=im.size[1], img_width=im.size[0]))
Consulta l'esempio di segmentazione nella guida del cookbook per un esempio più dettagliato.
Formati di immagine supportati
Gemini supporta i seguenti tipi MIME di formato immagine:
- PNG -
image/png
- JPEG -
image/jpeg
- WEBP -
image/webp
- HEIC -
image/heic
- HEIF -
image/heif
Limitazioni e informazioni tecniche chiave
- Limite di file: Gemini 2.5 Pro, 2.0 Flash, 1.5 Pro e 1.5 Flash supportano un massimo di 3600 file immagine per richiesta.
- Calcolo dei token:
- Gemini 1.5 Flash e Gemini 1.5 Pro: 258 token se entrambe le dimensioni <= 384 pixel. Le immagini più grandi vengono suddivise in riquadri (riquadro minimo 256 px, massimo 768 px, ridimensionato a 768 x 768), con un costo di 258 token per ogni riquadro.
- Gemini 2.0 Flash e Gemini 2.5 Flash/Pro: 258 token se entrambe le dimensioni sono <= 384 pixel. Le immagini più grandi vengono suddivise in riquadri di 768 x 768 pixel, ciascuno dei quali ha un costo di 258 token.
Suggerimenti e best practice
- Verifica che le immagini siano ruotate correttamente.
- Utilizza immagini chiare e non sfocate.
- Quando utilizzi una singola immagine con testo, posiziona il prompt di testo dopo la parte dell'immagine nell'array
contents
.
Passaggi successivi
Questa guida mostra come caricare file di immagini e generare output di testo da input di immagini. Per saperne di più, consulta le seguenti risorse:
- API Files: scopri di più sul caricamento e sulla gestione dei file da utilizzare con Gemini.
- Istruzioni di sistema: le istruzioni di sistema ti consentono di indirizzare il comportamento del modello in base alle tue esigenze e ai tuoi casi d'uso specifici.
- Strategie di prompt dei file: l'API Gemini supporta i prompt con dati di testo, immagini, audio e video, noti anche come prompt multimodali.
- Indicazioni per la sicurezza: a volte i modelli di IA generativa producono output inaspettati, ad esempio imprecisi, biassati o offensivi. Il post-trattamento e la valutazione umana sono essenziali per limitare il rischio di danni derivanti da questi output.