Imagen è un modello di generazione di immagini. Può essere utilizzato per generare avatar personalizzati per i profili utente o per integrare asset visivi personalizzati nei flussi di schermata esistenti per aumentare il coinvolgimento degli utenti.
Puoi accedere ai modelli Imagen dalla tua app per Android utilizzando l'SDK Firebase AI Logic. I modelli Imagen sono disponibili utilizzando entrambi i provider di API Firebase AI Logic: l'API Gemini Developer (consigliata per la maggior parte degli sviluppatori) e Vertex AI.
Sperimenta con i prompt
La creazione dei prompt ideali spesso richiede più tentativi. Puoi sperimentare con i prompt di immagini in Google AI Studio, un IDE per la progettazione e la prototipazione dei prompt. Per suggerimenti su come migliorare i prompt, consulta la guida agli attributi di prompt e immagine.

Configura un progetto Firebase e connetti la tua app
Segui i passaggi descritti nella documentazione di Firebase per aggiungere Firebase al tuo progetto Android.
Aggiungi la dipendenza Gradle
Aggiungi le seguenti dipendenze al file build.gradle
:
dependencies {
// Import the BoM for the Firebase platform
implementation(platform("com.google.firebase:firebase-bom:34.4.0"))
// Add the dependency for the Firebase AI Logic library. When using the BoM,
// you don't specify versions in Firebase library dependencies
implementation("com.google.firebase:firebase-ai")
}
Genera un'immagine
Per generare un'immagine nella tua app per Android, inizia istanziando un
ImagenModel
con una configurazione facoltativa.
Puoi utilizzare il parametro generationConfig
per definire un prompt negativo,
il numero di immagini, le proporzioni dell'immagine di output, il formato dell'immagine e aggiungere una
filigrana. Puoi utilizzare il parametro safetySettings
per configurare i filtri
sicurezza e persone.
Kotlin
val config = ImagenGenerationConfig {
numberOfImages = 2,
aspectRatio = ImagenAspectRatio.LANDSCAPE_16x9,
imageFormat = ImagenImageFormat.jpeg(compressionQuality = 100),
addWatermark = false
}
// Initialize the Gemini Developer API backend service
// For Vertex AI use Firebase.ai(backend = GenerativeBackend.vertexAI())
val model = Firebase.ai(backend = GenerativeBackend.googleAI()).imagenModel(
modelName = "imagen-4.0-generate-001",
generationConfig = config,
safetySettings = ImagenSafetySettings(
safetyFilterLevel = ImagenSafetyFilterLevel.BLOCK_LOW_AND_ABOVE,
personFilterLevel = ImagenPersonFilterLevel.BLOCK_ALL
)
)
Java
ImagenGenerationConfig config = new ImagenGenerationConfig.Builder()
.setNumberOfImages(2)
.setAspectRatio(ImagenAspectRatio.LANDSCAPE_16x9)
.setImageFormat(ImagenImageFormat.jpeg(100))
.setAddWatermark(false)
.build();
// For Vertex AI use Firebase.ai(backend = GenerativeBackend.vertexAI())
ImagenModelFutures model = ImagenModelFutures.from(
FirebaseAI.ai(backend = GenerativeBackend.googleAI()).imagenModel(
"imagen-4.0-generate-001",
config,
ImagenSafetySettings.builder()
.setSafetyFilterLevel(ImagenSafetyFilterLevel.BLOCK_LOW_AND_ABOVE)
.setPersonFilterLevel(ImagenPersonFilterLevel.BLOCK_ALL)
.build())
);
Una volta creata un'istanza di ImagenModel
, puoi generare immagini chiamando
generateImages
:
Kotlin
val imageResponse = model.generateImages(
prompt = "A hyper realistic picture of a t-rex with a blue bagpack in a prehistoric forest",
)
val image = imageResponse.images.first
val bitmapImage = image.asBitmap()
Java
CompletableFuture<GenerateContentResponse> futureResponse =
model.generateContent(
Content.newBuilder()
.addParts(
Part.newBuilder()
.setText("A hyper realistic picture of a t-rex with a blue bagpack in a prehistoric forest")
.build())
.build());
try {
GenerateContentResponse imageResponse = futureResponse.get();
List<GeneratedImage> images =
imageResponse
.getCandidates(0)
.getContent()
.getParts(0)
.getInlineData()
.getImagesList();
if (!images.isEmpty()) {
GeneratedImage image = images.get(0);
Bitmap bitmapImage = image.asBitmap();
// Use bitmapImage
}
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
Modificare le immagini con Imagen
Gli SDK Firebase AI Logic offrono funzionalità avanzate di editing delle immagini tramite il modello Imagen, che ti consente di:
- Modifica le immagini in base alle maschere, che include azioni come l'inserimento o la rimozione di oggetti, l'estensione dei contenuti dell'immagine oltre i suoi limiti originali e la modifica degli sfondi.
- Personalizza le immagini applicando stili specifici (pattern, texture o stili di artisti), concentrandoti su vari soggetti (ad esempio prodotti, persone o animali) o rispettando diversi controlli (ad esempio uno schizzo disegnato a mano, un'immagine con rilevamento dei contorni o una mesh del volto).
Inizializzazione del modello
Per utilizzare le funzionalità di editing di Imagen, specifica un modello Imagen che supporti l'editing delle immagini, come imgen-3.0-capability-001
. versione del modello:
val imagenModel = Firebase.ai(backend = GenerativeBackend.vertexAI())
.imagenModel("imagen-3.0-capability-001")
Modifica basata su maschera
La modifica basata su maschera di Imagen consente di modificare le immagini definendo aree specifiche da manipolare per il modello. Questa funzionalità consente una serie di azioni, tra cui la creazione e l'applicazione di maschere, l'inserimento o la rimozione di oggetti e l'espansione dei contenuti delle immagini oltre i confini originali.
Creare una maschera
Per eseguire modifiche basate su maschera, ad esempio inserire o rimuovere oggetti, devi definire l'area che deve essere modificata dal modello, ovvero la maschera.
Per creare una maschera, puoi farla generare automaticamente al modello utilizzando
ImagenBackgroundMask()
o ImagenSemanticMask()
, passando un ID
classe.
Puoi anche disegnare manualmente la maschera sullo schermo generando una bitmap della maschera e
convertendola in un ImagenRawMask
. Utilizzando detectDragGestures
e Canvas
,
puoi implementare un'interfaccia utente per il disegno di maschere con Jetpack Compose nella tua app
nel seguente modo:
import androidx.compose.ui.graphics.Color as ComposeColor
[...]
@Composable
fun ImagenEditingMaskEditor(
sourceBitmap: Bitmap,
onMaskFinalized: (Bitmap) -> Unit,
) {
val paths = remember { mutableStateListOf<Path>() }
var currentPath by remember { mutableStateOf<Path?>(null) }
var scale by remember { mutableFloatStateOf(1f) }
var offsetX by remember { mutableFloatStateOf(0f) }
var offsetY by remember { mutableFloatStateOf(0f) }
Column(
modifier = Modifier.fillMaxSize(),
) {
Box(
modifier = Modifier
.fillMaxWidth()
.pointerInput(Unit) {
detectDragGestures(
onDragStart = { startOffset ->
val transformedStart = Offset(
(startOffset.x - offsetX) / scale,
(startOffset.y - offsetY) / scale,
)
currentPath = Path().apply { moveTo(transformedStart.x, transformedStart.y) }
},
onDrag = { change, _ ->
currentPath?.let {
val transformedChange = Offset(
(change.position.x - offsetX) / scale,
(change.position.y - offsetY) / scale,
)
it.lineTo(transformedChange.x, transformedChange.y)
currentPath = Path().apply { addPath(it) }
}
change.consume()
},
onDragEnd = {
currentPath?.let { paths.add(it) }
currentPath = null
},
)
},
) {
Image(
bitmap = sourceBitmap.asImageBitmap(),
contentDescription = null,
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Fit,
)
Canvas(modifier = Modifier.fillMaxSize()) {
val canvasWidth = size.width
val canvasHeight = size.height
val bitmapWidth = sourceBitmap.width.toFloat()
val bitmapHeight = sourceBitmap.height.toFloat()
scale = min(canvasWidth / bitmapWidth, canvasHeight / bitmapHeight)
offsetX = (canvasWidth - bitmapWidth * scale) / 2
offsetY = (canvasHeight - bitmapHeight * scale) / 2
withTransform(
{
translate(left = offsetX, top = offsetY)
scale(scale, scale, pivot = Offset.Zero)
},
) {
val strokeWidth = 70f / scale
val stroke = Stroke(width = strokeWidth, cap = StrokeCap.Round, join = StrokeJoin.Round)
val pathColor = ComposeColor.White.copy(alpha = 0.5f)
paths.forEach { path ->
drawPath(path = path, color = pathColor, style = stroke)
}
currentPath?.let { path ->
drawPath(path = path, color = pathColor, style = stroke)
}
}
}
}
Button(
onClick = {
val maskBitmap = createMask(sourceBitmap, paths)
onMaskFinalized(maskBitmap)
},
) {
Text("Save mask")
}
}
}
Puoi quindi creare la bitmap della maschera disegnando i tracciati sul canvas:
import android.graphics.Color as AndroidColor
import android.graphics.Paint
[...]
private fun createMaskBitmap(
sourceBitmap: Bitmap,
paths: SnapshotStateList<Path>,
): Bitmap {
val maskBitmap = createBitmap(sourceBitmap.width, sourceBitmap.height)
val canvas = android.graphics.Canvas(maskBitmap)
val paint = Paint().apply {
color = AndroidColor.RED
strokeWidth = 70f
style = Paint.Style.STROKE
strokeCap = Paint.Cap.ROUND
strokeJoin = Paint.Join.ROUND
isAntiAlias = true
}
paths.forEach { path -> canvas.drawPath(path.asAndroidPath(), paint) }
return maskBitmap
}
Assicurati che la maschera abbia le stesse dimensioni dell'immagine di origine. Per saperne di più, consulta i campioni del catalogo Imagen AI.
Inserire oggetti
Puoi inserire un nuovo oggetto o contenuto in un'immagine esistente, operazione chiamata anche inpainting. Il modello genererà e inserirà i nuovi contenuti nell'area mascherata specificata.
Per farlo, utilizza la funzione editImage()
. Dovrai fornire l'immagine originale, una maschera e un prompt di testo che descriva i contenuti che vuoi inserire. Inoltre, passa un oggetto
ImagenEditingConfig
, assicurandoti che la proprietà editMode
sia impostata su
ImagenEditMode.INPAINT_INSERTION
.
suspend fun insertFlowersIntoImage(
model: ImagenModel,
originalImage: Bitmap,
mask: ImagenMaskReference): ImagenGenerationResponse<ImagenInlineImage> {
val prompt = "a vase of flowers"
// Pass the original image, a mask, the prompt, and an editing configuration.
val editedImage = model.editImage(
sources = listOf(
ImagenRawImage(originalImage),
mask),
prompt = prompt,
// Define the editing configuration for inpainting and insertion.
config = ImagenEditingConfig(ImagenEditMode.INPAINT_INSERTION)
)
return editedImage
}
Rimuovere oggetti
L'inpainting ti consente di rimuovere gli oggetti indesiderati da un'immagine. Per farlo, utilizza
la funzione editImage
. Dovrai fornire l'immagine originale e una
maschera che evidenzi l'oggetto che vuoi
rimuovere. Se vuoi, puoi includere un prompt di testo per descrivere l'oggetto, il che
può aiutare il modello a identificarlo con precisione. Inoltre, devi impostare
editMode
all'interno di ImagenEditingConfig
su ImagenEditMode.INPAINT_REMOVAL
.
suspend fun removeBallFromImage(model: ImagenModel, originalImage: Bitmap, mask: ImagenMaskReference): ImagenGenerationResponse<ImagenInlineImage> {
// Optional: provide the prompt describing the content to be removed.
val prompt = "a ball"
// Pass the original image, a mask, the prompt, and an editing configuration.
val editedImage = model.editImage(
sources = listOf(
ImagenRawImage(originalImage),
mask
),
prompt = prompt,
// Define the editing configuration for inpainting and removal.
config = ImagenEditingConfig(ImagenEditMode.INPAINT_REMOVAL)
)
return editedImage
}
Espandi i contenuti dell'immagine
Puoi espandere un'immagine oltre i suoi limiti originali, una tecnica nota come outpainting,
utilizzando la funzione outpaintImage()
. Questa funzione richiede l'immagine originale e il Dimensions
necessario dell'immagine espansa.
Se vuoi, puoi includere un prompt descrittivo per l'espansione e specificare
il ImagenImagePlacement
dell'immagine originale all'interno
della nuova immagine generata:
suspend fun expandImage(originalImage: Bitmap, imagenModel: ImagenModel): ImagenGenerationResponse<ImagenInlineImage> {
// Optionally describe what should appear in the expanded area.
val prompt = "a sprawling sandy beach next to the ocean"
val editedImage = model.outpaintImage(
ImagenRawImage(originalImage),
Dimension(width, height),
prompt = prompt,
newPosition = ImagenImagePlacement.LEFT_CENTER
)
return editedImage
}
Sostituire lo sfondo
Puoi sostituire lo sfondo di un'immagine mantenendo il soggetto in primo piano. Per farlo, utilizza la funzione editImage
. Passa l'immagine originale, un oggetto ImagenBackgroundMask
(contenente un prompt di testo per il nuovo sfondo) e un ImagenEditingConfig
con la proprietà editMode
impostata su ImagenEditMode.INPAINT_INSERTION
.
suspend fun replaceBackground(model: ImagenModel, originalImage: Bitmap): ImagenGenerationResponse<ImagenInlineImage> {
// Provide the prompt describing the new background.
val prompt = "space background"
// Pass the original image, a mask, the prompt, and an editing configuration.
val editedImage = model.editImage(
sources = listOf(
ImagenRawImage(originalImage),
ImagenBackgroundMask(),
),
prompt = prompt,
config = ImagenEditingConfig(ImagenEditMode.INPAINT_INSERTION)
)
return editedImage
}
Personalizzazione
Puoi utilizzare la funzionalità di personalizzazione di Imagen per generare o modificare immagini basate su immagini di riferimento che specificano un soggetto, un controllo o uno stile. Ciò si ottiene fornendo un prompt di testo insieme a una o più immagini di riferimento per guidare il modello.
Personalizzare in base a un argomento
Puoi generare nuove immagini di un soggetto specifico a partire da un'immagine di riferimento (ad esempio, un prodotto, una persona o un animale). È sufficiente fornire un prompt di testo e almeno un'immagine di riferimento del soggetto. Ad esempio, potresti caricare una foto del tuo animale domestico e generare una nuova immagine in un ambiente completamente diverso.
Per farlo, definisci il riferimento dell'oggetto utilizzando ImagenSubjectReference
e poi
trasferiscilo a editImage
insieme al prompt. Inoltre, includi un
ImagenEditingConfig
che specifica il numero di editSteps
; un valore di editSteps
più alto generalmente porta a risultati di qualità migliore:
suspend fun customizeCatImage(model: ImagenModel, referenceCatImage: Bitmap): ImagenGenerationResponse<ImagenInlineImage> {
// Define the subject reference using the reference image.
val subjectReference = ImagenSubjectReference(
image = referenceCatImage,
referenceID = 1,
description = "cat",
subjectType = ImagenSubjectReferenceType.ANIMAL
)
// Provide a prompt that describes the final image.
// The "[1]" links the prompt to the subject reference with ID 1.
val prompt = "A cat[1] flying through outer space"
// Use the editImage API to perform the subject customization.
val editedImage = model.editImage(
references = listOf(subjectReference),
prompt = prompt,
config = ImagenEditingConfig(
editSteps = 50 // Number of editing steps, a higher value can improve quality
)
)
return editedImage
}
Personalizzare in base a un controllo
Questa tecnica genera una nuova immagine basata su un'immagine di riferimento di controllo, come uno schizzo disegnato a mano ("scarabocchio"), un'immagine con rilevamento dei contorni di Canny o una mesh del volto. Il modello utilizza l'immagine di controllo come guida strutturale per il layout e la composizione della nuova immagine, mentre il prompt di testo fornisce dettagli come colore e texture.
Definisci un riferimento di controllo con ImagenControlReference
e fornisci a
editImage
insieme a un prompt e ImagenEditingConfig
con il numero di
editSteps
(un valore più alto può migliorare la qualità):
suspend fun customizeCatImageByControl(model: ImagenModel, referenceCatImage: Bitmap): ImagenGenerationResponse<ImagenInlineImage> {
// Define the subject reference using the reference image.
val controlReference = ImagenControlReference(
image = referenceImage,
referenceID = 1,
controlType = CONTROL_TYPE_SCRIBBLE
)
val prompt = "A cat flying through outer space arranged like the scribble map[1]"
val editedImage = model.editImage(
references = listOf(controlReference),
prompt = prompt,
config = ImagenEditingConfig(
editSteps = 50
)
)
return editedImage
}
Personalizzare in base a uno stile
Puoi generare o modificare un'immagine in modo che corrisponda a uno stile specifico di un'immagine di riferimento, ad esempio il suo pattern, la sua texture o il suo design. Il modello utilizza l'immagine di riferimento per comprendere l'estetica richiesta e la applica alla nuova immagine descritta nel prompt di testo. Ad esempio, potresti generare l'immagine di un gatto nello stile di un famoso dipinto fornendo un'immagine di quel dipinto.
Definisci un riferimento di stile con ImagenStyleReference
e fornisci editImage
insieme a un prompt e ImagenEditingConfig
con il numero di editSteps
(un valore più alto può migliorare la qualità):
suspend fun customizeImageByStyle(model: ImagenModel, referenceVanGoghImage: Bitmap): ImagenGenerationResponse<ImagenInlineImage> {
// Define the style reference using the reference image.
val styleReference = ImagenStyleReference(
image = referenceVanGoghImage,
referenceID = 1,
description = "Van Gogh style"
)
// Provide a prompt that describes the final image.
// The "1" links the prompt to the style reference with ID 1.
val prompt = "A cat flying through outer space, in the Van Gogh style[1]"
// Use the editImage API to perform the style customization.
val editedImage = model.editImage(
references = listOf(styleReference),
prompt = prompt,
config = ImagenEditingConfig(
editSteps = 50 // Number of editing steps, a higher value can improve quality
)
)
return editedImage
}
Passaggi successivi
- Scopri di più su Firebase AI Logic nella documentazione di Firebase.
- Esplora il catalogo di esempi di AI per Android.