คู่มือการสร้างรูปภาพสำหรับ Android

งานเครื่องมือสร้างรูปภาพ MediaPipe ช่วยให้คุณสร้างรูปภาพตามพรอมต์ข้อความได้ งานนี้ใช้โมเดลเปลี่ยนข้อความเป็นรูปภาพเพื่อสร้างรูปภาพโดยใช้เทคนิคการแพร่กระจาย

งานจะยอมรับพรอมต์ข้อความเป็นอินพุต พร้อมกับรูปภาพเงื่อนไขที่ไม่บังคับซึ่งโมเดลสามารถเพิ่มและใช้เป็นข้อมูลอ้างอิงในการสร้าง นอกจากนี้ เครื่องสร้างรูปภาพยังสร้างรูปภาพตามแนวคิดที่เฉพาะเจาะจงซึ่งระบุให้กับโมเดลระหว่างการฝึกอบรมหรือการฝึกอบรมใหม่ได้ด้วย ดูข้อมูลเพิ่มเติมได้ที่ปรับแต่งด้วย LoRA

ตัวอย่างโค้ดที่อธิบายในวิธีการเหล่านี้มีอยู่ใน GitHub ดูข้อมูลเพิ่มเติมเกี่ยวกับความสามารถ รูปแบบ และตัวเลือกการกําหนดค่าของงานนี้ได้ที่ภาพรวม

ตัวอย่างโค้ด

โค้ดตัวอย่างของ MediaPipe Tasks คือการใช้งานพื้นฐานของแอป Image Generator สำหรับ Android คุณสามารถใช้แอปนี้เป็นจุดเริ่มต้นสําหรับแอป Android ของคุณเอง หรือใช้อ้างอิงเมื่อแก้ไขแอปที่มีอยู่ โค้ดตัวอย่างของตัวสร้างรูปภาพโฮสต์อยู่ใน GitHub

ดาวน์โหลดรหัส

วิธีการต่อไปนี้แสดงวิธีสร้างสำเนาโค้ดตัวอย่างในเครื่องโดยใช้เครื่องมือบรรทัดคำสั่ง git

วิธีดาวน์โหลดโค้ดตัวอย่าง

  1. โคลนที่เก็บ Git โดยใช้คำสั่งต่อไปนี้
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. (ไม่บังคับ) กำหนดค่าอินสแตนซ์ git ให้ใช้การตรวจสอบแบบเบาบางเพื่อให้คุณมีไฟล์สำหรับแอปตัวอย่าง Image Generator เท่านั้น โดยทำดังนี้
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_generation/android
    

หลังจากสร้างโค้ดตัวอย่างเวอร์ชันในเครื่องแล้ว คุณสามารถนําเข้าโปรเจ็กต์ไปยัง Android Studio และเรียกใช้แอปได้ ดูวิธีการได้ที่คู่มือการตั้งค่าสําหรับ Android

คอมโพเนนต์หลัก

ไฟล์ต่อไปนี้มีโค้ดสําคัญสําหรับตัวอย่างการสร้างรูปภาพนี้ แอปพลิเคชัน

  • ImageGenerationHelper.kt: เริ่มต้นงานและจัดการการสร้างรูปภาพ
  • DiffusionActivity.kt: สร้างรูปภาพเมื่อไม่ได้เปิดใช้ปลั๊กอินหรือน้ำหนัก LoRA
  • PluginActivity.kt: ใช้โมเดลปลั๊กอิน ซึ่งช่วยให้ผู้ใช้ระบุเงื่อนไขภาพเป็นอินพุตได้
  • LoRAWeightActivity.kt: เข้าถึงและจัดการน้ำหนัก LoRA ซึ่งใช้ในการปรับแต่งโมเดลพื้นฐานและช่วยให้โมเดลสร้างรูปภาพของแนวคิดที่เฉพาะเจาะจงได้

ตั้งค่า

ส่วนนี้จะอธิบายขั้นตอนสำคัญในการตั้งค่าสภาพแวดล้อมการพัฒนาและโปรเจ็กต์โค้ดเพื่อใช้ Image Generator โดยเฉพาะ ดูข้อมูลทั่วไปเกี่ยวกับการตั้งค่าสภาพแวดล้อมการพัฒนาเพื่อใช้งาน MediaPipe รวมถึงข้อกำหนดเวอร์ชันแพลตฟอร์มได้ที่คู่มือการตั้งค่าสำหรับ Android

การอ้างอิง

งาน Image Generator ใช้ไลบรารี com.google.mediapipe:tasks-vision-image-generator เพิ่ม Dependency นี้ลงในไฟล์ build.gradle ของแอป Android

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

สำหรับอุปกรณ์ที่ใช้ Android 12 (API 31) ขึ้นไป ให้เพิ่มข้อกำหนดของไลบรารี OpenCL เดิม ดูข้อมูลเพิ่มเติมได้ที่เอกสารประกอบเกี่ยวกับแท็ก uses-native-library

เพิ่มแท็ก uses-native-library ต่อไปนี้ลงในไฟล์ AndroidManifest.xml

<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 Image Generator ใช้ฟังก์ชัน createFromOptions() เพื่อตั้งค่างาน ฟังก์ชัน createFromOptions() ยอมรับค่าสำหรับตัวเลือกการกําหนดค่า ดูข้อมูลเพิ่มเติมเกี่ยวกับตัวเลือกการกำหนดค่าได้ที่ตัวเลือกการกำหนดค่า

ตัวเลือกการกำหนดค่า

งานนี้มีตัวเลือกการกำหนดค่าต่อไปนี้สำหรับแอป Android

ชื่อตัวเลือก คำอธิบาย ช่วงของค่า
imageGeneratorModelDirectory ไดเรกทอรีโมเดลเครื่องมือสร้างรูปภาพที่จัดเก็บน้ำหนักโมเดล PATH
loraWeightsFilePath กำหนดเส้นทางไปยังไฟล์น้ำหนัก LoRA ไม่บังคับและใช้ได้เฉพาะในกรณีที่มีการปรับแต่งรุ่นด้วย LoRA PATH
errorListener ตั้งค่าโปรแกรมรับฟังข้อผิดพลาด (ไม่บังคับ) N/A

งานยังรองรับโมเดลปลั๊กอิน ซึ่งช่วยให้ผู้ใช้ใส่รูปภาพเงื่อนไขในอินพุตงานได้ ซึ่งโมเดลพื้นฐานจะเพิ่มและใช้เป็นข้อมูลอ้างอิงในการสร้าง รูปภาพที่มีเงื่อนไขเหล่านี้อาจเป็นจุดสังเกตบนใบหน้า ขอบของรูปภาพ และค่าประมาณความลึก ซึ่งโมเดลจะใช้เป็นบริบทและข้อมูลเพิ่มเติมในการสร้างรูปภาพ

เมื่อเพิ่มรูปแบบปลั๊กอินลงในรูปแบบพื้นฐาน ให้กําหนดค่าตัวเลือกปลั๊กอินด้วย ปลั๊กอินจุดสังเกตใบหน้าใช้ faceConditionOptions, ปลั๊กอินขอบ Canny ใช้ edgeConditionOptions และปลั๊กอินความลึกใช้ depthConditionOptions

ตัวเลือกขอบ Canny

กําหนดค่าตัวเลือกต่อไปนี้ใน edgeConditionOptions

ชื่อตัวเลือก คำอธิบาย ช่วงของค่า ค่าเริ่มต้น
threshold1 เกณฑ์แรกสำหรับกระบวนการฮิสเทรีซิส Float 100
threshold2 เกณฑ์ที่ 2 สำหรับกระบวนการฮิสเทรีซิส Float 200
apertureSize ขนาดรูรับแสงสําหรับโอเปอเรเตอร์ Sobel ช่วงทั่วไปอยู่ระหว่าง 3-7 Integer 3
l2Gradient ระบุว่าจะใช้ค่า L2 ในการคำนวณขนาดของเส้นลาดของรูปภาพแทนค่า L1 เริ่มต้นหรือไม่ BOOLEAN False
EdgePluginModelBaseOptions ออบเจ็กต์ BaseOptions ที่ตั้งค่าเส้นทางสําหรับโมเดลปลั๊กอิน วัตถุ BaseOptions รายการ N/A

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของตัวเลือกการกําหนดค่าเหล่านี้ได้ที่หัวข้อCanny Edge Detector

ตัวเลือกจุดสังเกตของใบหน้า

กําหนดค่าตัวเลือกต่อไปนี้ใน 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

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของตัวเลือกการกําหนดค่าเหล่านี้ได้ที่หัวข้องานเครื่องหมายจุดสังเกตใบหน้า

ตัวเลือกความลึก

กําหนดค่าตัวเลือกต่อไปนี้ใน 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)

เตรียมข้อมูล

เครื่องมือสร้างรูปภาพยอมรับอินพุตต่อไปนี้

  • prompt (ต้องระบุ): พรอมต์ข้อความที่อธิบายรูปภาพที่จะสร้าง
  • 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 หากต้องการดูผลลัพธ์ขั้นกลางเหล่านี้ ให้เรียกใช้เมธอด 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())

รูปภาพต่อไปนี้สร้างขึ้นจากอินพุตต่อไปนี้โดยใช้เฉพาะโมเดลพื้นฐาน

อินพุต:

  • พรอมต์: "แรคคูนการ์ตูนสีสันสดใสสวมหมวกปีกกว้างแบบย้วยๆ ถือไม้เดินผ่านป่า ภาพเคลื่อนไหว มุมมอง 3 ส่วน 4 ส่วน ภาพวาด"
  • Seed: 312687592
  • จำนวนรอบ: 20

รูปภาพที่สร้างขึ้น: