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 schermate 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 dell'API Firebase AI Logic: l'API Gemini Developer (consigliata per la maggior parte degli sviluppatori) e Vertex AI.
Sperimenta i prompt
La creazione dei prompt ideali spesso richiede più tentativi. Puoi sperimentare 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.12.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 creando un'istanza di 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 safetySettings parametro per configurare i
filtri di sicurezza e per le 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.getInstance(GenerativeBackend.googleAI()).imagenModel( "imagen-4.0-generate-001", config, new ImagenSafetySettings( ImagenSafetyFilterLevel.BLOCK_LOW_AND_ABOVE, ImagenPersonFilterLevel.BLOCK_ALL)) );
Una volta creata l'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
ListenableFuture<ImagenGenerationResponse<ImagenInlineImage>> futureResponse = model.generateImages( "A hyper realistic picture of a t-rex with a blue bagpack in a prehistoric forest"); try { ImagenGenerationResponse<ImagenInlineImage> imageResponse = futureResponse.get(); List<ImagenInlineImage> images = null; if (imageResponse != null) { images = imageResponse.getImages(); } if (images != null && !images.isEmpty()) { ImagenInlineImage image = images.get(0); Bitmap bitmapImage = image.asBitmap(); // Use bitmapImage } } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); }
Modifica le immagini con Imagen
Gli SDK Firebase AI Logic offrono funzionalità avanzate di modifica delle immagini tramite il modello Imagen, che ti consentono di:
- Modificare le immagini in base alle maschere, incluse azioni come l'inserimento o la rimozione di oggetti, l'estensione dei contenuti delle immagini oltre i limiti originali, e la modifica degli sfondi.
- Personalizzare le immagini applicando stili specifici (pattern, texture o stili di artisti), concentrandoti su vari soggetti (come prodotti, persone o animali) o rispettando diversi controlli (come uno schizzo disegnato a mano, un'immagine con bordi Canny o un mesh del volto).
Inizializzazione del modello
Per utilizzare le funzionalità di modifica di Imagen, specifica un modello Imagen che supporti la modifica delle immagini, ad esempio imagen-3.0-capability-001:
val imagenModel = Firebase.ai(backend = GenerativeBackend.vertexAI()) .imagenModel("imagen-3.0-capability-001")
Modifica basata su maschere
La modifica basata su maschere di Imagen consente di modificare le immagini definendo aree specifiche che il modello deve manipolare. 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 limiti originali.
Crea una maschera
Per eseguire la modifica basata su maschere, ad esempio l'inserimento o la rimozione di oggetti, devi definire l'area che deve essere modificata dal modello, ovvero la maschera.
Per creare una maschera, puoi farla generare automaticamente dal 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 = createMaskBitmap(sourceBitmap, paths) onMaskFinalized(maskBitmap) }, ) { Text("Save mask") } } }
Puoi quindi creare la bitmap della maschera disegnando i percorsi sulla tela:
// import android.graphics.Color as AndroidColor // import android.graphics.Paint private fun createMaskBitmap( sourceBitmap: Bitmap, paths: SnapshotStateList<Path>, ): Bitmap { val maskBitmap = Bitmap.createBitmap(sourceBitmap.width, sourceBitmap.height, Bitmap.Config.ARGB_8888) 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 maggiori dettagli, consulta gli esempi del catalogo di AI di Imagen AI Catalog Samples.
.Inserisci 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 relativa 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( referenceImages = listOf( ImagenRawImage(originalImage.toImagenInlineImage()), mask, ), prompt = prompt, // Define the editing configuration for inpainting and insertion. config = ImagenEditingConfig(ImagenEditMode.INPAINT_INSERTION) ) return editedImage }
Rimuovi 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. Facoltativamente, puoi includere un prompt di testo per descrivere l'oggetto, 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( referenceImages = listOf( ImagenRawImage(originalImage.toImagenInlineImage()), mask ), prompt = prompt, // Define the editing configuration for inpainting and removal. config = ImagenEditingConfig(ImagenEditMode.INPAINT_REMOVAL) ) return editedImage }
Espandi i contenuti delle immagini
Puoi espandere un'immagine oltre i limiti originali, operazione nota come outpainting,
utilizzando la funzione outpaintImage(). Questa funzione richiede l'immagine originale
e le Dimensions necessarie dell'immagine espansa.
Facoltativamente, puoi includere un prompt descrittivo per l'espansione e specificare
the 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 = imagenModel.outpaintImage( originalImage.toImagenInlineImage(), Dimensions(1024, 1024), prompt = prompt, newPosition = ImagenImagePlacement.LEFT_CENTER ) return editedImage }
Sostituisci 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( referenceImages = listOf( ImagenRawImage(originalImage.toImagenInlineImage()), ImagenBackgroundMask(), ), prompt = prompt, config = ImagenEditingConfig(ImagenEditMode.INPAINT_INSERTION) ) return editedImage }
Personalizzazione
Puoi utilizzare la funzionalità di personalizzazione di Imagen per generare o modificare immagini in base a immagini di riferimento che specificano un soggetto, un controllo o uno stile. Per farlo, fornisci un prompt di testo insieme a una o più immagini di riferimento per guidare il modello.
Personalizza in base a un soggetto
Puoi generare nuove immagini di un soggetto specifico da un'immagine di riferimento (ad esempio, un prodotto, una persona o un animale). Ti basta fornire un prompt di testo e almeno un'immagine di riferimento del soggetto. Ad esempio, puoi caricare una foto del tuo animale domestico e generare una nuova immagine in un ambiente completamente diverso.
Per farlo, definisci il riferimento del soggetto utilizzando ImagenSubjectReference e poi passalo a editImage insieme al prompt. Inoltre, includi un ImagenEditingConfig che specifichi il numero di editSteps; un valore editSteps più alto in genere 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.toImagenInlineImage(), 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( referenceImages = listOf(subjectReference), prompt = prompt, config = ImagenEditingConfig( editSteps = 50 // Number of editing steps, a higher value can improve quality ) ) return editedImage }
Personalizza in base a un controllo
Questa tecnica genera una nuova immagine basata su un' immagine di riferimento di controllo, ad esempio uno schizzo disegnato a mano ("scarabocchio"), un' immagine con bordi Canny, o un 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 forniscilo a editImage insieme a un prompt e a ImagenEditingConfig con il numero di editSteps (un valore più alto può migliorare la qualità):
suspend fun customizeCatImageByControl(model: ImagenModel, referenceImage: Bitmap): ImagenGenerationResponse<ImagenInlineImage> { // Define the subject reference using the reference image. val controlReference = ImagenControlReference( image = referenceImage.toImagenInlineImage(), referenceId = 1, type = ImagenControlType.SCRIBBLE, ) val prompt = "A cat flying through outer space arranged like the scribble map[1]" val editedImage = model.editImage( referenceImages = listOf(controlReference), prompt = prompt, config = ImagenEditingConfig( editSteps = 50 ), ) return editedImage }
Personalizza 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 pattern, la texture o il 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, puoi 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 forniscilo a editImage insieme a un prompt e a 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.toImagenInlineImage(), 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( referenceImages = 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.