Imagen — это модель генерации изображений. Она может использоваться для создания пользовательских аватаров для профилей пользователей или для интеграции персонализированных визуальных элементов в существующие сценарии взаимодействия с пользователем для повышения вовлеченности пользователей.
Вы можете получить доступ к моделям Imagen из своего Android-приложения, используя SDK Firebase AI Logic. Модели Imagen доступны через оба API-провайдера Firebase AI Logic: Gemini Developer API (рекомендуется большинству разработчиков) и Vertex AI.
Поэкспериментируйте с подсказками.
Создание идеальных подсказок часто требует нескольких попыток. Вы можете поэкспериментировать с подсказками в виде изображений в Google AI Studio , интегрированной среде разработки для создания подсказок и прототипирования. Советы по улучшению подсказок можно найти в руководстве по атрибутам подсказок и изображений .

Создайте проект Firebase и подключите к нему свое приложение.
Чтобы добавить Firebase в свой Android-проект , следуйте инструкциям в документации Firebase.
Добавьте зависимость Gradle.
Добавьте следующие зависимости в файл build.gradle :
dependencies {
// Import the BoM for the Firebase platform
implementation(platform("com.google.firebase:firebase-bom:34.8.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")
}
Сгенерировать изображение
Для генерации изображения в вашем Android-приложении начните с создания экземпляра ImagenModel с необязательной конфигурацией.
Параметр generationConfig позволяет задать отрицательное значение подсказки, количество изображений, соотношение сторон выходного изображения, формат изображения и добавить водяной знак. Параметр safetySettings позволяет настроить фильтры безопасности и идентификации людей.
Котлин
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)) );
После создания экземпляра ImagenModel вы можете генерировать изображения, вызвав метод generateImages :
Котлин
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(); }
Редактируйте изображения с помощью Imagen
SDK Firebase AI Logic предоставляют расширенные возможности редактирования изображений благодаря модели Imagen, позволяя вам:
- Редактирование изображений на основе масок включает в себя такие действия, как вставка или удаление объектов, расширение содержимого изображения за пределы его исходных границ и изменение фона.
- Настраивайте изображения, применяя определенные стили (узоры, текстуры или художественные стили), фокусируясь на различных объектах (таких как товары, люди или животные) или используя различные параметры (например, эскиз, нарисованный от руки, изображение с эффектом "умных краев" или сетку лица).
Инициализация модели
Для использования функций редактирования изображений в Imagen укажите модель Imagen, поддерживающую редактирование изображений, например, imagen-3.0-capability-001 :
val imagenModel = Firebase.ai(backend = GenerativeBackend.vertexAI()) .imagenModel("imagen-3.0-capability-001")
Редактирование на основе масок
Функция редактирования на основе масок в Imagen позволяет вносить изменения в изображения, определяя конкретные области для манипуляций моделью. Эта возможность обеспечивает широкий спектр действий, включая создание и применение масок, вставку или удаление объектов, а также расширение содержимого изображения за пределы исходных границ.
Создать маску
Для выполнения редактирования с использованием маски, например, вставки или удаления объектов, необходимо определить область, которую модель должна редактировать, — маску .
Для создания маски можно использовать автоматическую генерацию модели с помощью функций ImagenBackgroundMask() или ImagenSemanticMask() , передав идентификатор класса .
Вы также можете вручную нарисовать маску на экране, сгенерировав растровое изображение маски и преобразовав его в ImagenRawMask . Используя detectDragGestures и Canvas , вы можете реализовать пользовательский интерфейс для рисования маски с помощью Jetpack Compose в своем приложении следующим образом:
//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") } } }
Затем вы можете создать растровое изображение маски, нарисовав контуры на холсте:
// 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 }
Убедитесь, что размер маски совпадает с размером исходного изображения. Дополнительные сведения см. в каталоге примеров Imagen AI.
Вставка объектов
Вы можете вставить новый объект или контент в существующее изображение, что также называется заполнением пропущенных областей . Модель сгенерирует и вставит новый контент в указанную замаскированную область.
Для этого используйте функцию editImage() . Вам потребуется указать исходное изображение и маску. и текстовое поле с описанием содержимого, которое вы хотите вставить. Кроме того, передайте объект ImagenEditingConfig , убедившись, что его свойство editMode установлено в значение 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 }
Удалить объекты
Функция заполнения пробелов (inpainting) позволяет удалять ненужные объекты с изображения. Для этого используйте функцию editImage . Вам потребуется указать исходное изображение и маску. Это подсветит объект, который вы хотите удалить. При желании вы можете добавить текстовое описание объекта, что поможет модели точно его идентифицировать. Кроме того, необходимо установить editMode в файле ImagenEditingConfig в значение 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 }
Развернуть содержимое изображения
Расширение изображения за пределы его исходных границ, известное как вытягивание , можно выполнить с помощью функции outpaintImage() . Для работы этой функции требуется исходное изображение и необходимые Dimensions расширенного изображения. При желании можно добавить пояснительную подсказку для расширения и указать параметр ImagenImagePlacement исходного изображения внутри нового сгенерированного изображения:
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 }
Замените фон
Вы можете заменить фон изображения, сохранив при этом объект переднего плана. Для этого используйте функцию editImage . Передайте исходное изображение, объект ImagenBackgroundMask (содержащий текстовое поле для нового фона) и объект ImagenEditingConfig со свойством editMode , установленным в значение 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 }
Настройка
Вы можете использовать возможности настройки Imagen для создания или редактирования изображений на основе эталонных изображений, которые определяют объект, элемент управления или стиль. Это достигается путем предоставления текстовой подсказки вместе с одним или несколькими эталонными изображениями, которые служат ориентиром для модели.
Настройте параметры по теме.
Вы можете создавать новые изображения определенного объекта на основе эталонного изображения (например, товара, человека или животного). Просто укажите текстовую подсказку и как минимум одно эталонное изображение объекта. Например, вы можете загрузить фотографию своего питомца и создать новое изображение в совершенно другой обстановке.
Для этого определите ссылку на объект с помощью ImagenSubjectReference , а затем передайте её в editImage вместе с вашим запросом. Кроме того, добавьте ImagenEditingConfig , указывающий количество editSteps ); большее значение editSteps обычно приводит к лучшим результатам:
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 }
Настройка на основе элемента управления
Этот метод генерирует новое изображение на основе контрольного эталонного изображения , такого как набросок, выполненный от руки («каракули»), изображение границ, полученное с помощью алгоритма Кэнни , или сетка лица. Модель использует контрольное изображение в качестве структурного ориентира для компоновки и композиции нового изображения, а текстовая подсказка предоставляет такие детали, как цвет и текстура.
Определите управляющую ссылку с помощью ImagenControlReference и передайте её в editImage вместе с запросом и ImagenEditingConfig с указанием количества editSteps (большее значение может улучшить качество):
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 }
Настройте в соответствии со стилем.
Вы можете создать или отредактировать изображение, чтобы оно соответствовало определенному стилю , используя в качестве образца изображение, например, его узор, текстуру или дизайн. Модель использует эталонное изображение, чтобы понять требуемую эстетику, и применяет ее к новому изображению, описанному в текстовом запросе. Например, вы можете создать изображение кошки в стиле известной картины, предоставив изображение этой картины.
Задайте эталонный стиль с помощью ImagenStyleReference и передайте его в editImage вместе с запросом и ImagenEditingConfig с указанием количества editSteps (большее значение может улучшить качество):
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 }
Следующие шаги
- Подробнее о Firebase AI Logic можно узнать в документации Firebase .
- Изучите каталог примеров Android AI .