Imagen es un modelo de generación de imágenes. Se puede usar para generar avatares personalizados para perfiles de usuario o para integrar recursos visuales personalizados en flujos de pantallas existentes para aumentar la participación de los usuarios.
Puedes acceder a los modelos de Imagen desde tu app para Android con el SDK de Firebase AI Logic. Los modelos de Imagen están disponibles a través de los proveedores de la API de Firebase AI Logic: la API de Gemini Developer (recomendada para la mayoría de los desarrolladores) y Vertex AI.
Experimenta con instrucciones
Crear las instrucciones ideales suele requerir varios intentos. Puedes experimentar con instrucciones de imágenes en Google AI Studio, un IDE para el diseño y la creación de prototipos de instrucciones. Si quieres obtener sugerencias para mejorar tus instrucciones, consulta la guía de atributos de imágenes y mensajes.

Configura un proyecto de Firebase y conecta tu app
Sigue los pasos que se indican en la documentación de Firebase para agregar Firebase a tu proyecto de Android.
Agrega la dependencia de Gradle
Agrega las siguientes dependencias a tu archivo 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 una imagen
Para generar una imagen en tu app para Android, primero crea una instancia de ImagenModel
con una configuración opcional.
Puedes usar el parámetro generationConfig
para definir una instrucción negativa, la cantidad de imágenes, la relación de aspecto de la imagen de salida, el formato de la imagen y agregar una marca de agua. Puedes usar el parámetro safetySettings
para configurar los filtros de seguridad y de personas.
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 vez que se crea una instancia de tu ImagenModel
, puedes generar imágenes llamando a 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();
}
Edita imágenes con Imagen
Los SDKs de Firebase AI Logic ofrecen capacidades avanzadas de edición de imágenes a través del modelo Imagen, lo que te permite hacer lo siguiente:
- Edita imágenes basadas en máscaras, lo que incluye acciones como insertar o quitar objetos, extender el contenido de la imagen más allá de sus límites originales y cambiar fondos.
- Personaliza imágenes aplicando estilos específicos (patrones, texturas o estilos de artistas), enfocándote en varios temas (como productos, personas o animales) o siguiendo diferentes controles (como un boceto dibujado a mano, una imagen de borde de Canny o una malla facial).
Inicialización del modelo
Para usar las funciones de edición de Imagen, especifica un modelo de Imagen que admita la edición de imágenes, como imgen-3.0-capability-001
. versión del modelo:
val imagenModel = Firebase.ai(backend = GenerativeBackend.vertexAI())
.imagenModel("imagen-3.0-capability-001")
Edición basada en máscaras
La edición basada en máscaras de Imagen permite modificar imágenes definiendo áreas específicas para que el modelo las manipule. Esta capacidad permite realizar una variedad de acciones, como crear y aplicar máscaras, insertar o quitar objetos, y expandir el contenido de la imagen más allá de los límites originales.
Cómo crear una máscara
Para realizar ediciones basadas en máscaras, como insertar o quitar objetos, debes definir el área que el modelo debe editar, es decir, la máscara.
Para crear una máscara, puedes hacer que el modelo la genere automáticamente con ImagenBackgroundMask()
o ImagenSemanticMask()
, y pasar un ID de clase.
También puedes dibujar la máscara de forma manual en la pantalla. Para ello, genera un mapa de bits de la máscara y conviértelo en un ImagenRawMask
. Con detectDragGestures
y Canvas
, puedes implementar una interfaz de usuario de dibujo de máscaras con Jetpack Compose en tu app de la siguiente manera:
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")
}
}
}
Luego, puedes crear el mapa de bits de la máscara dibujando las rutas de acceso en el lienzo:
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
}
Asegúrate de que la máscara tenga el mismo tamaño que la imagen de origen. Consulta las Muestras del catálogo de IA de Imagen para obtener más detalles.
Cómo insertar objetos
Puedes insertar un objeto o contenido nuevo en una imagen existente, lo que también se conoce como relleno. El modelo generará e insertará el contenido nuevo en el área enmascarada especificada.
Para lograrlo, usa la función editImage()
. Deberás proporcionar la imagen original, una máscara y una instrucción de texto que describa el contenido que deseas insertar. Además, pasa un objeto ImagenEditingConfig
y asegúrate de que su propiedad editMode
esté establecida en 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
}
Cómo quitar objetos
El retoque te permite quitar objetos no deseados de una imagen. Para ello, usa la función editImage
. Deberás proporcionar la imagen original y una máscara que destaque el objeto que deseas quitar. De manera opcional, puedes incluir una instrucción de texto para describir el objeto, lo que puede ayudar al modelo a identificarlo con precisión. Además, debes establecer editMode
dentro de ImagenEditingConfig
en 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
}
Expande el contenido de la imagen
Puedes expandir una imagen más allá de sus límites originales, lo que se conoce como expansión de imagen, con la función outpaintImage()
. Esta función requiere la imagen original y el Dimensions
necesario de la imagen expandida.
De manera opcional, puedes incluir una instrucción descriptiva para la expansión y especificar el ImagenImagePlacement
de la imagen original dentro de la nueva imagen generada:
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
}
Reemplaza el fondo
Puedes reemplazar el fondo de una imagen y conservar el sujeto en primer plano. Para ello, usa la función editImage
. Pasa la imagen original, un objeto ImagenBackgroundMask
(que contiene una instrucción de texto para el nuevo fondo) y un ImagenEditingConfig
con su propiedad editMode
establecida en 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
}
Personalización
Puedes usar la capacidad de personalización de Imagen para generar o editar imágenes basadas en imágenes de referencia que especifican un tema, un control o un estilo. Esto se logra proporcionando una instrucción de texto junto con una o más imágenes de referencia para guiar el modelo.
Personaliza el contenido según un tema
Puedes generar imágenes nuevas de un tema específico a partir de una imagen de referencia (por ejemplo, un producto, una persona o un animal). Solo tienes que proporcionar una instrucción de texto y, al menos, una imagen de referencia del sujeto. Por ejemplo, podrías subir una foto de tu mascota y generar una imagen nueva de ella en un entorno completamente diferente.
Para ello, define la referencia del tema con ImagenSubjectReference
y, luego, pásala a editImage
junto con tu instrucción. Además, incluye un ImagenEditingConfig
que especifique la cantidad de editSteps
. Por lo general, un valor de editSteps
más alto genera resultados de mejor calidad:
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
}
Personaliza en función de un control
Esta técnica genera una imagen nueva basada en una imagen de referencia de control, como un boceto dibujado a mano ("garabato"), una imagen de borde de Canny o una malla facial. El modelo usa la imagen de control como guía estructural para el diseño y la composición de la imagen nueva, mientras que la instrucción de texto proporciona detalles como el color y la textura.
Define una referencia de control con ImagenControlReference
y proporciónala a editImage
junto con una instrucción y ImagenEditingConfig
con la cantidad de editSteps
(un valor más alto puede mejorar la calidad):
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
}
Personaliza el diseño según un estilo
Puedes generar o editar una imagen para que coincida con un estilo específico de una imagen de referencia, como su patrón, textura o diseño. El modelo usa la imagen de referencia para comprender la estética requerida y la aplica a la nueva imagen descrita en la instrucción de texto. Por ejemplo, podrías generar una imagen de un gato al estilo de una pintura famosa si proporcionas una imagen de esa pintura.
Define una referencia de estilo con ImagenStyleReference
y proporciónala a editImage
junto con una instrucción y ImagenEditingConfig
con la cantidad de editSteps
(un valor más alto puede mejorar la calidad):
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
}
Próximos pasos
- Obtén más información sobre Firebase AI Logic en la documentación de Firebase.
- Explora el Catálogo de muestras de IA de Android.