Imagen to model generowania obrazów. Może służyć do generowania niestandardowych awatarów do profili użytkowników lub do integrowania spersonalizowanych komponentów wizualnych z istniejącymi przepływami ekranów, aby zwiększyć zaangażowanie użytkowników.
Dostęp do modeli Imagen możesz uzyskać z aplikacji na Androida za pomocą pakietu SDK Firebase AI Logic. Modele Imagen są dostępne za pomocą obu dostawców interfejsu Firebase AI Logic API: Gemini Developer API (zalecany dla większości deweloperów) i Vertex AI.
Eksperymentowanie z promptami
Stworzenie idealnych promptów często wymaga wielu prób. Możesz eksperymentować z promptami graficznymi w Google AI Studio, czyli IDE do projektowania i tworzenia prototypów promptów. Wskazówki dotyczące ulepszania promptów znajdziesz w przewodniku po promptach i atrybutach obrazów.
Konfigurowanie projektu w Firebase i łączenie aplikacji
Aby dodać Firebase do projektu aplikacji na Androida, wykonaj czynności opisane w dokumentacji Firebase .
Dodawanie zależności Gradle
Dodaj te zależności do pliku build.gradle:
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")
}
Wygeneruj obraz
Aby wygenerować obraz w aplikacji na Androida, zacznij od utworzenia instancji ImagenModel z opcjonalną konfiguracją.
Za pomocą parametru generationConfig możesz zdefiniować prompt negatywny,
liczbę obrazów, format obrazu wyjściowego i format obrazu oraz dodać
znak wodny. Za pomocą parametru safetySettings możesz skonfigurować filtry bezpieczeństwa i filtry osób.
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)) );
Po utworzeniu instancji ImagenModel możesz generować obrazy, wywołując 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(); }
Edytowanie obrazów za pomocą Imagen
Pakiety SDK Firebase AI Logic oferują zaawansowane możliwości edycji obrazów za pomocą modelu Imagen, co pozwala na:
- Edytowanie obrazów na podstawie masek , w tym wykonywanie takich działań jak wstawianie lub usuwanie obiektów, rozszerzanie treści obrazu poza jego pierwotne granice oraz zmienianie tła.
- **Dostosowywanie obrazów** przez stosowanie określonych stylów (wzorów, tekstur lub stylów artystycznych), skupianie się na różnych tematach (takich jak produkty, ludzie lub zwierzęta) lub stosowanie się do różnych elementów sterujących (takich jak odręczny szkic, obraz z krawędziami Canny lub siatka twarzy).
Inicjowanie modelu
Aby korzystać z funkcji edycji Imagen, określ model Imagen, który obsługuje edycję obrazów
, np. imagen-3.0-capability-001:
val imagenModel = Firebase.ai(backend = GenerativeBackend.vertexAI()) .imagenModel("imagen-3.0-capability-001")
Edytowanie na podstawie maski
Edytowanie na podstawie maski w Imagen umożliwia modyfikowanie obrazów przez zdefiniowanie określonych obszarów, które mają być modyfikowane przez model. Ta funkcja umożliwia wykonywanie różnych działań, w tym tworzenie i stosowanie masek, wstawianie lub usuwanie obiektów oraz rozszerzanie treści obrazu poza jego pierwotne granice.
Tworzenie maski
Aby przeprowadzić edycję na podstawie maski, np. wstawić lub usunąć obiekty, musisz zdefiniować obszar, który ma być edytowany przez model, czyli maskę.
Aby utworzyć maskę, możesz poprosić model o automatyczne wygenerowanie jej za pomocą
ImagenBackgroundMask() lub ImagenSemanticMask(), przekazując identyfikator
klasy.
Możesz też ręcznie narysować maskę na ekranie, generując bitmapę maski i przekształcając ją w ImagenRawMask. Za pomocą detectDragGestures i Canvas możesz zaimplementować w aplikacji interfejs użytkownika do rysowania maski za pomocą Jetpack Compose w ten sposób:
//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") } } }
Następnie możesz utworzyć bitmapę maski, rysując ścieżki na płótnie:
// 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 }
Upewnij się, że maska ma taki sam rozmiar jak obraz źródłowy. Więcej informacji znajdziesz w przykładach z katalogu Imagen AI Catalog Samples.
Wstawianie obiektów
Możesz wstawić nowy obiekt lub treść do istniejącego obrazu, co nazywa się też uzupełnianiem. Model wygeneruje i wstawi nową treść w określonym zamaskowanym obszarze.
Aby to zrobić, użyj funkcji editImage(). Musisz podać
oryginalny obraz, maskęi prompt tekstowy
opisujący treść, którą chcesz wstawić. Dodatkowo przekaż obiekt ImagenEditingConfig, upewniając się, że jego właściwość editMode jest ustawiona na 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 }
Usuwanie obiektów
Uzupełnianie umożliwia usuwanie niechcianych obiektów z obrazu. Aby to zrobić, użyj funkcji editImage. Musisz podać oryginalny obraz i a
maskę, która wyróżnia obiekt, który chcesz
usunąć. Opcjonalnie możesz dodać prompt tekstowy opisujący obiekt, co może pomóc modelowi w dokładnej identyfikacji. Dodatkowo musisz ustawić editMode w ImagenEditingConfig na 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 }
Rozszerzanie treści obrazu
Możesz rozszerzyć obraz poza jego pierwotne granice, co nazywa się rozszerzaniem obrazu,
za pomocą funkcji outpaintImage(). Ta funkcja wymaga oryginalnego
obrazu i niezbędnych Dimensions rozszerzonego obrazu.
Opcjonalnie możesz dodać opisowy prompt rozszerzenia i określić
the ImagenImagePlacement of the original image within the
new generated image:
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 }
Zmienianie tła
Możesz zmienić tło obrazu, zachowując obiekt na pierwszym planie. Aby to zrobić, użyj funkcji editImage. Przekaż oryginalny obraz, obiekt ImagenBackgroundMask (zawierający prompt tekstowy nowego tła) i ImagenEditingConfig z właściwością editMode ustawioną na 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 }
Dostosowywanie
Za pomocą funkcji dostosowywania w Imagen możesz generować lub edytować obrazy na podstawie obrazów referencyjnych, które określają temat, element sterujący lub styl. Aby to zrobić, podaj prompt tekstowy wraz z co najmniej 1 obrazem referencyjnym, aby ukierunkować działanie modelu.
Dostosowywanie na podstawie tematu
Możesz generować nowe obrazy określonego tematu na podstawie obrazu referencyjnego (np. produktu, osoby lub zwierzęcia). Wystarczy, że podasz prompt tekstowy i co najmniej 1 obraz referencyjny tematu. Możesz na przykład przesłać zdjęcie swojego zwierzaka i wygenerować jego nowy obraz w zupełnie innym otoczeniu.
Aby to zrobić, zdefiniuj odniesienie do tematu za pomocą ImagenSubjectReference, a następnie przekaż je do editImage wraz z promptem. Dodatkowo dodaj ImagenEditingConfig, który określa liczbę editSteps; wyższa wartość editSteps zwykle prowadzi do lepszych wyników:
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 }
Dostosowywanie na podstawie elementu sterującego
Ta technika generuje nowy obraz na podstawie obrazu referencyjnego elementu sterującego, takiego jak odręczny szkic („bazgroł”), obraz z krawędziami Canny, lub siatka twarzy. Model używa obrazu elementu sterującego jako strukturalnego przewodnika po układzie i kompozycji nowego obrazu, a prompt tekstowy zawiera szczegóły takie jak kolor i tekstura.
Zdefiniuj odniesienie do elementu sterującego za pomocą ImagenControlReference i przekaż je do editImage wraz z promptem i ImagenEditingConfig z liczbą editSteps (wyższa wartość może poprawić jakość):
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 }
Dostosowywanie na podstawie stylu
Możesz wygenerować lub edytować obraz, aby pasował do określonego stylu z obrazu referencyjnego, np. do jego wzoru, tekstury lub projektu. Model używa obrazu referencyjnego, aby zrozumieć wymagane estetykę i zastosować ją do nowego obrazu opisanego w prompcie tekstowym. Możesz na przykład wygenerować obraz kota w stylu słynnego obrazu, podając obraz tego obrazu.
Zdefiniuj odniesienie do stylu za pomocą ImagenStyleReference i przekaż je do editImage wraz z promptem i ImagenEditingConfig z liczbą editSteps (wyższa wartość może poprawić jakość):
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 }
Dalsze kroki
- Więcej informacji o Firebase AI Logic znajdziesz w dokumentacji Firebase.
- Zapoznaj się z katalogiem przykładów AI na Androida.