Imagen ist ein Bildgenerierungsmodell. Es kann verwendet werden, um benutzerdefinierte Avatare für Nutzerprofile zu generieren oder personalisierte visuelle Assets in vorhandene Bildschirmabläufe zu integrieren, um die Nutzerinteraktion zu steigern.
Sie können über das Firebase AI Logic SDK von Ihrer Android-App aus auf Imagen-Modelle zugreifen. Imagen-Modelle sind mit beiden Firebase AI Logic API-Anbietern verfügbar: Gemini Developer API (für die meisten Entwickler empfohlen) und Vertex AI.
Mit Prompts experimentieren
Das Erstellen der idealen Prompts erfordert oft mehrere Versuche. Sie können in Google AI Studio mit Bild-Prompts experimentieren . Google AI Studio ist eine IDE für das Prompt-Design und die Prototyperstellung. Tipps zur Verbesserung Ihrer Prompts finden Sie im Leitfaden Prompts und Bildattribute.
Firebase-Projekt einrichten und App verbinden
Folgen Sie der Anleitung in der Firebase-Dokumentation, um Ihrem Android-Projekt Firebase hinzuzufügen.
Gradle-Abhängigkeit hinzufügen
Fügen Sie der Datei build.gradle die folgenden Abhängigkeiten hinzu:
dependencies {
// Import the BoM for the Firebase platform
implementation(platform("com.google.firebase:firebase-bom:34.15.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")
}
Bild generieren
Wenn Sie in Ihrer Android-App ein Bild generieren möchten, instanziieren Sie zuerst ein ImagenModel mit einer optionalen Konfiguration.
Mit dem generationConfig Parameter können Sie einen negativen Prompt,
die Anzahl der Bilder, das Seitenverhältnis des Ausgabebilds und das Bildformat definieren sowie ein
Wasserzeichen hinzufügen. Mit dem safetySettings Parameter können Sie die
Filter für Sicherheit und Personen konfigurieren.
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)) );
Sobald Ihr ImagenModel instanziiert ist, können Sie Bilder generieren, indem Sie generateImages aufrufen:
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(); }
Bilder mit Imagen bearbeiten
Die Firebase AI Logic SDKs bieten erweiterte Bildbearbeitungsfunktionen über das Imagen-Modell. Damit können Sie Folgendes tun:
- Bilder anhand von Masken bearbeiten , einschließlich Aktionen wie das Einfügen oder Entfernen von Objekten, das Erweitern von Bildinhalten über die ursprünglichen Grenzen hinaus und das Ändern von Hintergründen.
- Bilder anpassen , indem Sie bestimmte Stile anwenden (Muster, Texturen oder Künstlerstile), sich auf verschiedene Motive konzentrieren (z. B. Produkte, Personen oder Tiere) oder verschiedene Steuerelemente verwenden (z. B. eine handgezeichnete Skizze, ein Canny-Edge-Bild oder ein Gesichtsnetz).
Modellinitialisierung
Wenn Sie die Imagen-Bearbeitungsfunktionen verwenden möchten, geben Sie ein Imagen-Modell an, das die Bild
bearbeitung unterstützt, z. B. imagen-3.0-capability-001:
val imagenModel = Firebase.ai(backend = GenerativeBackend.vertexAI()) .imagenModel("imagen-3.0-capability-001")
Maskenbasierte Bearbeitung
Mit der maskenbasierten Bearbeitung von Imagen können Sie Bilder ändern, indem Sie bestimmte Bereiche definieren, die das Modell bearbeiten soll. Diese Funktion ermöglicht eine Reihe von Aktionen, darunter das Erstellen und Anwenden von Masken, das Einfügen oder Entfernen von Objekten und das Erweitern von Bildinhalten über die ursprünglichen Grenzen hinaus.
Maske erstellen
Für die maskenbasierte Bearbeitung, z. B. das Einfügen oder Entfernen von Objekten, müssen Sie den Bereich definieren, der vom Modell bearbeitet werden soll, die Maske.
Sie können eine Maske automatisch vom Modell generieren lassen, indem Sie
ImagenBackgroundMask() oder ImagenSemanticMask() verwenden und eine Klassen
ID übergeben.
Sie können die Maske auch manuell auf dem Bildschirm zeichnen, indem Sie eine Maskenbitmap generieren und in ein ImagenRawMask umwandeln. Mit detectDragGestures und Canvas können Sie in Ihrer App eine Benutzeroberfläche zum Zeichnen von Masken mit Jetpack Compose implementieren:
//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") } } }
Sie können dann die Maskenbitmap erstellen, indem Sie die Pfade auf die Canvas zeichnen:
// 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 }
Die Maske muss dieselbe Größe wie das Quellbild haben. Weitere Informationen finden Sie in den Imagen AI Catalog Samples.
Objekte einfügen
Sie können ein neues Objekt oder einen neuen Inhalt in ein vorhandenes Bild einfügen. Das wird auch als Inpainting bezeichnet. Das Modell generiert den neuen Inhalt und fügt ihn in den angegebenen maskierten Bereich ein.
Verwenden Sie dazu die Funktion editImage(). Sie müssen das
Originalbild, eine Maskeund einen Text-Prompt
angeben, der den einzufügenden Inhalt beschreibt. Übergeben Sie außerdem ein ImagenEditingConfig-Objekt und stellen Sie sicher, dass die Property editMode auf ImagenEditMode.INPAINT_INSERTION gesetzt ist.
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 }
Objekte entfernen
Mit Inpainting können Sie unerwünschte Objekte aus einem Bild entfernen. Verwenden Sie dazu die Funktion editImage. Sie müssen das Originalbild und eine
Maske angeben, die das zu entfernende Objekt hervorhebt. Optional können Sie einen Text-Prompt hinzufügen, um das Objekt zu beschreiben. Das kann dem Modell helfen, es genau zu identifizieren. Außerdem müssen Sie editMode in ImagenEditingConfig auf ImagenEditMode.INPAINT_REMOVAL setzen.
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 }
Bildinhalte erweitern
Mit der Funktion outpaintImage() können Sie ein Bild über seine ursprünglichen Grenzen hinaus erweitern. Das wird als Outpainting bezeichnet.
Für diese Funktion sind das Original
bild und die erforderlichen Dimensions des erweiterten Bilds erforderlich.
Optional können Sie einen beschreibenden Prompt für die Erweiterung angeben und die
das ImagenImagePlacement des Originalbilds im
neu generierten Bild festlegen:
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 }
Hintergrund ersetzen
Sie können den Hintergrund eines Bilds ersetzen und dabei das Vordergrundmotiv beibehalten. Verwenden Sie dazu die Funktion editImage. Übergeben Sie das Originalbild, ein ImagenBackgroundMask-Objekt (mit einem Text-Prompt für den neuen Hintergrund) und ein ImagenEditingConfig-Objekt, dessen Property editMode auf ImagenEditMode.INPAINT_INSERTION gesetzt ist.
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 }
Anpassung
Mit der Anpassungsfunktion von Imagen können Sie Bilder anhand von Referenzbildern generieren oder bearbeiten, die ein Motiv, ein Steuerelement oder einen Stil angeben. Dazu geben Sie einen Text-Prompt zusammen mit einem oder mehreren Referenzbildern an, um das Modell zu steuern.
Anpassung anhand eines Motivs
Sie können neue Bilder eines bestimmten Motivs aus einem Referenzbild generieren (z. B. ein Produkt, eine Person oder ein Tier). Geben Sie einfach einen Text-Prompt und mindestens ein Referenzbild des Motivs an. Sie könnten beispielsweise ein Bild Ihres Haustiers hochladen und ein neues Bild davon in einer völlig anderen Umgebung generieren.
Definieren Sie dazu die Motivreferenz mit ImagenSubjectReference und übergeben Sie sie zusammen mit Ihrem Prompt an editImage. Fügen Sie außerdem ein ImagenEditingConfig-Objekt hinzu, das die Anzahl der editSteps angibt. Ein höherer Wert für editSteps führt in der Regel zu besseren Ergebnissen:
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 }
Anpassung anhand eines Steuerelements
Mit dieser Technik wird ein neues Bild anhand eines Steuerungsreferenzbilds, z. B. einer handgezeichneten Skizze („Scribble“), eines Canny-Edge-Bilds, oder eines Gesichtsnetzes generiert. Das Modell verwendet das Steuerungsbild als strukturelle Anleitung für das Layout und die Komposition des neuen Bilds, während der Text-Prompt Details wie Farbe und Textur liefert.
Definieren Sie eine Steuerungsreferenz mit ImagenControlReference und übergeben Sie sie zusammen mit einem Prompt und ImagenEditingConfig mit der Anzahl der editSteps an editImage. Ein höherer Wert kann die Qualität verbessern:
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 }
Anpassung anhand eines Stils
Sie können ein Bild generieren oder bearbeiten, um es an einen bestimmten Stil aus einem Referenzbild anzupassen, z. B. an sein Muster, seine Textur oder sein Design. Das Modell verwendet das Referenzbild, um die erforderliche Ästhetik zu verstehen, und wendet sie auf das neue Bild an, das im Text-Prompt beschrieben wird. Sie könnten beispielsweise ein Bild einer Katze im Stil eines berühmten Gemäldes generieren, indem Sie ein Bild dieses Gemäldes angeben.
Definieren Sie eine Stilreferenz mit ImagenStyleReference und übergeben Sie sie zusammen mit einem Prompt und ImagenEditingConfig mit der Anzahl der editSteps an editImage. Ein höherer Wert kann die Qualität verbessern:
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 }
Nächste Schritte
- Weitere Informationen zu Firebase AI Logic finden Sie in der Firebase Dokumentation.
- Den Android AI Sample Catalog ansehen