تولید تصاویر با Imagen، تولید تصاویر با Imagen، تولید تصاویر با Imagen

Imagen یک مدل تولید تصویر است. می‌توان از آن برای تولید آواتارهای سفارشی برای نمایه‌های کاربر یا ادغام دارایی‌های بصری شخصی‌شده در جریان‌های صفحه موجود برای افزایش تعامل کاربر استفاده کرد.

می‌توانید با استفاده از Firebase AI Logic SDK به مدل‌های Imagen از برنامه Android خود دسترسی پیدا کنید. مدل‌های Imagen با استفاده از هر دو ارائه‌دهنده API AI Logic Firebase در دسترس هستند: Gemini Developer API (توصیه‌شده برای اکثر توسعه‌دهندگان) و Vertex AI.

نموداری که معماری یکپارچه سازی منطق هوش مصنوعی Firebase را نشان می دهد        برای دسترسی به Gemini Developer API. یک برنامه اندروید از Firebase استفاده می کند        Android SDK برای اتصال به Firebase. سپس Firebase با آن تعامل دارد        Gemini Developer API، که به Gemini Pro & Flash در داخل دسترسی دارد        ابر
شکل 1. با استفاده از Firebase AI Logic به مدل های Imagen دسترسی پیدا کنید.

با دستورات آزمایش کنید

ایجاد درخواست های ایده آل اغلب به تلاش های متعدد نیاز دارد. می‌توانید درخواست‌های تصویر را در Google AI Studio آزمایش کنید، یک IDE برای طراحی سریع و نمونه‌سازی. برای راهنمایی در مورد چگونگی بهبود درخواست‌های خود، راهنمای ویژگی فرمان و تصویر را مرور کنید.

تصویری از رابط هوش مصنوعی گوگل استودیو،       نمایش چهار تصویر تولید شده از یک تی رکس با یک کوله پشتی آبی در یک       جنگل ماقبل تاریخ
شکل 2. استودیوی هوش مصنوعی گوگل می تواند به شما کمک کند تا درخواست های تولید تصویر خود را اصلاح کنید.

یک پروژه 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 برای پیکربندی فیلترهای ایمنی و شخص استفاده کنید.

کاتلین

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 تصاویر ایجاد کنید:

کاتلین

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 را مشخص کنید که از ویرایش تصویر پشتیبانی می‌کند، مانند imgen-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 = 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 مراجعه کنید.

اشیاء را درج کنید

می‌توانید یک شی یا محتوای جدید را در یک تصویر موجود وارد کنید، که به آن inpainting نیز می‌گویند. مدل محتوای جدید را در ناحیه پوشانده شده مشخص شده تولید و وارد می کند.

برای رسیدن به این هدف، از تابع 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
}

اشیاء را حذف کنید

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(
        sources = listOf(
            ImagenRawImage(originalImage),
            mask
        ),
        prompt = prompt,
        // Define the editing configuration for inpainting and removal.
        config = ImagenEditingConfig(ImagenEditMode.INPAINT_REMOVAL)
    )

    return editedImage
}

محتوای تصویر را گسترش دهید

با استفاده از تابع outpaintImage() می توانید یک تصویر را فراتر از مرزهای اصلی آن که به عنوان outpainting شناخته می شود گسترش دهید. این تابع به تصویر اصلی و 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 (حاوی یک درخواست متنی برای پس‌زمینه جدید) و یک 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(
        sources = listOf(
            ImagenRawImage(originalImage),
            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,
        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 تعریف کنید و آن را به editImage به همراه یک اعلان و ImagenEditingConfig با تعداد 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 تعریف کنید و آن را به 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,
        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 
}

مراحل بعدی