Imagen est un modèle de génération d'images. Il peut être utilisé pour générer des avatars personnalisés pour les profils utilisateur ou pour intégrer des composants visuels personnalisés dans des flux d'écran existants afin d'accroître l'engagement des utilisateurs.
Vous pouvez accéder aux modèles Imagen depuis votre application Android à l'aide du SDK Firebase AI Logic. Les modèles Imagen sont disponibles avec les fournisseurs d'API Firebase AI Logic : l'API Gemini Developer (recommandée pour la plupart des développeurs) et Vertex AI.
Tester des requêtes
Il faut souvent plusieurs tentatives pour créer les requêtes idéales. Vous pouvez tester les requêtes d'image dans Google AI Studio, un IDE pour la conception et le prototypage de requêtes. Pour obtenir des conseils sur l'amélioration de vos requêtes, consultez le guide des attributs de requête et d'image.

Configurer un projet Firebase et associer votre application
Suivez les étapes de la documentation Firebase pour ajouter Firebase à votre projet Android.
Ajouter la dépendance Gradle
Ajoutez les dépendances suivantes à votre fichier 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")
}
Générer une image
Pour générer une image dans votre application Android, commencez par instancier un ImagenModel
avec une configuration facultative.
Vous pouvez utiliser le paramètre generationConfig
pour définir un prompt négatif, le nombre d'images, les proportions de l'image de sortie, le format de l'image et ajouter un filigrane. Vous pouvez utiliser le paramètre safetySettings
pour configurer les filtres de sécurité et de personnes.
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())
);
Une fois votre ImagenModel
instancié, vous pouvez générer des images en appelant 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();
}
Modifier des images avec Imagen
Les SDK Firebase AI Logic offrent des fonctionnalités avancées de retouche d'images grâce au modèle Imagen. Ils vous permettent de :
- Modifier des images en fonction de masques, y compris des actions telles que l'insertion ou la suppression d'objets, l'extension du contenu d'une image au-delà de ses limites d'origine et la modification des arrière-plans.
- Personnalisez les images en appliquant des styles spécifiques (motifs, textures ou styles d'artistes), en vous concentrant sur différents sujets (produits, personnes ou animaux, par exemple) ou en respectant différents contrôles (croquis dessiné à la main, image de contour canny ou maillage facial, par exemple).
Initialisation du modèle
Pour utiliser les fonctionnalités de retouche d'Imagen, spécifiez un modèle Imagen compatible avec la retouche d'images, comme imgen-3.0-capability-001
. la version du modèle ;
val imagenModel = Firebase.ai(backend = GenerativeBackend.vertexAI())
.imagenModel("imagen-3.0-capability-001")
Édition basée sur un masque
La modification basée sur un masque d'Imagen permet de modifier des images en définissant des zones spécifiques que le modèle doit manipuler. Cette fonctionnalité permet d'effectuer diverses actions, y compris de créer et d'appliquer des masques, d'insérer ou de supprimer des objets, et d'étendre le contenu d'une image au-delà de ses limites d'origine.
Créer un masque
Pour effectuer des modifications basées sur des masques, comme insérer ou supprimer des objets, vous devez définir la zone à modifier par le modèle, c'est-à-dire le masque.
Pour créer un masque, vous pouvez le faire générer automatiquement par le modèle à l'aide de ImagenBackgroundMask()
ou ImagenSemanticMask()
, en transmettant un ID de classe.
Vous pouvez également dessiner manuellement le masque à l'écran en générant un bitmap de masque et en le convertissant en ImagenRawMask
. À l'aide de detectDragGestures
et Canvas
, vous pouvez implémenter une interface utilisateur de dessin de masque avec Jetpack Compose dans votre application comme suit :
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")
}
}
}
Vous pouvez ensuite créer le bitmap du masque en dessinant les chemins d'accès sur le canevas :
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
}
Assurez-vous que le masque a la même taille que l'image source. Pour en savoir plus, consultez les exemples de catalogue Imagen AI.
Insérer des objets
Vous pouvez insérer un nouvel objet ou contenu dans une image existante, ce que l'on appelle l'inpainting. Le modèle génère et insère le nouveau contenu dans la zone masquée spécifiée.
Pour ce faire, utilisez la fonction editImage()
. Vous devrez fournir l'image d'origine, un masque et un prompt textuel décrivant le contenu que vous souhaitez insérer. Transmettez également un objet ImagenEditingConfig
en vous assurant que sa propriété editMode
est définie sur 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
}
Supprimer des objets
Le remplissage permet de supprimer les objets indésirables d'une image. Pour ce faire, utilisez la fonction editImage
. Vous devrez fournir l'image d'origine et un masque qui met en évidence l'objet que vous souhaitez supprimer. Vous pouvez éventuellement inclure une requête textuelle pour décrire l'objet, ce qui peut aider le modèle à l'identifier avec précision. De plus, vous devez définir editMode
dans ImagenEditingConfig
sur 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
}
Développer le contenu de l'image
Vous pouvez étendre une image au-delà de ses limites d'origine, ce que l'on appelle l'outpainting, à l'aide de la fonction outpaintImage()
. Cette fonction nécessite l'image d'origine et les Dimensions
nécessaires de l'image agrandie.
Vous pouvez également inclure une invite descriptive pour l'expansion et spécifier le ImagenImagePlacement
de l'image d'origine dans la nouvelle image générée :
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
}
Remplacer l'arrière-plan
Vous pouvez remplacer l'arrière-plan d'une image tout en conservant le sujet au premier plan. Pour ce faire, utilisez la fonction editImage
. Transmettez l'image d'origine, un objet ImagenBackgroundMask
(contenant une requête textuelle pour le nouvel arrière-plan) et un ImagenEditingConfig
avec sa propriété editMode
définie sur 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
}
Personnalisation
Vous pouvez utiliser la fonctionnalité de personnalisation d'Imagen pour générer ou modifier des images en fonction d'images de référence qui spécifient un sujet, un contrôle ou un style. Pour ce faire, il faut fournir une invite textuelle ainsi qu'une ou plusieurs images de référence pour guider le modèle.
Personnaliser en fonction d'un sujet
Vous pouvez générer de nouvelles images d'un sujet spécifique à partir d'une image de référence (par exemple, un produit, une personne ou un animal). Il vous suffit de fournir une requête textuelle et au moins une image de référence du sujet. Par exemple, vous pouvez importer une photo de votre animal de compagnie et générer une nouvelle image de celui-ci dans un environnement complètement différent.
Pour ce faire, définissez la référence du sujet à l'aide de ImagenSubjectReference
, puis transmettez-la à editImage
avec votre requête. Incluez également un ImagenEditingConfig
qui spécifie le nombre de editSteps
. Une valeur editSteps
plus élevée conduit généralement à des résultats de meilleure qualité :
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
}
Personnaliser en fonction d'un contrôle
Cette technique génère une image à partir d'une image de référence de contrôle, comme un croquis dessiné à la main, une image de contours Canny ou un maillage facial. Le modèle utilise l'image de contrôle comme guide structurel pour la mise en page et la composition de la nouvelle image, tandis que la requête textuelle fournit des détails tels que la couleur et la texture.
Définissez une référence de contrôle avec ImagenControlReference
et fournissez-la à editImage
avec une invite et ImagenEditingConfig
avec le nombre de editSteps
(une valeur plus élevée peut améliorer 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
}
Personnaliser en fonction d'un style
Vous pouvez générer ou modifier une image pour qu'elle corresponde à un style spécifique à partir d'une image de référence, comme son motif, sa texture ou son design. Le modèle utilise l'image de référence pour comprendre l'esthétique requise et l'applique à la nouvelle image décrite dans le prompt textuel. Par exemple, vous pouvez générer une image de chat dans le style d'un tableau célèbre en fournissant une image de ce tableau.
Définissez une référence de style avec ImagenStyleReference
et fournissez-la à editImage
avec un prompt et ImagenEditingConfig
avec le nombre de editSteps
(une valeur plus élevée peut améliorer 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
}
Étapes suivantes
- Pour en savoir plus sur Firebase AI Logic, consultez la documentation Firebase.
- Explorez le catalogue d'exemples d'IA Android.