Imagen, इमेज जनरेट करने वाला एक मॉडल है. इसका इस्तेमाल, उपयोगकर्ता प्रोफ़ाइल के लिए पसंद के मुताबिक अवतार जनरेट करने या मौजूदा स्क्रीन फ़्लो में, पसंद के मुताबिक विज़ुअल ऐसेट इंटिग्रेट करने के लिए किया जा सकता है. इससे, उपयोगकर्ता की दिलचस्पी बढ़ाई जा सकती है.
Firebase AI Logic SDK का इस्तेमाल करके, अपने Android ऐप्लिकेशन से Imagen मॉडल ऐक्सेस किए जा सकते हैं. Imagen मॉडल, Firebase AI Logic API के इन दोनों प्रोवाइडर की मदद से उपलब्ध हैं: Gemini Developer API (ज़्यादातर डेवलपर के लिए सुझाव दिया जाता है) और Vertex AI.
प्रॉम्प्ट के साथ एक्सपेरिमेंट करना
सही प्रॉम्प्ट बनाने में अक्सर कई बार कोशिश करनी पड़ती है. प्रॉम्प्ट डिज़ाइन और प्रोटोटाइपिंग के लिए, Google AI Studio एक आईडीई है. इसमें इमेज प्रॉम्प्ट के साथ एक्सपेरिमेंट किया जा सकता है . अपने प्रॉम्प्ट को बेहतर बनाने के सुझाव पाने के लिए, प्रॉम्प्ट और इमेज एट्रिब्यूट की गाइड देखें.
Firebase प्रोजेक्ट सेट अप करना और अपने ऐप्लिकेशन को कनेक्ट करना
अपने Android प्रोजेक्ट में Firebase जोड़ने के लिए, Firebase के दस्तावेज़ में दिया गया तरीका अपनाएं.
Gradle डिपेंडेंसी जोड़ना
अपनी build.gradle फ़ाइल में ये डिपेंडेंसी जोड़ें:
dependencies {
// Import the BoM for the Firebase platform
implementation(platform("com.google.firebase:firebase-bom:34.12.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 ), )
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 को कॉल करके इमेज जनरेट की जा सकती हैं:
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(); }
Imagen की मदद से इमेज में बदलाव करना
Firebase AI Logic SDK, 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 Catalog के सैंपल देखें.
ऑब्जेक्ट शामिल करना
किसी मौजूदा इमेज में नया ऑब्जेक्ट या कॉन्टेंट शामिल किया जा सकता है. इसे इनपेंटिंग भी कहा जाता है. मॉडल, तय किए गए मास्क वाले हिस्से में नया कॉन्टेंट जनरेट करेगा और उसे शामिल करेगा.
ऐसा करने के लिए, 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 }
ऑब्जेक्ट हटाना
इनपेंटिंग की मदद से, किसी इमेज से अनचाहे ऑब्जेक्ट हटाए जा सकते हैं. ऐसा करने के लिए, 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( 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 की मदद से, कंट्रोल रेफ़रंस तय करें. इसके बाद, इसे प्रॉम्प्ट और ImagenEditingConfig के साथ editImage में उपलब्ध कराएं. इसमें 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 की मदद से, स्टाइल रेफ़रंस तय करें. इसके बाद, इसे प्रॉम्प्ट और ImagenEditingConfig के साथ editImage में उपलब्ध कराएं. इसमें 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 के Firebase दस्तावेज़ में, Firebase AI Logic के बारे में ज़्यादा जानें.
- Android AI के सैंपल का कैटलॉग एक्सप्लोर करें.