คู่มือการตรวจหาจุดสังเกตสำหรับใบหน้าสำหรับ Android

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

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

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

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

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

ดาวน์โหลดโค้ด

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

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

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

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

องค์ประกอบหลัก

ไฟล์ต่อไปนี้มีโค้ดที่จำเป็นสำหรับแอปพลิเคชันตัวอย่าง การทำเครื่องหมายใบหน้านี้

  • FaceLandmarkerHelper.kt - เริ่มใช้งานตัวทำเครื่องหมายของใบหน้า รวมถึงจัดการโมเดลและมอบสิทธิ์การเลือก
  • CameraFragment.kt - จัดการกล้องของอุปกรณ์และประมวลผลข้อมูลอินพุตรูปภาพและวิดีโอ
  • GalleryFragment.kt - โต้ตอบกับ OverlayView เพื่อแสดงรูปภาพหรือวิดีโอเอาต์พุต
  • OverlayView.kt - ใช้จอแสดงผลที่มี Mesh กับใบหน้าที่ตรวจพบ

ตั้งค่า

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

การอ้างอิง

งานจุดสังเกตสำหรับใบหน้าจะใช้คลัง com.google.mediapipe:tasks-vision เพิ่มทรัพยากร Dependency นี้ไปยังไฟล์ build.gradle ของแอป Android

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

รุ่น

งาน MediaPipe Face Marker ต้องใช้แพ็กเกจโมเดลที่ผ่านการฝึกแล้วซึ่งเข้ากันได้กับงานนี้ ดูข้อมูลเพิ่มเติมเกี่ยวกับโมเดลที่ฝึกแล้วที่พร้อมใช้งานสำหรับจุดสังเกตสำหรับใบหน้า ได้ที่ภาพรวมงานส่วนโมเดล

เลือกและดาวน์โหลดโมเดล แล้วจัดเก็บไว้ในไดเรกทอรีโปรเจ็กต์ของคุณ ดังนี้

<dev-project-root>/src/main/assets

ระบุเส้นทางของโมเดลภายในพารามิเตอร์ ModelAssetPath ในโค้ดตัวอย่าง โมเดลจะได้รับการกำหนดในไฟล์ FaceLandmarkerHelper.kt ดังนี้

baseOptionsBuilder.setModelAssetPath(MP_FACE_LANDMARKER_TASK)

สร้างงาน

งาน MediaPipe Face Marker จะใช้ฟังก์ชัน createFromOptions() เพื่อตั้งค่างาน ฟังก์ชัน createFromOptions() จะยอมรับค่าสำหรับตัวเลือกการกำหนดค่า ดูข้อมูลเพิ่มเติมเกี่ยวกับตัวเลือกการกำหนดค่าได้ที่ตัวเลือกการกำหนดค่า

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

รูปภาพ

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_FACE_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder = 
    FaceLandmarker.FaceLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinFaceDetectionConfidence(minFaceDetectionConfidence)
        .setMinTrackingConfidence(minFaceTrackingConfidence)
        .setMinFacePresenceConfidence(minFacePresenceConfidence)
        .setNumFaces(maxNumFaces)
        .setRunningMode(RunningMode.IMAGE)

val options = optionsBuilder.build()
FaceLandmarker = FaceLandmarker.createFromOptions(context, options)
    

วิดีโอ

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_FACE_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder = 
    FaceLandmarker.FaceLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinFaceDetectionConfidence(minFaceDetectionConfidence)
        .setMinTrackingConfidence(minFaceTrackingConfidence)
        .setMinFacePresenceConfidence(minFacePresenceConfidence)
        .setNumFaces(maxNumFaces)
        .setRunningMode(RunningMode.VIDEO)

val options = optionsBuilder.build()
FaceLandmarker = FaceLandmarker.createFromOptions(context, options)
    

สตรีมแบบสด

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_FACE_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder = 
    FaceLandmarker.FaceLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinFaceDetectionConfidence(minFaceDetectionConfidence)
        .setMinTrackingConfidence(minFaceTrackingConfidence)
        .setMinFacePresenceConfidence(minFacePresenceConfidence)
        .setNumFaces(maxNumFaces)
        .setResultListener(this::returnLivestreamResult)
        .setErrorListener(this::returnLivestreamError)
        .setRunningMode(RunningMode.LIVE_STREAM)

val options = optionsBuilder.build()
FaceLandmarker = FaceLandmarker.createFromOptions(context, options)
    

การใช้โค้ดตัวอย่างโปรแกรมจุดสังเกตสำหรับใบหน้าช่วยให้ผู้ใช้สลับโหมดการประมวลผลได้ วิธีนี้ทำให้โค้ดการสร้างงานซับซ้อนขึ้นและอาจไม่เหมาะกับกรณีการใช้งานของคุณ คุณดูโค้ดนี้ได้ในฟังก์ชัน setupFaceLandmarker() ในไฟล์ FaceLandmarkerHelper.kt

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

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

ชื่อตัวเลือก คำอธิบาย ช่วงของค่า ค่าเริ่มต้น
runningMode ตั้งค่าโหมดการทำงาน มี 3 โหมดดังนี้

IMAGE: โหมดสำหรับการป้อนข้อมูลรูปภาพเดียว

วิดีโอ: โหมดสำหรับเฟรมที่ถอดรหัสของวิดีโอ

LIVE_Stream: โหมดสำหรับสตรีมแบบสดของข้อมูลอินพุต เช่น จากกล้อง ในโหมดนี้ ต้องมีการเรียกใช้ resultsListener เพื่อตั้งค่า Listener เพื่อรับผลลัพธ์แบบไม่พร้อมกัน
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
numFaces จำนวนใบหน้าสูงสุดที่ FaceLandmarker ตรวจพบได้ ระบบจะใช้การทำให้เนียนก็ต่อเมื่อตั้งค่า num_faces เป็น 1 เท่านั้น Integer > 0 1
minFaceDetectionConfidence คะแนนความเชื่อมั่นขั้นต่ำสำหรับการตรวจจับใบหน้าจะถือว่าสำเร็จ Float [0.0,1.0] 0.5
minFacePresenceConfidence คะแนนความเชื่อมั่นขั้นต่ำของคะแนนการแสดงใบหน้าของใบหน้าในการตรวจจับจุดสังเกตของใบหน้า Float [0.0,1.0] 0.5
minTrackingConfidence คะแนนความเชื่อมั่นขั้นต่ำสำหรับการติดตามใบหน้าจึงจะถือว่าประสบความสำเร็จ Float [0.0,1.0] 0.5
outputFaceBlendshapes กำหนดว่าจะให้จุดสังเกตสำหรับใบหน้าแสดงรูปร่างการผสานใบหน้าหรือไม่ รูปร่างกลมกลืนของใบหน้าใช้ในการแสดงผลโมเดลใบหน้า 3 มิติ Boolean False
outputFacialTransformationMatrixes เลือกว่าจะให้ FaceLandmarker แสดงผลเมทริกซ์การเปลี่ยนแปลงใบหน้าหรือไม่ FaceLandmarker ใช้เมทริกซ์เพื่อเปลี่ยนจุดสังเกตของใบหน้าจากรูปแบบใบหน้า Canonical เป็นใบหน้าที่ตรวจพบ เพื่อให้ผู้ใช้ใส่เอฟเฟกต์กับจุดสังเกตที่ตรวจพบได้ Boolean False
resultListener ตั้งค่า Listener ผลลัพธ์ให้รับผลลัพธ์ของจุดสังเกตแบบไม่พร้อมกันเมื่อ FaceLandmarker อยู่ในโหมดสตรีมแบบสด ใช้ได้เมื่อตั้งค่าโหมดการทำงานเป็น LIVE_STREAM เท่านั้น ResultListener N/A
errorListener ตั้งค่า Listener ข้อผิดพลาดที่ไม่บังคับ ErrorListener N/A

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

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

โค้ดต่อไปนี้แสดงวิธีส่งต่อข้อมูลเพื่อการประมวลผล ตัวอย่างเหล่านี้มีรายละเอียดเกี่ยวกับวิธีจัดการข้อมูลจากรูปภาพ ไฟล์วิดีโอ และสตรีมวิดีโอสด

รูปภาพ

import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(image).build()
    

วิดีโอ

import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage

val argb8888Frame =
    if (frame.config == Bitmap.Config.ARGB_8888) frame
    else frame.copy(Bitmap.Config.ARGB_8888, false)

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(argb8888Frame).build()
    

สตรีมแบบสด

import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(rotatedBitmap).build()
    

ในโค้ดตัวอย่างโปรแกรมจุดสังเกตสำหรับใบหน้า ระบบจะจัดการการจัดเตรียมข้อมูลในไฟล์ FaceLandmarkerHelper.kt

เรียกใช้งาน

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

ตัวอย่างโค้ดต่อไปนี้แสดงตัวอย่างง่ายๆ ของวิธีเรียกใช้จุดสังเกตสำหรับใบหน้าในโหมดข้อมูลที่แตกต่างกัน

รูปภาพ

val result = FaceLandmarker.detect(mpImage)
    

วิดีโอ

val timestampMs = i * inferenceIntervalMs

FaceLandmarker.detectForVideo(mpImage, timestampMs)
    .let { detectionResult ->
        resultList.add(detectionResult)
    }
    

สตรีมแบบสด

val mpImage = BitmapImageBuilder(rotatedBitmap).build()
val frameTime = SystemClock.uptimeMillis()

FaceLandmarker.detectAsync(mpImage, frameTime)
    

โปรดทราบดังต่อไปนี้

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

ในโค้ดตัวอย่างโปรแกรมจุดสังเกตสำหรับใบหน้า จะมีการกำหนดฟังก์ชัน detect, detectForVideo และ detectAsync ไว้ในไฟล์ FaceLandmarkerHelper.kt

แฮนเดิลและแสดงผลลัพธ์

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

ตัวอย่างต่อไปนี้แสดงตัวอย่างข้อมูลเอาต์พุตจากงานนี้

FaceLandmarkerResult:
  face_landmarks:
    NormalizedLandmark #0:
      x: 0.5971359014511108
      y: 0.485361784696579
      z: -0.038440968841314316
    NormalizedLandmark #1:
      x: 0.3302789330482483
      y: 0.29289937019348145
      z: -0.09489090740680695
    ... (478 landmarks for each face)
  face_blendshapes:
    browDownLeft: 0.8296722769737244
    browDownRight: 0.8096957206726074
    browInnerUp: 0.00035583582939580083
    browOuterUpLeft: 0.00035752105759456754
    ... (52 blendshapes for each face)
  facial_transformation_matrixes:
    [9.99158978e-01, -1.23036895e-02, 3.91213447e-02, -3.70770246e-01]
    [1.66496094e-02,  9.93480563e-01, -1.12779640e-01, 2.27719707e+01]
    ...

รูปภาพต่อไปนี้แสดงภาพเอาต์พุตของงาน

โค้ดตัวอย่างโปรแกรมจุดสังเกตสำหรับใบหน้าสาธิตวิธีแสดงผลลัพธ์ที่ได้จากงาน ดูรายละเอียดเพิ่มเติมได้ที่ชั้นเรียน OverlayView