מדריך ליצירת תמונות ל-Android

המשימה 'יצירת תמונות של MediaPipe' מאפשרת ליצור תמונות על סמך הנחיית טקסט. במשימה הזו נעשה שימוש במודל של טקסט לתמונה כדי ליצור תמונות באמצעות טכניקות דיפוזיה.

המשימה מקבלת פרומפט טקסט כקלט, יחד עם תמונת תנאי אופציונלית שהמודל יכול להרחיב ולהשתמש בה כחומר עזר ליצירה. מחולל התמונות יכול גם ליצור תמונות על סמך קונספטים ספציפיים שסופקו למודל במהלך האימון או האימון מחדש. למידע נוסף, ראו התאמה אישית באמצעות LoRA.

דוגמת הקוד שמתוארת בהוראות האלו זמינה ב-GitHub. למידע נוסף על היכולות, המודלים ואפשרויות ההגדרה של המשימה הזו, קראו את הסקירה הכללית.

קוד לדוגמה

הקוד לדוגמה של משימות MediaPipe הוא יישום בסיסי של אפליקציה ליצירת תמונות ל-Android. תוכלו להשתמש באפליקציה כנקודת התחלה לאפליקציה שלכם ל-Android, או להתייחס אליה כשאתם משנים אפליקציה קיימת. הקוד לדוגמה של מחולל התמונות מתארח ב-GitHub.

הורדת הקוד

בהוראות הבאות מוסבר איך ליצור עותק מקומי של הקוד לדוגמה באמצעות כלי שורת הפקודה git.

כדי להוריד את הקוד לדוגמה:

  1. משכפלים את מאגר ה-Git באמצעות הפקודה הבאה:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. לחלופין, אפשר להגדיר את מכונת ה-Git לשימוש בקופה עם נפח נתונים נמוך (sparse), כדי שיהיו לכם רק את הקבצים של האפליקציה לדוגמה של 'מחולל התמונות':
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_generator/android
    

אחרי שיוצרים גרסה מקומית של הקוד לדוגמה, אפשר לייבא את הפרויקט אל Android Studio ולהפעיל את האפליקציה. לקבלת הוראות, אפשר לעיין במדריך ההגדרה ל-Android.

רכיבים עיקריים

הקבצים הבאים מכילים את הקוד החיוני לאפליקציה לדוגמה הזו ליצירת תמונות:

  • ImageGenerationHelper.kt: מפעיל את המשימה ומטפל ביצירת התמונה.
  • DiffusionActivity.kt: יצירת תמונות כשיישומי פלאגין או משקולות LoRA לא מופעלים.
  • PluginActivity.kt: הטמעה של מודלים של יישומי פלאגין, שמאפשרת למשתמשים לספק תמונת תנאי כקלט.
  • LoRAWeightActivity.kt: גישה למשקולות של LoRA, המשמשות להתאמה אישית של מודלים בסיסיים ויצירת תמונות של קונספטים ספציפיים, ומטפלות בהן.

הגדרה

בקטע הזה מתוארים שלבים עיקריים להגדרה של סביבת הפיתוח ופרויקטים של קוד במיוחד לשימוש בכלי ליצירת תמונות. במדריך ההגדרה ל-Android תוכלו לקרוא מידע כללי על הגדרת סביבת הפיתוח לשימוש במשימות של MediaPipe, כולל הדרישות לגבי גרסת הפלטפורמה.

יחסי תלות

המשימה 'מחולל תמונות' משתמשת בספרייה com.google.mediapipe:tasks-vision-image-generator. הוסיפו את התלות הבאה לקובץ build.gradle באפליקציה ל-Android:

dependencies {
    implementation 'com.google.mediapipe:tasks-vision-image-generator:latest.release'
}

במכשירים עם Android 12 (API 31) ואילך, צריך להוסיף את התלות של ספריית OpenCL המקורית ל-AndroidManifest.xml. למידע נוסף, עיינו במסמכי התיעוד בתג uses-native-library.

במכשירי Android מסוימים יכול להיות שיידרשו גם ספריות נוספות:

<uses-native-library android:name="libOpenCL.so" android:required="false" />
<uses-native-library android:name="libOpenCL-car.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-pixel.so" android:required="false" />

מודל

למשימה הזו של MediaPipe Image Generator נדרש מודל בסיס שעבר אימון, שתואם למשימה הזו. אחרי שמורידים מודל, צריך להתקין את יחסי התלות הנדרשים ולהמיר את המודל לפורמט מתאים. לאחר מכן שלחו את המודל שעבר המרה למכשיר ה-Android.

למידע נוסף על המודלים הזמינים ליצירת תמונות, קראו את הקטע על מודלים בסקירה הכללית על משימות.

הורדת מודל הבסיס

הכלי ליצירת תמונות מחייב שהמודל הבסיסי יהיה תואם לפורמט המודל runwayml/stable-diffusion-v1-5 EMA-only, על סמך המודל הבא: runwayml/stable-diffusion-v1-5.

התקנת יחסי תלות והמרת המודל

$ pip install torch typing_extensions numpy Pillow requests pytorch_lightning absl-py

מריצים את הסקריפט convert.py:

$ python3 convert.py --ckpt_path <ckpt_path> --output_path <output_path>

העברת מודל שהומר למכשיר

מעבירים את תוכן התיקייה <output_path> למכשיר ה-Android.

$ adb shell rm -r /data/local/tmp/image_generator/ # Remove any previously loaded weights
$ adb shell mkdir -p /data/local/tmp/image_generator/
$ adb push <output_path>/. /data/local/tmp/image_generator/bins

הורדת מודלים של יישומי פלאגין והוספת משקולות של LoRA (אופציונלי)

אם אתם מתכוונים להשתמש במודל של פלאגין, צריך לבדוק אם חייבים להוריד את המודל. לגבי יישומי פלאגין שדורשים מודל נוסף, המודלים של יישומי הפלאגין חייבים להיות חלק מ-APK או שאפשר להוריד לפי דרישה. דגמים של יישומי פלאגין הם קלים (כ-23MB) וניתן לצרף אותם ישירות ב-APK. עם זאת, מומלץ להוריד מודלים של יישומי פלאגין לפי דרישה.

אם התאמתם מודל ל-LoRA, תוכלו להוריד אותו לפי דרישה. למידע נוסף, ראו את מודל הפלאגין של משקלי LoRA.

יצירת המשימה

המשימה 'יצירת תמונות של MediaPipe' משתמשת בפונקציה createFromOptions() כדי להגדיר את המשימה. הפונקציה createFromOptions() מקבלת ערכים לאפשרויות התצורה. מידע נוסף על אפשרויות ההגדרה זמין במאמר אפשרויות תצורה.

אפשרויות הגדרה

המשימה כוללת את אפשרויות ההגדרה הבאות לאפליקציות ל-Android:

שם האפשרות תיאור טווח ערכים
imageGeneratorModelDirectory ספריית המודלים של מחולל התמונות שבה מאוחסנים משקולות המודל. PATH
loraWeightsFilePath מגדיר את הנתיב לקובץ המשקולות של LoRA. אופציונלי ורלוונטי רק אם המודל הותאם אישית באמצעות LoRA. PATH
errorListener מגדירה האזנה לשגיאות כאופציונלי. N/A

המשימה תומכת גם במודלים של יישומי פלאגין, שמאפשרים למשתמשים לכלול תמונות תנאים בקלט המשימה. מודל הבסיס יכול להרחיב אותן ולהשתמש בהן כחומר עזר ליצירה. תמונות התנאי יכולות להיות ציוני פנים, קווי מתאר והערכות עומק, והמודל משתמש בהם בתור הקשר ומידע נוסף ליצירת תמונות.

כשמוסיפים מודל פלאגין למודל הבסיס, צריך להגדיר גם את האפשרויות של יישומי הפלאגין. הפלאגין Face landmark משתמש ב-faceConditionOptions, הפלאגין Canny edge משתמש ב-edgeConditionOptions והפלאגין Depth משתמש ב-depthConditionOptions.

אפשרויות להצללה

מגדירים את האפשרויות הבאות ב-edgeConditionOptions.

שם האפשרות תיאור טווח ערכים ערך ברירת מחדל
threshold1 הסף הראשון להליך ההיסטרזה. Float 100
threshold2 הסף השני להליך ההיסטרזה. Float 200
apertureSize גודל הצמצם לאופרטור Sobel. הטווח האופייני נע בין 3 ל-7. Integer 3
l2Gradient האם נורמת L2 משמשת לחישוב הגודל של ההדרגתיות של התמונה, במקום נורמת ברירת המחדל L1. BOOLEAN False
EdgePluginModelBaseOptions האובייקט BaseOptions שמגדיר את הנתיב למודל של הפלאגין. אובייקט BaseOptions N/A

למידע נוסף על אופן הפעולה של אפשרויות ההגדרה האלה, תוכלו לקרוא את המאמר מזהה קצוות Canny.

אפשרויות של זיהוי פנים

מגדירים את האפשרויות הבאות ב-faceConditionOptions.

שם האפשרות תיאור טווח ערכים ערך ברירת מחדל
minFaceDetectionConfidence ציון הסמך המינימלי שצריך לעמוד בו כדי שזיהוי הפנים ייחשב כמוצלח. Float [0.0,1.0] 0.5
minFacePresenceConfidence ציון המהימנות המינימלי של ציון נוכחות הפנים בזיהוי של ציון הפנים. Float [0.0,1.0] 0.5
faceModelBaseOptions האובייקט BaseOptions שמגדיר את הנתיב של המודל שיוצר את תמונת התנאי. אובייקט BaseOptions N/A
FacePluginModelBaseOptions האובייקט BaseOptions שמגדיר את הנתיב למודל של הפלאגין. אובייקט BaseOptions N/A

למידע נוסף על אופן הפעולה של אפשרויות התצורה האלה, קראו את המשימה של Face Looker.

אפשרויות עומק

מגדירים את האפשרויות הבאות ב-depthConditionOptions.

שם האפשרות תיאור טווח ערכים ערך ברירת מחדל
depthModelBaseOptions האובייקט BaseOptions שמגדיר את הנתיב של המודל שיוצר את תמונת התנאי. אובייקט BaseOptions N/A
depthPluginModelBaseOptions האובייקט BaseOptions שמגדיר את הנתיב למודל של הפלאגין. אובייקט BaseOptions N/A

יצירה באמצעות מודל הבסיס בלבד

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

imageGenerator = ImageGenerator.createFromOptions(context, options)

יצירה באמצעות יישומי פלאגין

אם מחילים מודל פלאגין אופציונלי, צריך להגדיר את אפשרויות הבסיס למודל הפלאגין באמצעות setPluginModelBaseOptions. אם מודל הפלאגין דורש מודל נוסף שהורדתם כדי ליצור את תמונת התנאי, צריך לציין את הנתיב ב-BaseOptions.

סימון פנים

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

val faceModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("face_landmarker.task")
    .build()

val facePluginModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("face_landmark_plugin.tflite")
    .build()

val faceConditionOptions = FaceConditionOptions.builder()
    .setFaceModelBaseOptions(faceModelBaseOptions)
    .setPluginModelBaseOptions(facePluginModelBaseOptions)
    .setMinFaceDetectionConfidence(0.3f)
    .setMinFacePresenceConfidence(0.3f)
    .build()

val conditionOptions = ConditionOptions.builder()
    .setFaceConditionOptions(faceConditionOptions)
    .build()

imageGenerator =
    ImageGenerator.createFromOptions(context, options, conditionOptions)
    

Canny Edge

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

val edgePluginModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("canny_edge_plugin.tflite")
    .build()

val edgeConditionOptions = EdgeConditionOptions.builder()
    .setThreshold1(100.0f)
    .setThreshold2(100.0f)
    .setApertureSize(3)
    .setL2Gradient(false)
    .setPluginModelBaseOptions(edgePluginModelBaseOptions)
    .build()

val conditionOptions = ConditionOptions.builder()
    .setEdgeConditionOptions(edgeConditionOptions)
    .build()

imageGenerator =
    ImageGenerator.createFromOptions(context, options, conditionOptions)
    

עומק

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

val depthModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("depth_model.tflite")
    .build()

val depthPluginModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("depth_plugin.tflite")
    .build()

val depthConditionOptions =
    ConditionOptions.DepthConditionOptions.builder()
        .setDepthModelBaseOptions(depthModelBaseOptions)
        .setPluginModelBaseOptions(depthPluginModelBaseOptions)
        .build()

val conditionOptions = ConditionOptions.builder()
    .setDepthConditionOptions(depthConditionOptions)
    .build()

imageGenerator =
    ImageGenerator.createFromOptions(context, options, conditionOptions)
    

יצירה באמצעות משקולות של LoRA

אם כוללים משקולות של LoRA, צריך להשתמש בפרמטר loraWeightsFilePath כדי להצביע על מיקום הנתיב.

val options = ImageGeneratorOptions.builder()
    .setLoraWeightsFilePath(weightsPath)
    .setImageGeneratorModelDirectory(modelPath)
    .build()

imageGenerator = ImageGenerator.createFromOptions(context, options)

הכנת הנתונים

מחולל התמונות מקבל את מקורות הקלט הבאים:

  • הנחיה (חובה): הנחיית הטקסט שמתארת את התמונה שתיווצר.
  • iterations (חובה): סך כל האיטרציות ליצירת התמונה. נקודת התחלה טובה היא 20.
  • seed (חובה): המקור האקראי ששימש ליצירת התמונה.
  • condition image (אופציונלי): התמונה שמשמשת את המודל לצורכי יצירה. רלוונטי רק כשמשתמשים במודל פלאגין.
  • condition type (אופציונלי): הסוג של מודל הפלאגין ששימש לביצוע המשימה. רלוונטי רק כשמשתמשים במודל פלאגין.

שיטות קלט עם מודל הבסיס בלבד

fun setInput(prompt: String, iteration: Int, seed: Int) {
    imageGenerator.setInputs(prompt, iteration, seed)
}

קלט עם יישומי פלאגין

אם מחילים מודל פלאגין אופציונלי, צריך להשתמש גם בפרמטר conditionType כדי לבחור את מודל הפלאגין ובפרמטר sourceConditionImage כדי ליצור את תמונת התנאי.

שם האפשרות תיאור ערך
conditionType מודל הפלאגין שהוחל על מודל הבסיס. {"FACE", "EDGE", "DEPTH"}
sourceConditionImage תמונת המקור ששימשה ליצירת תמונת התנאי. אובייקט MPImage

אם אתם משתמשים במודל פלאגין, השתמשו ב-createConditionImage כדי ליצור את תמונת התנאי:

fun createConditionImage(
    inputImage: MPImage,
    conditionType: ConditionType
): Bitmap {
    val result =
        imageGenerator.createConditionImage(inputImage, conditionType)
    return BitmapExtractor.extract(result)
}

אחרי שיוצרים את תמונת התנאי, צריך לכלול בתוכה את הקלט כקלט עם הבקשה, המקור ומספר האיטרציות.

imageGenerator.setInputs(
    prompt,
    conditionalImage,
    conditionType,
    iteration,
    seed
)

קלט עם משקולות של LoRA

אם משתמשים במשקולות של LoRA, חשוב לוודא שהאסימון מופיע בשורת הטקסט אם אתם מתכוונים ליצור תמונה עם הקונספט הספציפי שמיוצג על ידי המשקולות.

fun setInput(prompt: String, iteration: Int, seed: Int) {
    imageGenerator.setInputs(prompt, iteration, seed)
}

מריצים את המשימה.

משתמשים בשיטה generate() כדי ליצור תמונה באמצעות מקורות הקלט שניתנו בקטע הקודם. כך נוצרת תמונה אחת.

יצירה באמצעות מודל הבסיס בלבד

fun generate(prompt: String, iteration: Int, seed: Int): Bitmap {
    val result = imageGenerator.generate(prompt, iteration, seed)
    val bitmap = BitmapExtractor.extract(result?.generatedImage())
    return bitmap
}

יצירה באמצעות יישומי פלאגין

fun generate(
    prompt: String,
    inputImage: MPImage,
    conditionType: ConditionType,
    iteration: Int,
    seed: Int
): Bitmap {
    val result = imageGenerator.generate(
        prompt,
        inputImage,
        conditionType,
        iteration,
        seed
    )
    val bitmap = BitmapExtractor.extract(result?.generatedImage())
    return bitmap
}

יצירה באמצעות משקולות של LoRA

התהליך של יצירת תמונות באמצעות מודל בהתאמה אישית עם משקולות LoRA דומה לתהליך של יצירת תמונות עם מודל בסיס סטנדרטי. חשוב לוודא שהאסימון כלול בהנחיה ולהריץ את אותו קוד.

fun generate(prompt: String, iteration: Int, seed: Int): Bitmap {
    val result = imageGenerator.generate(prompt, iteration, seed)
    val bitmap = BitmapExtractor.extract(result?.generatedImage())
    return bitmap
}

יצירה חוזרת

מחולל התמונות יכול גם להפיק פלט של תמונות הביניים שנוצרות במהלך כל איטרציה, כפי שמוגדר בפרמטר הקלט iterations. כדי להציג את תוצאות הביניים האלה, צריך לקרוא ל-method setInputs ואז לבצע קריאה ל-execute() כדי להריץ כל שלב. מגדירים את הפרמטר showResult לערך true על מנת להציג את תוצאות הביניים.

fun execute(showResult: Boolean): Bitmap {
    val result = imageGenerator.execute(showResult)

    val bitmap =
        BitmapExtractor.extract(result.generatedImage())

    return bitmap
}

טיפול בתוצאות והצגתן

מחולל התמונות יחזיר ImageGeneratorResult, שכולל את התמונה שנוצרה, חותמת זמן של מועד ההשלמה ואת התמונה המותנית אם סופקה כקלט.

val bitmap = BitmapExtractor.extract(result.generatedImage())

התמונה הבאה נוצרה על סמך מקורות הקלט הבאים, באמצעות מודל בסיס בלבד.

שיטות קלט:

  • הנחיה: "דביבון מצויר צבעוני חובש כובע עם שוליים רחבים מחזיק מקל הליכה ביער, אנימציה של תצוגת שלושת-רבעי, ציור"
  • מקור: 312687592
  • חזרות: 20

תמונה שנוצרה: