Imagen은 이미지 생성 모델입니다. 사용자 프로필의 맞춤 아바타를 생성하거나 맞춤설정된 시각적 애셋을 기존 화면 흐름에 통합하여 사용자 참여도를 높이는 데 사용할 수 있습니다.
Firebase AI Logic SDK를 사용하여 Android 앱에서 Imagen 모델에 액세스할 수 있습니다. Imagen 모델은 Firebase AI Logic API 제공업체인 Gemini Developer API (대부분의 개발자에게 권장)와 Vertex AI를 모두 사용하여 사용할 수 있습니다.
프롬프트 실험
이상적인 프롬프트를 만들려면 여러 번 시도해야 하는 경우가 많습니다. 프롬프트 설계 및 프로토타입 제작을 위한 IDE인 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.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")
}
이미지 생성
Android 앱에서 이미지를 생성하려면 선택적 구성으로 ImagenModel
를 인스턴스화하는 것으로 시작합니다.
generationConfig
매개변수를 사용하여 부정적 프롬프트, 이미지 수, 출력 이미지 가로세로 비율, 이미지 형식을 정의하고 워터마크를 추가할 수 있습니다. safetySettings
매개변수를 사용하여 안전 및 인물 필터를 구성할 수 있습니다.
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
)
)
자바
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())
);
ImagenModel
가 인스턴스화되면 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()
자바
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();
}
Imagen으로 이미지 수정하기
Firebase AI Logic SDK는 Imagen 모델을 통해 고급 이미지 편집 기능을 제공하므로 다음 작업을 할 수 있습니다.
- 마스크를 기반으로 이미지 수정: 객체 삽입 또는 삭제, 이미지 콘텐츠를 원래 경계 너머로 확장, 배경 변경 등의 작업이 포함됩니다.
- 이미지 맞춤설정: 특정 스타일(패턴, 텍스처, 아티스트 스타일)을 적용하거나, 다양한 피사체 (예: 제품, 사람, 동물)에 초점을 맞추거나, 다양한 컨트롤 (예: 손으로 그린 스케치, 캐니 윤곽선 이미지, 얼굴 메쉬)을 준수합니다.
모델 초기화
Imagen 수정 기능을 사용하려면 이미지 수정을 지원하는 Imagen 모델(예: imgen-3.0-capability-001
)을 지정하세요. 모델 버전:
val imagenModel = Firebase.ai(backend = GenerativeBackend.vertexAI())
.imagenModel("imagen-3.0-capability-001")
마스크 기반 수정
Imagen의 마스크 기반 수정을 사용하면 모델이 조작할 특정 영역을 정의하여 이미지를 수정할 수 있습니다. 이 기능을 사용하면 마스크를 만들고 적용하고, 객체를 삽입하거나 삭제하고, 원래 경계를 넘어 이미지 콘텐츠를 확장하는 등 다양한 작업을 할 수 있습니다.
마스크 만들기
객체 삽입 또는 삭제와 같은 마스크 기반 수정을 수행하려면 모델에서 수정해야 하는 영역인 마스크를 정의해야 합니다.
마스크를 만들려면 ImagenBackgroundMask()
또는 ImagenSemanticMask()
를 사용하여 모델이 클래스 ID를 전달하여 마스크를 자동 생성하도록 할 수 있습니다.
마스크 비트맵을 생성하고 이를 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 = createMask(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 = 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
}
마스크가 소스 이미지와 동일한 크기인지 확인합니다. 자세한 내용은 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(
sources = listOf(
ImagenRawImage(originalImage),
mask),
prompt = prompt,
// Define the editing configuration for inpainting and insertion.
config = ImagenEditingConfig(ImagenEditMode.INPAINT_INSERTION)
)
return editedImage
}
객체 삭제
인페인팅을 사용하면 이미지에서 원치 않는 객체를 삭제할 수 있습니다. 이렇게 하려면 editImage
함수를 사용합니다. 원본 이미지와 삭제하려는 객체를 강조 표시하는 마스크를 제공해야 합니다. 원하는 경우 텍스트 프롬프트를 포함하여 객체를 설명할 수 있으며, 이는 모델이 정확하게 식별하는 데 도움이 됩니다. 또한 ImagenEditingConfig
내에서 editMode
를 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
}
이미지 콘텐츠 펼치기
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 = model.outpaintImage(
ImagenRawImage(originalImage),
Dimension(width, height),
prompt = prompt,
newPosition = ImagenImagePlacement.LEFT_CENTER
)
return editedImage
}
배경 바꾸기
전경 피사체를 유지하면서 이미지의 배경을 바꿀 수 있습니다. 이렇게 하려면 editImage
함수를 사용합니다. 원래 이미지, ImagenBackgroundMask
객체 (새 배경의 텍스트 프롬프트 포함), editMode
속성이 ImagenEditMode.INPAINT_INSERTION
로 설정된 ImagenEditingConfig
을 전달합니다.
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
}
맞춤설정
Imagen의 맞춤설정 기능을 사용하여 주제, 제어, 스타일을 지정하는 참조 이미지를 기반으로 이미지를 생성하거나 수정할 수 있습니다. 이를 위해 모델을 안내하는 하나 이상의 참조 이미지와 함께 텍스트 프롬프트를 제공합니다.
주제에 따라 맞춤설정
참조 이미지 (예: 제품, 사람, 동물)에서 특정 주제의 새 이미지를 생성할 수 있습니다. 텍스트 프롬프트와 주제의 참고 이미지를 하나 이상 제공하기만 하면 됩니다. 예를 들어 반려동물의 사진을 업로드하고 완전히 다른 환경에서 새 이미지를 생성할 수 있습니다.
이렇게 하려면 ImagenSubjectReference
를 사용하여 주제 참조를 정의한 다음 프롬프트와 함께 editImage
에 전달합니다. 또한 editSteps
수를 지정하는 ImagenEditingConfig
를 포함합니다. 일반적으로 editSteps
값이 높을수록 품질이 더 나은 결과를 얻을 수 있습니다.
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
}
컨트롤을 기반으로 맞춤설정
이 기법은 손으로 그린 스케치 ('낙서'), Canny 윤곽선 이미지, 얼굴 메시와 같은 대조 참고 이미지를 기반으로 새 이미지를 생성합니다. 모델은 제어 이미지를 새 이미지의 레이아웃과 구성을 위한 구조적 가이드로 사용하고, 텍스트 프롬프트는 색상과 질감과 같은 세부정보를 제공합니다.
ImagenControlReference
로 제어 참조를 정의하고 프롬프트 및 ImagenEditingConfig
와 함께 editImage
에 제공합니다 (값이 높을수록 품질이 향상될 수 있음).editSteps
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
}
스타일을 기반으로 맞춤설정
참조 이미지의 패턴, 질감, 디자인과 같은 특정 스타일에 맞게 이미지를 생성하거나 수정할 수 있습니다. 모델은 참조 이미지를 사용하여 필요한 미적 요소를 파악하고 텍스트 프롬프트에 설명된 새 이미지에 적용합니다. 예를 들어 유명한 그림의 이미지를 제공하여 해당 그림 스타일로 고양이 이미지를 생성할 수 있습니다.
ImagenStyleReference
로 스타일 참조를 정의하고 프롬프트 및 editSteps
개수가 포함된 ImagenEditingConfig
와 함께 editImage
에 제공합니다 (값이 높을수록 품질이 향상될 수 있음).
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
}
다음 단계
- Firebase 문서에서 Firebase AI Logic에 대해 자세히 알아보세요.
- Android AI 샘플 카탈로그를 살펴봅니다.