O Imagen é um modelo de geração de imagens. Ele pode ser usado para gerar avatares personalizados para perfis de usuários ou integrar recursos visuais personalizados aos fluxos de tela atuais para aumentar o engajamento do usuário.
É possível acessar os modelos do Imagen no seu app Android usando o Firebase AI Logic SDK. Os modelos do Imagen estão disponíveis usando os dois provedores da API Firebase AI Logic: a API Gemini Developer (recomendada para a maioria dos desenvolvedores) e a Vertex AI.
Teste os comandos
A criação dos comandos ideais geralmente exige várias tentativas. É possível testar comandos de imagem em Google AI Studio, um ambiente de desenvolvimento integrado para design e prototipagem de comandos. Para conferir dicas sobre como melhorar seus comandos, consulte o guia de comandos e atributos de imagem.
Configurar um projeto do Firebase e conectar seu app
Siga as etapas na documentação do Firebase para adicionar o Firebase ao seu Projeto do Android.
Adicionar a dependência do Gradle
Adicione as seguintes dependências ao arquivo build.gradle:
dependencies {
// Import the BoM for the Firebase platform
implementation(platform("com.google.firebase:firebase-bom:34.11.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")
}
Gerar uma imagem
Para gerar uma imagem no seu app Android, comece instanciando um ImagenModel com uma configuração opcional.
É possível usar o parâmetro generationConfig para definir um comando negativo,
o número de imagens, a proporção da imagem de saída, o formato da imagem e adicionar uma
marca d'água. Você pode usar o safetySettings parâmetro para configurar os
filtros de segurança e de pessoas.
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)) );
Depois que o ImagenModel for instanciado, você poderá gerar imagens chamando 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(); }
Editar imagens com o Imagen
Os SDKs do Firebase AI Logic oferecem recursos avançados de edição de imagens pelo modelo do Imagen, permitindo que você:
- Edite imagens com base em máscaras, que incluem ações como inserir ou remover objetos, estender o conteúdo da imagem além dos limites originais, e mudar planos de fundo.
- Personalize imagens aplicando estilos específicos (padrões, texturas ou estilos de artistas), concentrando-se em vários assuntos (como produtos, pessoas ou animais) ou aderindo a diferentes controles (como um esboço desenhado à mão, uma imagem de borda nítida ou uma malha facial).
Inicialização do modelo
Para usar os recursos de edição do Imagen, especifique um modelo do Imagen que ofereça suporte à edição de imagens, como imagen-3.0-capability-001:
val imagenModel = Firebase.ai(backend = GenerativeBackend.vertexAI()) .imagenModel("imagen-3.0-capability-001")
Edição baseada em máscara
A edição baseada em máscara do Imagen permite modificações em imagens definindo áreas específicas para o modelo manipular. Esse recurso permite uma variedade de ações, incluindo a criação e aplicação de máscaras, a inserção ou remoção de objetos e a expansão do conteúdo da imagem além dos limites originais.
Criar uma máscara
Para realizar edições baseadas em máscara, como inserir ou remover objetos, é necessário definir a área que precisa ser editada pelo modelo, a máscara.
Para criar uma máscara, você pode fazer com que o modelo a gere automaticamente usando
ImagenBackgroundMask() ou ImagenSemanticMask(), transmitindo um ID
de classe.
Também é possível desenhar a máscara manualmente na tela, gerando um bitmap de máscara e convertendo-o em um ImagenRawMask. Usando detectDragGestures e Canvas, você pode implementar uma interface do usuário de desenho de máscara com o Jetpack Compose no seu app da seguinte maneira:
//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") } } }
Em seguida, crie o bitmap da máscara desenhando os caminhos na 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 }
Verifique se a máscara tem o mesmo tamanho da imagem de origem. Consulte os exemplos do catálogo de IA do Imagen AI para mais detalhes.
Inserir objetos
É possível inserir um novo objeto ou conteúdo em uma imagem atual, também chamado de retoque. O modelo vai gerar e inserir o novo conteúdo na área mascarada especificada.
Para fazer isso, use a função editImage(). Você precisará fornecer a
imagem original, uma máscara, e um comando de texto
que descreva o conteúdo que você quer inserir. Além disso, transmita um objeto ImagenEditingConfig, garantindo que a propriedade editMode esteja definida como 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 }
Remover objetos
O retoque permite remover objetos indesejados de uma imagem. Para fazer isso, use a função editImage. Você precisará fornecer a imagem original e uma
máscara que destaque o objeto que você quer
remover. Opcionalmente, você pode incluir um comando de texto para descrever o objeto, o que pode ajudar o modelo na identificação precisa. Além disso, é necessário definir o editMode no ImagenEditingConfig como 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 }
Expandir o conteúdo da imagem
É possível expandir uma imagem além dos limites originais, conhecido como outpainting,
usando a função outpaintImage(). Essa função exige a imagem original
e as Dimensions necessárias da imagem expandida.
Opcionalmente, você pode incluir um comando descritivo para a expansão e especificar
o ImagenImagePlacement da imagem original na
nova imagem gerada:
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 }
Substituir o plano de fundo
É possível substituir o plano de fundo de uma imagem, preservando o assunto em primeiro plano. Para fazer isso, use a função editImage. Transmita a imagem original, um objeto ImagenBackgroundMask (que contém um comando de texto para o novo plano de fundo) e um ImagenEditingConfig com a propriedade editMode definida como 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 }
Personalização
É possível usar o recurso de personalização do Imagen para gerar ou editar imagens com base em imagens de referência que especificam um assunto, controle ou estilo. Isso é feito fornecendo um comando de texto com uma ou mais imagens de referência para orientar o modelo.
Personalizar com base em um assunto
É possível gerar novas imagens de um assunto específico a partir de uma imagem de referência (por exemplo, um produto, pessoa ou animal). Basta fornecer um comando de texto e pelo menos uma imagem de referência do assunto. Por exemplo, você pode fazer upload de uma foto do seu animal de estimação e gerar uma nova imagem dele em um ambiente completamente diferente.
Para fazer isso, defina a referência do assunto usando ImagenSubjectReference e transmita-a para editImage com o comando. Além disso, inclua um ImagenEditingConfig que especifique o número de editSteps. Um valor editSteps mais alto geralmente leva a resultados de melhor qualidade:
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 }
Personalizar com base em um controle
Essa técnica gera uma nova imagem com base em uma imagem de referência de controle, como um esboço desenhado à mão ("rabisco"), uma imagem de borda nítida, ou uma malha facial. O modelo usa a imagem de controle como um guia estrutural para o layout e a composição da nova imagem, enquanto o comando de texto fornece detalhes como cor e textura.
Defina uma referência de controle com ImagenControlReference e forneça-a para editImage com um comando e ImagenEditingConfig com o número de editSteps (um valor mais alto pode melhorar a qualidade):
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 }
Personalizar com base em um estilo
É possível gerar ou editar uma imagem para corresponder a um estilo específico de uma imagem de referência, como padrão, textura ou design. O modelo usa a imagem de referência para entender a estética necessária e a aplica à nova imagem descrita no comando de texto. Por exemplo, você pode gerar uma imagem de um gato no estilo de uma pintura famosa fornecendo uma imagem dessa pintura.
Defina uma referência de estilo com ImagenStyleReference e forneça-a para editImage com um comando e ImagenEditingConfig com o número de editSteps (um valor mais alto pode melhorar a qualidade):
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 }
Próximas etapas
- Saiba mais sobre a lógica de IA do Firebase na documentação do Firebase AI Logic.
- Confira o catálogo de amostras de IA do Android.