การสร้างรูปภาพในอุปกรณ์บน Android ด้วย MediaPipe

1. บทนำ

MediaPipe คืออะไร

โซลูชัน MediaPipe ช่วยให้คุณใช้โซลูชันแมชชีนเลิร์นนิง (ML) กับแอปได้ ซึ่งให้บริการเฟรมเวิร์กสำหรับการกําหนดค่าไปป์ไลน์การประมวลผลที่สร้างไว้ล่วงหน้าซึ่งให้เอาต์พุตที่ดึงดูดใจและมีประโยชน์แก่ผู้ใช้ได้ทันที คุณยังปรับแต่งโซลูชันเหล่านี้ได้หลายรายการด้วย MediaPipe Model Maker เพื่ออัปเดตโมเดลเริ่มต้น

การสร้างข้อความเป็นรูปภาพเป็นหนึ่งในงาน ML หลายอย่างที่โซลูชัน MediaPipe มีให้บริการ

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

สิ่งที่คุณจะได้เรียนรู้

  • วิธีใช้การสร้างจากข้อความเป็นรูปภาพที่ทำงานแบบภายในในแอป Android ด้วย MediaPipe Tasks

สิ่งที่คุณต้องมี

  • Android Studio เวอร์ชันที่ติดตั้งไว้ (โค้ดแล็บนี้เขียนและทดสอบด้วย Android Studio Giraffe)
  • อุปกรณ์ Android ที่มี RAM อย่างน้อย 8 GB
  • ความรู้พื้นฐานเกี่ยวกับการพัฒนา Android และความสามารถในการเรียกใช้สคริปต์ Python ที่เขียนไว้ล่วงหน้า

2. เพิ่ม MediaPipe Tasks ลงในแอป Android

ดาวน์โหลดแอปเริ่มต้นสำหรับ Android

Codelab นี้จะเริ่มต้นด้วยตัวอย่างที่สร้างไว้ล่วงหน้า ซึ่งประกอบด้วย UI ที่จะใช้สําหรับการสร้างรูปภาพเวอร์ชันพื้นฐาน คุณดูแอปเริ่มต้นได้ในที่เก็บตัวอย่าง MediaPipe อย่างเป็นทางการที่นี่ โคลนที่เก็บหรือดาวน์โหลดไฟล์ ZIP โดยคลิกโค้ด > ดาวน์โหลด ZIP

นําเข้าแอปไปยัง Android Studio

  1. เปิด Android Studio
  2. จากหน้าจอยินดีต้อนรับสู่ Android Studio ให้เลือกเปิดที่มุมขวาบน

a0b5b070b802e4ea.png

  1. ไปที่ตำแหน่งที่คุณโคลนหรือดาวน์โหลดที่เก็บและเปิดไดเรกทอรี codelabs/image_generation_basic/android/start
  2. ในขั้นตอนนี้ แอปไม่ควรคอมไพล์เนื่องจากคุณยังไม่ได้รวมข้อกําหนดของ MediaPipe Tasks

คุณจะแก้ไขแอปและทำให้แอปทำงานได้โดยไปที่ไฟล์ build.gradle แล้วเลื่อนลงไปที่ // ขั้นตอนที่ 1 - เพิ่ม Dependency จากตรงนั้น ให้ใส่บรรทัดต่อไปนี้ แล้วกดปุ่มซิงค์เลยที่ปรากฏในแบนเนอร์ที่ด้านบนของ Android Studio

// Step 1 - Add dependency
implementation 'com.google.mediapipe:tasks-vision-image-generator:latest.release'

เมื่อซิงค์เสร็จแล้ว ให้ตรวจสอบว่าทุกอย่างเปิดและติดตั้งอย่างถูกต้องโดยคลิกลูกศรเรียกใช้สีเขียว ( 7e15a9c9e1620fe7.png) ที่ด้านขวาบนของ Android Studio คุณควรเห็นแอปเปิดขึ้นสู่หน้าจอที่มีปุ่มตัวเลือก 2 ปุ่มและปุ่มที่มีป้ายกำกับว่าเริ่มต้น เมื่อคลิกปุ่มดังกล่าว ระบบจะนําคุณไปยัง UI แยกต่างหากทันที ซึ่งประกอบด้วยพรอมต์ข้อความและตัวเลือกอื่นๆ ข้างปุ่มที่ระบุว่าสร้าง

83c31de8e8a320ee.png 78b8765e832024e3.png

ขออภัย นี่เป็นแอปเริ่มต้นที่ใหญ่ที่สุดแล้ว ตอนนี้ถึงเวลาที่คุณจะได้เรียนรู้วิธีทำให้แอปนี้เสร็จสมบูรณ์และเริ่มสร้างรูปภาพใหม่ในอุปกรณ์

3. การตั้งค่าเครื่องมือสร้างรูปภาพ

ในตัวอย่างนี้ การสร้างรูปภาพส่วนใหญ่จะเกิดขึ้นในไฟล์ ImageGenerationHelper.kt เมื่อเปิดไฟล์นี้ คุณจะเห็นตัวแปรที่ด้านบนของคลาสชื่อ imageGenerator นี่คือออบเจ็กต์งานที่จะทํางานหนักในแอปการสร้างรูปภาพ

ใต้ออบเจ็กต์ดังกล่าว คุณจะเห็นฟังก์ชันชื่อ initializeImageGenerator() พร้อมความคิดเห็นต่อไปนี้ // ขั้นตอนที่ 2 - เริ่มต้นสร้างภาพ ดังที่คุณอาจเดาได้ นี่คือจุดที่คุณจะต้องเริ่มต้นออบเจ็กต์ ImageGenerator แทนที่เนื้อหาฟังก์ชันนั้นด้วยโค้ดต่อไปนี้เพื่อตั้งค่าเส้นทางโมเดลการสร้างรูปภาพและเริ่มต้นออบเจ็กต์ ImageGenerator

// Step 2 - initialize the image generator
val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

imageGenerator = ImageGenerator.createFromOptions(context, options)

ด้านล่างนั้น คุณจะเห็นฟังก์ชันอื่นชื่อ setInput() ซึ่งรับพารามิเตอร์ 3 รายการ ได้แก่ สตริงพรอมต์ที่จะใช้กำหนดรูปภาพที่สร้างขึ้น จำนวนการทำซ้ำที่งานควรทำขณะสร้างรูปภาพใหม่ และค่าเมล็ดพันธุ์ที่ใช้สร้างรูปภาพเวอร์ชันใหม่โดยอิงตามพรอมต์เดียวกันขณะสร้างรูปภาพเดียวกันเมื่อใช้เมล็ดพันธุ์เดียวกัน ฟังก์ชันนี้มีไว้เพื่อตั้งค่าพารามิเตอร์เริ่มต้นเหล่านี้สำหรับเครื่องมือสร้างรูปภาพเมื่อคุณพยายามสร้างรูปภาพที่แสดงขั้นตอนกลาง

แทนที่เนื้อหา setInput() (ที่คุณจะเห็นความคิดเห็น // ขั้นตอนที่ 3 - รับอินพุต) ด้วยบรรทัดนี้

// Step 3 - accept inputs
imageGenerator.setInputs(prompt, iteration, seed)

2 ขั้นตอนถัดไปคือขั้นตอนการสร้าง ฟังก์ชัน generate() จะรับอินพุตเดียวกับ setInput แต่สร้างรูปภาพด้วยการเรียกใช้แบบครั้งเดียวที่จะไม่แสดงผลรูปภาพขั้นตอนกลาง คุณสามารถแทนที่เนื้อหาของฟังก์ชันนี้ (ซึ่งมีความคิดเห็น // ขั้นตอนที่ 4 - สร้างโดยไม่แสดงการทำซ้ำ) ด้วยข้อมูลต่อไปนี้

// Step 4 - generate without showing iterations
val result = imageGenerator.generate(prompt, iteration, seed)
val bitmap = BitmapExtractor.extract(result?.generatedImage())
return bitmap

สิ่งสำคัญที่ควรทราบคืองานนี้จะทํางานพร้อมกัน คุณจึงต้องเรียกใช้ฟังก์ชันจากเธรดเบื้องหลัง คุณจะได้ดูข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ใน Codelab นี้ในภายหลัง

ขั้นตอนสุดท้ายที่คุณจะทำในไฟล์นี้คือกรอกข้อมูลในฟังก์ชัน execute() (ติดป้ายกำกับไว้ว่าขั้นตอนที่ 5) ซึ่งจะยอมรับพารามิเตอร์ที่บอกให้ทราบว่าควรแสดงรูปภาพขั้นกลางหรือไม่สำหรับการสร้างขั้นตอนเดียวที่จะดำเนินการกับฟังก์ชัน execute() ของ ImageGenerator แทนที่เนื้อหาของฟังก์ชันด้วยโค้ดนี้

// Step 5 - generate with iterations
val result = imageGenerator.execute(showResult)

if (result == null || result.generatedImage() == null) {
    return Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888)
        .apply {
            val canvas = Canvas(this)
            val paint = Paint()
            paint.color = Color.WHITE
            canvas.drawPaint(paint)
        }
}

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

return bitmap

เท่านี้สำหรับไฟล์ Helper ในส่วนถัดไป คุณจะกรอกข้อมูลในไฟล์ ViewModel ที่จัดการตรรกะสําหรับตัวอย่างนี้

4. การรวมแอปเข้าด้วยกัน

ไฟล์ MainViewModel จะจัดการสถานะ UI และตรรกะอื่นๆ ที่เกี่ยวข้องกับแอปตัวอย่างนี้ ไปเปิดเลย

คุณควรเห็นความคิดเห็น // ขั้นตอนที่ 6 - ตั้งค่าเส้นทางโมเดลที่ด้านบนของไฟล์ ในส่วนนี้คุณจะบอกแอปว่าจะค้นหาไฟล์โมเดลที่จำเป็นต่อการสร้างรูปภาพได้จากที่ใด ในตัวอย่างนี้ คุณจะต้องตั้งค่าเป็น /data/local/tmp/image_generator/bins/

// Step 6 - set model path
private val MODEL_PATH = "/data/local/tmp/image_generator/bins/"

จากนั้นเลื่อนลงไปที่ฟังก์ชัน generateImage() คุณจะดูทั้งขั้นตอนที่ 7 และ 8 ได้ที่ด้านล่างของฟังก์ชันนี้ ซึ่งจะใช้ในการสร้างรูปภาพที่มีการทำซ้ำที่แสดงผลหรือไม่แสดงผลตามลำดับ เนื่องจากการดำเนินการทั้ง 2 รายการนี้เกิดขึ้นพร้อมกัน คุณจึงจะเห็นการดำเนินการดังกล่าวรวมอยู่ใน coroutine คุณอาจเริ่มต้นด้วยการแทนที่ // ขั้นตอนที่ 7 - สร้างโดยไม่แสดงการวนซ้ำด้วยบล็อกโค้ดนี้เพื่อเรียกใช้ generate() จากไฟล์ ImageGenerationHelper จากนั้นอัปเดตสถานะ UI

// Step 7 - Generate without showing iterations
val result = helper?.generate(prompt, iteration, seed)
_uiState.update {
    it.copy(outputBitmap = result)
}

ขั้นตอนที่ 8 จะยากขึ้นเล็กน้อย เนื่องจากฟังก์ชัน execute() จะดำเนินการเพียงขั้นตอนเดียวแทนที่จะทำทุกขั้นตอนในการสร้างรูปภาพ คุณจึงต้องเรียกใช้แต่ละขั้นตอนทีละขั้นตอนผ่านลูป นอกจากนี้ คุณจะต้องพิจารณาด้วยว่าควรแสดงขั้นตอนปัจจุบันต่อผู้ใช้หรือไม่ สุดท้าย คุณจะต้องอัปเดตสถานะ UI หากต้องการให้แสดงการวนซ้ำปัจจุบัน คุณทําสิ่งเหล่านี้ทั้งหมดได้แล้วตอนนี้

// Step 8 - Generate with showing iterations
helper?.setInput(prompt, iteration, seed)
for (step in 0 until iteration) {
    isDisplayStep =
        (displayIteration > 0 && ((step + 1) % displayIteration == 0))
    val result = helper?.execute(isDisplayStep)

    if (isDisplayStep) {
        _uiState.update {
            it.copy(
                outputBitmap = result,
                generatingMessage = "Generating... (${step + 1}/$iteration)",
            )
        }
    }
}

เมื่อถึงจุดนี้ คุณควรติดตั้งแอป เริ่มต้นเครื่องมือสร้างรูปภาพ แล้วสร้างรูปภาพใหม่ตามพรอมต์ข้อความได้

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

นอกจากการคัดลอกไฟล์ไปยังอุปกรณ์สำหรับพัฒนาโดยตรงแล้ว คุณยังตั้งค่า Firebase Storage ให้ดาวน์โหลดไฟล์ที่จำเป็นไปยังอุปกรณ์ของผู้ใช้โดยตรงได้ขณะรันไทม์

5. ทำให้แอปใช้งานได้และทดสอบ

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

  1. คลิก "เรียกใช้" (7e15a9c9e1620fe7.png) ในแถบเครื่องมือของ Android Studio เพื่อเรียกใช้แอป
  2. เลือกประเภทของขั้นตอนการสร้าง (ขั้นสุดท้ายหรือแบบซ้ำ) แล้วกดปุ่มเริ่มต้น
  3. ในหน้าจอถัดไป ให้ตั้งค่าพร็อพเพอร์ตี้ที่ต้องการ แล้วคลิกปุ่มสร้างเพื่อดูสิ่งที่เครื่องมือสร้างขึ้น

e46cfaeb9d3fc235.gif

6. ยินดีด้วย

สำเร็จแล้ว! ในโค้ดแล็บนี้ คุณได้เรียนรู้วิธีเพิ่มการสร้างจากข้อความเป็นรูปภาพในอุปกรณ์ลงในแอป Android

ขั้นตอนถัดไป

คุณทําสิ่งอื่นๆ อีกมากมายกับงานการสร้างรูปภาพได้ ดังนี้

  • โดยใช้รูปภาพฐานเพื่อจัดโครงสร้างรูปภาพที่สร้างขึ้นผ่านปลั๊กอิน หรือฝึกน้ำหนัก LoRA เพิ่มเติมของคุณเองผ่าน Vertex AI
  • ใช้ Firebase Storage เพื่อเรียกข้อมูลไฟล์โมเดลในอุปกรณ์โดยไม่ต้องใช้เครื่องมือ ADB

เราหวังว่าจะได้ดูผลงานเจ๋งๆ ทั้งหมดที่คุณสร้างจากภารกิจทดลองนี้ และโปรดคอยติดตามโค้ดแล็บและเนื้อหาอื่นๆ จากทีม MediaPipe