Imagen to model generowania obrazów. Może służyć do generowania niestandardowych awatarów w profilach użytkowników lub do integrowania spersonalizowanych komponentów wizualnych z istniejącymi ścieżkami ekranów, aby zwiększać 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ą dostawców interfejsów API Firebase AI Logic: Gemini Developer API (zalecany dla większości deweloperów) i Vertex AI.
Eksperymentuj z promptami
Stworzenie idealnych promptów często wymaga wielu prób. Możesz eksperymentować z promptami dotyczącymi obrazów w Google AI Studio, środowisku 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 Firebase i łączenie z nim aplikacji
Wykonaj czynności opisane w dokumentacji Firebase, aby dodać Firebase do projektu na Androida.
Dodawanie zależności Gradle
Dodaj do pliku build.gradle
te zależności:
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")
}
Generowanie obrazu
Aby wygenerować obraz w aplikacji na Androida, zacznij od utworzenia instancji klasy ImagenModel
z opcjonalną konfiguracją.
Za pomocą parametru generationConfig
możesz zdefiniować negatywny prompt, liczbę obrazów, format obrazu wyjściowego, format obrazu i 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.ai(backend = GenerativeBackend.googleAI()).imagenModel(
"imagen-4.0-generate-001",
config,
ImagenSafetySettings.builder()
.setSafetyFilterLevel(ImagenSafetyFilterLevel.BLOCK_LOW_AND_ABOVE)
.setPersonFilterLevel(ImagenPersonFilterLevel.BLOCK_ALL)
.build())
);
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
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();
}
Edytowanie obrazów za pomocą Imagen
Pakiety SDK Firebase AI Logic oferują zaawansowane funkcje edycji obrazów za pomocą modelu Imagen, które umożliwiają:
- Edytowanie obrazów na podstawie masek, co obejmuje takie działania jak wstawianie lub usuwanie obiektów, rozszerzanie treści obrazu poza jego pierwotne granice i zmiana tła.
- Dostosowywanie obrazów przez stosowanie określonych stylów (wzorów, tekstur lub stylów artystycznych), skupianie się na różnych tematach (np. produktach, osobach lub zwierzętach) lub stosowanie różnych elementów sterujących (np. odręcznego szkicu, obrazu z wykrytymi krawędziami lub siatki twarzy).
Inicjowanie modelu
Aby korzystać z funkcji edycji Imagen, określ model Imagen, który obsługuje edycję obrazów, np. imgen-3.0-capability-001
. wersja modelu:
val imagenModel = Firebase.ai(backend = GenerativeBackend.vertexAI())
.imagenModel("imagen-3.0-capability-001")
Edytowanie na podstawie maski
Edycja oparta na maskach w Imagen umożliwia modyfikowanie obrazów przez określanie konkretnych obszarów, które model ma przekształcić. Ta funkcja umożliwia wykonywanie różnych działań, w tym tworzenie i stosowanie masek, wstawianie i usuwanie obiektów oraz powiększanie obrazu poza jego oryginalne granice.
Tworzenie maski
Aby przeprowadzić edycję na podstawie maski, np. wstawić lub usunąć obiekty, musisz określić obszar, który ma być edytowany przez model, czyli maskę.
Aby utworzyć maskę, możesz wygenerować ją automatycznie za pomocą modelu, używając ImagenBackgroundMask()
lub ImagenSemanticMask()
i przekazując identyfikator klasy.
Możesz też ręcznie narysować maskę na ekranie, generując bitmapę maski i konwertując ją na ImagenRawMask
. Za pomocą detectDragGestures
i Canvas
możesz w aplikacji zaimplementować interfejs użytkownika do rysowania masek 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 = createMask(sourceBitmap, paths)
onMaskFinalized(maskBitmap)
},
) {
Text("Save mask")
}
}
}
Następnie możesz utworzyć bitmapę maski, rysując ścieżki na obszarze roboczym:
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
}
Upewnij się, że maska ma taki sam rozmiar jak obraz źródłowy. Więcej informacji znajdziesz w przykładowych katalogach Imagen AI.
Wstawianie obiektów
Możesz wstawić nowy obiekt lub treść do istniejącego obrazu. Ta funkcja jest też nazywana uzupełnianiem. Model wygeneruje i wstawi nowe treści w określonym zamaskowanym obszarze.
Aby to zrobić, użyj funkcji editImage()
. Musisz przesłać oryginalny obraz, maskę i prompt tekstowy z opisem treści, które chcesz wstawić. Dodatkowo przekaż obiekt ImagenEditingConfig
, upewniając się, że jego właściwość editMode
ma wartość 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
}
Usuwanie obiektów
Retusz pozwala usuwać niechciane obiekty z obrazu. Aby to zrobić, użyj funkcji editImage
. Musisz przesłać oryginalny obraz i maskę, która wyróżnia obiekt, który chcesz usunąć. Opcjonalnie możesz dołączyć prompt tekstowy z opisem obiektu, który 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(
sources = listOf(
ImagenRawImage(originalImage),
mask
),
prompt = prompt,
// Define the editing configuration for inpainting and removal.
config = ImagenEditingConfig(ImagenEditMode.INPAINT_REMOVAL)
)
return editedImage
}
Rozwijanie 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ędnego Dimensions
powiększonego obrazu.
Opcjonalnie możesz dodać opisowy prompt rozszerzenia i określić ImagenImagePlacement
oryginalnego obrazu w nowym wygenerowanym obrazie:
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
}
Zastępowanie tła
Możesz zastąpić 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 dla nowego tła) i obiekt 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(
sources = listOf(
ImagenRawImage(originalImage),
ImagenBackgroundMask(),
),
prompt = prompt,
config = ImagenEditingConfig(ImagenEditMode.INPAINT_INSERTION)
)
return editedImage
}
Dostosowywanie
Możesz użyć funkcji dostosowywania w Imagen, aby generować lub edytować obrazy na podstawie obrazów referencyjnych, które określają temat, kontrolę lub styl. Można to osiągnąć, podając prompt tekstowy wraz z co najmniej 1 obrazem referencyjnym, aby naprowadzić model.
Dostosowywanie na podstawie tematu
Możesz generować nowe obrazy konkretnego obiektu 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ć nowy obraz przedstawiający go 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 uwzględnij parametr ImagenEditingConfig
, który określa liczbę editSteps
. Wyższa wartość editSteps
zwykle prowadzi do uzyskania 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,
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
}
Dostosowywanie na podstawie elementu sterującego
Ta technika generuje nowy obraz na podstawie kontrolnego obrazu referencyjnego, takiego jak odręczny szkic („bazgroły”), obraz z wykrytymi krawędziami lub siatka twarzy. Model wykorzystuje obraz kontrolny jako wskazówkę strukturalną dotyczącą układu i kompozycji nowego obrazu, a prompt tekstowy zawiera szczegóły, takie jak kolor i tekstura.
Zdefiniuj odniesienie kontrolne 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, 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
}
Dostosowywanie na podstawie stylu
Możesz wygenerować lub edytować obraz, aby dopasować go do określonego stylu obrazu referencyjnego, np. jego wzoru, tekstury lub projektu. Model wykorzystuje obraz referencyjny, aby zrozumieć wymagane cechy estetyczne, i stosuje je do nowego obrazu opisanego w prompcie tekstowym. Możesz na przykład wygenerować obraz kota w stylu słynnego obrazu, przesyłając obraz tego obrazu.
Zdefiniuj odniesienie do stylu za pomocą parametru ImagenStyleReference
i przekaż je do parametru editImage
wraz z promptem i parametrem 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,
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
}
Dalsze kroki
- Więcej informacji o Firebase AI Logic znajdziesz w dokumentacji Firebase.
- Zapoznaj się z katalogiem przykładowych aplikacji AI na Androida.